diff --git a/.circleci/config.yml b/.circleci/config.yml index cffba354..97666303 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -11,14 +11,13 @@ jobs: resource_class: large steps: - go/install: - version: "1.20" + version: "1.21.4" - checkout - run: name: Print Go environment command: "go env" - go/load-cache: key: go-mod-v6-{{ checksum "go.sum" }} - - add_ssh_keys - go/mod-download - go/save-cache: key: go-mod-v6-{{ checksum "go.sum" }} @@ -29,8 +28,8 @@ jobs: - run: name: Lint command: | - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s v1.52.2 - ./bin/golangci-lint run + curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s v1.55.2 + ./bin/golangci-lint run --timeout 5m0s - run: name: Run tests command: | @@ -46,7 +45,6 @@ jobs: resource_class: large steps: - checkout - - add_ssh_keys - aws-ecr/build-image: push-image: false dockerfile: Dockerfile @@ -54,15 +52,14 @@ jobs: build-path: ./ tag: "$CIRCLE_SHA1,$CIRCLE_TAG" repo: "$CIRCLE_PROJECT_REPONAME" - extra-build-args: "--secret id=sshKey,src=/home/circleci/.ssh/$DEPLOY_KEY_NAME" - run: name: Save Docker image to export it to workspace command: | - docker save $(docker image ls --format '{{.Repository}}:{{.Tag}}') > /tmp/btcvalidator.tar + docker save $(docker image ls --format '{{.Repository}}:{{.Tag}}') > /tmp/finality-provider.tar - persist_to_workspace: root: /tmp paths: - - btcvalidator.tar + - finality-provider.tar push_docker: machine: @@ -74,7 +71,7 @@ jobs: - run: name: Load Docker image from workspace command: | - docker load -i /tmp/btcvalidator.tar + docker load -i /tmp/finality-provider.tar - aws-ecr/ecr-login: aws-access-key-id: AWS_ACCESS_KEY_ID aws-secret-access-key: AWS_SECRET_ACCESS_KEY diff --git a/Dockerfile b/Dockerfile index 1d5fceb8..dd5a7b21 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.20.5-alpine as builder +FROM golang:1.21.4-alpine as builder # Version to build. Default is the Git HEAD. ARG VERSION="HEAD" @@ -12,17 +12,13 @@ RUN apk add --no-cache --update openssh git make build-base linux-headers libc-d libzmq-static libsodium-static gcc -RUN mkdir -p /root/.ssh && ssh-keyscan github.com >> /root/.ssh/known_hosts -RUN git config --global url."git@github.com:".insteadOf "https://github.com/" -ENV GOPRIVATE=github.com/babylonchain/babylon-private - # Build -WORKDIR /go/src/github.com/babylonchain/btc-validator +WORKDIR /go/src/github.com/babylonchain/finality-provider # Cache dependencies -COPY go.mod go.sum /go/src/github.com/babylonchain/btc-validator/ -RUN --mount=type=secret,id=sshKey,target=/root/.ssh/id_rsa go mod download +COPY go.mod go.sum /go/src/github.com/babylonchain/finality-provider/ +RUN go mod download # Copy the rest of the files -COPY ./ /go/src/github.com/babylonchain/btc-validator/ +COPY ./ /go/src/github.com/babylonchain/finality-provider/ # Cosmwasm - Download correct libwasmvm version RUN WASMVM_VERSION=$(go list -m github.com/CosmWasm/wasmvm | cut -d ' ' -f 2) && \ @@ -41,17 +37,14 @@ RUN CGO_LDFLAGS="$CGO_LDFLAGS -lstdc++ -lm -lsodium" \ # FINAL IMAGE FROM alpine:3.16 AS run -RUN addgroup --gid 1138 -S btcvalidator && adduser --uid 1138 -S btcvalidator -G btcvalidator +RUN addgroup --gid 1138 -S finality-provider && adduser --uid 1138 -S finality-provider -G finality-provider RUN apk add bash curl jq -COPY --from=builder /go/src/github.com/babylonchain/btc-validator/build/vald /bin/vald -COPY --from=builder /go/src/github.com/babylonchain/btc-validator/build/valcli /bin/valcli - -WORKDIR /home/btcvalidator -RUN chown -R btcvalidator /home/btcvalidator -USER btcvalidator +COPY --from=builder /go/src/github.com/babylonchain/finality-provider/build/fpd /bin/fpd +COPY --from=builder /go/src/github.com/babylonchain/finality-provider/build/fpcli /bin/fpcli +COPY --from=builder /go/src/github.com/babylonchain/finality-provider/build/eotsd /bin/eotsd -ENTRYPOINT ["/bin/vald"] -CMD [] -STOPSIGNAL SIGTERM +WORKDIR /home/finality-provider +RUN chown -R finality-provider /home/finality-provider +USER finality-provider diff --git a/LICENSE b/LICENSE index 261eeb9e..4bda301c 100644 --- a/LICENSE +++ b/LICENSE @@ -1,201 +1,99 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. +Business Source License 1.1 + +License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved. +"Business Source License" is a trademark of MariaDB Corporation Ab. + + +----------------------------------------------------------------------------- + +Parameters + +Licensor: Babylonchain, Inc. + +Licensed Work: finality-provider + The Licensed Work is (c) 2023 Babylonchain, Inc. + +Additional Use Grant: None. + +Change Date: 2027-01-20 (January 20th, 2027] + +Change License: Apache 2.0 + +----------------------------------------------------------------------------- + +Terms + +The Licensor hereby grants you the right to copy, modify, create derivative +works, redistribute, and make non-production use of the Licensed Work. The +Licensor may make an Additional Use Grant, above, permitting limited +production use. + +Effective on the Change Date, or the fourth anniversary of the first publicly +available distribution of a specific version of the Licensed Work under this +License, whichever comes first, the Licensor hereby grants you rights under +the terms of the Change License, and the rights granted in the paragraph +above terminate. + +If your use of the Licensed Work does not comply with the requirements +currently in effect as described in this License, you must purchase a +commercial license from the Licensor, its affiliated entities, or authorized +resellers, or you must refrain from using the Licensed Work. + +All copies of the original and modified Licensed Work, and derivative works +of the Licensed Work, are subject to this License. This License applies +separately for each version of the Licensed Work and the Change Date may vary +for each version of the Licensed Work released by Licensor. + +You must conspicuously display this License on each original or modified copy +of the Licensed Work. If you receive the Licensed Work in original or +modified form from a third party, the terms and conditions set forth in this +License apply to your use of that work. + +Any use of the Licensed Work in violation of this License will automatically +terminate your rights under this License for the current and all other +versions of the Licensed Work. + +This License does not grant you any right in any trademark or logo of +Licensor or its affiliates (provided that you may use a trademark or logo of +Licensor as expressly required by this License). + +TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON +AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, +EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND +TITLE. + +MariaDB hereby grants you permission to use this License’s text to license +your works, and to refer to it using the trademark "Business Source License", +as long as you comply with the Covenants of Licensor below. + +----------------------------------------------------------------------------- + +Covenants of Licensor + +In consideration of the right to use this License’s text and the "Business +Source License" name and trademark, Licensor covenants to MariaDB, and to all +other recipients of the licensed work to be provided by Licensor: + +1. To specify as the Change License the GPL Version 2.0 or any later version, + or a license that is compatible with GPL Version 2.0 or a later version, + where "compatible" means that software provided under the Change License can + be included in a program with software provided under GPL Version 2.0 or a + later version. Licensor may specify additional Change Licenses without + limitation. + +2. To either: (a) specify an additional grant of rights to use that does not + impose any additional restriction on the right granted in this License, as + the Additional Use Grant; or (b) insert the text "None". + +3. To specify a Change Date. + +4. Not to modify this License in any other way. + +----------------------------------------------------------------------------- + +Notice + +The Business Source License (this document, or the "License") is not an Open +Source license. However, the Licensed Work will eventually be made available +under an Open Source License, as stated in this License. diff --git a/Makefile b/Makefile index c89cb271..857a26a5 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,6 @@ BUILDDIR ?= $(CURDIR)/build TOOLS_DIR := tools -BTCD_PKG := github.com/btcsuite/btcd BABYLON_PKG := github.com/babylonchain/babylon/cmd/babylond GO_BIN := ${GOPATH}/bin @@ -35,26 +34,23 @@ all: build install build: BUILD_ARGS := $(build_args) -o $(BUILDDIR) -clean: - rm -rf $(BUILDDIR) - $(BUILD_TARGETS): go.sum $(BUILDDIR)/ - go $@ -mod=readonly $(BUILD_FLAGS) $(BUILD_ARGS) ./... + CGO_CFLAGS="-O -D__BLST_PORTABLE__" go $@ -mod=readonly $(BUILD_FLAGS) $(BUILD_ARGS) ./... $(BUILDDIR)/: mkdir -p $(BUILDDIR)/ build-docker: - $(DOCKER) build --secret id=sshKey,src=${BBN_PRIV_DEPLOY_KEY} --tag babylonchain/btc-validator -f Dockerfile \ + $(DOCKER) build --tag babylonchain/finality-provider -f Dockerfile \ $(shell git rev-parse --show-toplevel) -.PHONY: build build-docker clean +.PHONY: build build-docker test: go test ./... test-e2e: - go install -trimpath $(BABYLON_PKG) + cd $(TOOLS_DIR); go install -trimpath $(BABYLON_PKG) go test -mod=readonly -timeout=25m -v $(PACKAGES_E2E) -count=1 --tags=e2e ############################################################################### @@ -64,7 +60,8 @@ test-e2e: proto-all: proto-gen proto-gen: - ./proto/scripts/protocgen.sh + make -C eotsmanager proto-gen + make -C finality-provider proto-gen .PHONY: proto-gen diff --git a/README.md b/README.md index 2017bb71..7fbdd11b 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,148 @@ -# BTC-Validator +# Finality Provider -BTC-Validator is a stand-alone program that creates and manages all BTC validators' keys and act on behalf of them. +A toolset crafted for the creation and +management of Finality Providers. + +## 1. Overview + +Finality providers are responsible for voting +at a finality round on top of [CometBFT](https://github.com/cometbft/cometbft). +Similar to any native PoS validator, +a finality provider can receive voting power delegations from BTC stakers, and +can earn commission from the staking rewards denominated in Babylon tokens. + +The finality provider toolset does not have +any special hardware requirements +and can operate on standard mid-sized machines +running a UNIX-flavored operating system. +It consists of the following programs: +- *Babylon full node*: An instance of a Babylon node connecting to + the Babylon network. Running one is not a strict requirement, + but it is recommended for security compared to trusting a third-party RPC node. +- *Extractable One-Time Signature (EOTS) manager*: + A daemon responsible for securely maintaining the finality provider’s + private key and producing extractable one time signatures from it. +- *Finality Provider*: A daemon managing the finality provider. + It connects to the EOTS manager to generate EOTS public randomness and + finality votes for Babylon blocks, which it submits to Babylon through + the node connection. + +The following graphic demonstrates the interconnections between the above programs: + +![Finality Provider Interconnections](./docs/finality-toolset.png) + + +## 2. Installation + +#### Prerequisites + +This project requires Go version 1.21 or later. + +Install Go by following the instructions on +the [official Go installation guide](https://golang.org/doc/install). + +#### Downloading the code + +To get started, clone the repository to your local machine from Github: + +```bash +git clone git@github.com:babylonchain/finality-provider.git +``` + +You can choose a specific version from +the [official releases page](https://github.com/babylonchain/finality-provider/releases) + +```bash +cd finality-provider # cd into the project directory +git checkout +``` + +#### Building and installing the binary + +At the top-level directory of the project + +```bash +make install +``` + +The above command will build and install the following binaries to +`$GOPATH/bin`: + +- `eotsd`: The daemon program for the EOTS manager. +- `fpd`: The daemon program for the finality-provider. +- `fpcli`: The CLI tool for interacting with the finality-provider daemon. + +If your shell cannot find the installed binaries, make sure `$GOPATH/bin` is in +the `$PATH` of your shell. Usually these commands will do the job + +```bash +export PATH=$HOME/go/bin:$PATH +echo 'export PATH=$HOME/go/bin:$PATH' >> ~/.profile +``` + +To build without installing, + +```bash +make build +``` + +The above command will put the built binaries in a build directory with the +following structure: +```bash +ls build + ├── eotsd + ├── fpcli + └── fpd +``` + +Another common issue with compiling is that some of the dependencies have +components written in C. If a C toolchain is absent, the Go compiler will throw +errors. (Most likely it will complain about undefined names/types.) Make sure a +C toolchain (for example, GCC or Clang) is available. On Ubuntu, this can be +installed by running + +```bash +sudo apt install build-essential +``` + +## 3. Setting up a finality provider + +#### 3.1. Setting up a Babylon Full Node + +Before setting up the finality provider toolset, +an operator must ensure a working connection with a Babylon full node. +It is highly recommended that operators run their own node to avoid +trusting third parties. Instructions on how to set up a full Babylon node +can be found in +[the Babylon documentation](https://docs.babylonchain.io/docs/user-guides/btc-timestamping-testnet/setup-node). + +The finality provider requires a Babylon keyring with loaded funds to be attached to it +in order to be able to send transactions to Babylon. +To setup such a keyring, follow the instructions in +[the Babylon documentation](https://docs.babylonchain.io/docs/user-guides/btc-timestamping-testnet/getting-funds). + +#### 3.2. Setting up the EOTS Manager + +After a node and a keyring have been set up, +the operator can set up and run the +Extractable One Time Signature (EOTS) manager daemon. +A complete overview of the EOTS manager, its operation, and +its configuration options can be found in the +[EOTS Manager page](docs/eots.md) + +#### 3.3. Setting up a Finality Provider + +The last step is to set up and run +the finality daemon. +A complete overview of the finality daemon, its operation, and +its configuration options can be found in the +[Finality page](docs/finality-provider.md). + +## 4. Delegations & Rewards + +A finality provider receives BTC delegations through delegators +interacting with Babylon and choosing it as the recipient of their delegations. +To perform a self-delegation, +the operator can either visit the staking web app we provide, +or run the Babylon [BTC Staker program](https://github.com/babylonchain/btc-staker) once. +The BTC staker connects to a Bitcoin wallet and Babylon to perform delegations. diff --git a/clientcontroller/babylon.go b/clientcontroller/babylon.go index 88843a61..77cf2e16 100644 --- a/clientcontroller/babylon.go +++ b/clientcontroller/babylon.go @@ -3,376 +3,212 @@ package clientcontroller import ( "context" "fmt" - "os" - "path" - "strings" - "sync" "time" - "github.com/avast/retry-go/v4" - bbnapp "github.com/babylonchain/babylon/app" + sdkErr "cosmossdk.io/errors" + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcutil" + + "cosmossdk.io/math" bbntypes "github.com/babylonchain/babylon/types" btcctypes "github.com/babylonchain/babylon/x/btccheckpoint/types" btclctypes "github.com/babylonchain/babylon/x/btclightclient/types" btcstakingtypes "github.com/babylonchain/babylon/x/btcstaking/types" finalitytypes "github.com/babylonchain/babylon/x/finality/types" - "github.com/btcsuite/btcd/btcutil" - ctypes "github.com/cometbft/cometbft/rpc/core/types" - sdkclient "github.com/cosmos/cosmos-sdk/client" + bbnclient "github.com/babylonchain/rpc-client/client" + "github.com/btcsuite/btcd/btcec/v2/schnorr" + "github.com/btcsuite/btcd/chaincfg" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" sdk "github.com/cosmos/cosmos-sdk/types" - sdkTypes "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/module" sdkquery "github.com/cosmos/cosmos-sdk/types/query" sttypes "github.com/cosmos/cosmos-sdk/x/staking/types" - "github.com/cosmos/relayer/v2/relayer/chains/cosmos" "github.com/cosmos/relayer/v2/relayer/provider" - pv "github.com/cosmos/relayer/v2/relayer/provider" - zaplogfmt "github.com/jsternberg/zap-logfmt" - "github.com/juju/fslock" - "github.com/sirupsen/logrus" "go.uber.org/zap" - "go.uber.org/zap/zapcore" - "golang.org/x/exp/maps" - "github.com/babylonchain/btc-validator/types" - "github.com/babylonchain/btc-validator/valcfg" + "github.com/babylonchain/finality-provider/config" + "github.com/babylonchain/finality-provider/types" ) var _ ClientController = &BabylonController{} -type BabylonController struct { - provider *cosmos.CosmosProvider - logger *logrus.Logger - timeout time.Duration -} - -func newRootLogger(format string, debug bool) (*zap.Logger, error) { - config := zap.NewProductionEncoderConfig() - config.EncodeTime = func(ts time.Time, encoder zapcore.PrimitiveArrayEncoder) { - encoder.AppendString(ts.UTC().Format("2006-01-02T15:04:05.000000Z07:00")) - } - config.LevelKey = "lvl" +var emptyErrs = []*sdkErr.Error{} - var enc zapcore.Encoder - switch format { - case "json": - enc = zapcore.NewJSONEncoder(config) - case "auto", "console": - enc = zapcore.NewConsoleEncoder(config) - case "logfmt": - enc = zaplogfmt.NewEncoder(config) - default: - return nil, fmt.Errorf("unrecognized log format %q", format) - } - - level := zap.InfoLevel - if debug { - level = zap.DebugLevel - } - return zap.New(zapcore.NewCore( - enc, - os.Stderr, - level, - )), nil +type BabylonController struct { + bbnClient *bbnclient.Client + cfg *config.BBNConfig + btcParams *chaincfg.Params + logger *zap.Logger } func NewBabylonController( - homedir string, - cfg *valcfg.BBNConfig, - logger *logrus.Logger, + cfg *config.BBNConfig, + btcParams *chaincfg.Params, + logger *zap.Logger, ) (*BabylonController, error) { - zapLogger, err := newRootLogger("console", true) - if err != nil { - return nil, err - } + bbnConfig := config.BBNConfigToBabylonConfig(cfg) - // HACK: replace the modules in public rpc-client to add BTC staking / finality modules - // so that it recognises their message formats - // TODO: fix this either by fixing rpc-client side - var moduleBasics []module.AppModuleBasic - for _, mbasic := range bbnapp.ModuleBasics { - moduleBasics = append(moduleBasics, mbasic) + if err := bbnConfig.Validate(); err != nil { + return nil, fmt.Errorf("invalid config for Babylon client: %w", err) } - cosmosConfig := valcfg.BBNConfigToCosmosProviderConfig(cfg) - - cosmosConfig.Modules = moduleBasics - - provider, err := cosmosConfig.NewProvider( - zapLogger, - homedir, - true, - "babylon", + bc, err := bbnclient.New( + &bbnConfig, + logger, ) - - if err != nil { - return nil, err - } - - cp := provider.(*cosmos.CosmosProvider) - - cp.PCfg.KeyDirectory = cfg.KeyDirectory - // Need to override this manually as otherwise oprion from config is ignored - cp.Cdc = cosmos.MakeCodec(moduleBasics, []string{}) - - err = cp.Init(context.Background()) - if err != nil { - return nil, err + return nil, fmt.Errorf("failed to create Babylon client: %w", err) } return &BabylonController{ - cp, + bc, + cfg, + btcParams, logger, - cfg.Timeout, }, nil } -func (bc *BabylonController) MustGetTxSigner() string { - address, err := bc.provider.Address() - if err != nil { - panic(err) - } - return address +func (bc *BabylonController) mustGetTxSigner() string { + signer := bc.GetKeyAddress() + prefix := bc.cfg.AccountPrefix + return sdk.MustBech32ifyAddressBytes(prefix, signer) } -func (bc *BabylonController) GetStakingParams() (*StakingParams, error) { - ctx, cancel := getContextWithCancel(bc.timeout) - defer cancel() +func (bc *BabylonController) GetKeyAddress() sdk.AccAddress { + // get key address, retrieves address based on key name which is configured in + // cfg *stakercfg.BBNConfig. If this fails, it means we have misconfiguration problem + // and we should panic. + // This is checked at the start of BabylonController, so if it fails something is really wrong - queryCkptClient := btcctypes.NewQueryClient(bc.provider) + keyRec, err := bc.bbnClient.GetKeyring().Key(bc.cfg.Key) - ckptQueryRequest := &btcctypes.QueryParamsRequest{} - ckptParamRes, err := queryCkptClient.Params(ctx, ckptQueryRequest) if err != nil { - return nil, fmt.Errorf("failed to query params of the btccheckpoint module: %v", err) + panic(fmt.Sprintf("Failed to get key address: %s", err)) } - queryStakingClient := btcstakingtypes.NewQueryClient(bc.provider) - stakingQueryRequest := &btcstakingtypes.QueryParamsRequest{} - stakingParamRes, err := queryStakingClient.Params(ctx, stakingQueryRequest) - if err != nil { - return nil, fmt.Errorf("failed to query staking params: %v", err) - } - juryPk, err := stakingParamRes.Params.JuryPk.ToBTCPK() + addr, err := keyRec.GetAddress() + if err != nil { - return nil, err + panic(fmt.Sprintf("Failed to get key address: %s", err)) } - return &StakingParams{ - ComfirmationTimeBlocks: ckptParamRes.Params.BtcConfirmationDepth, - FinalizationTimeoutBlocks: ckptParamRes.Params.CheckpointFinalizationTimeout, - MinSlashingTxFeeSat: btcutil.Amount(stakingParamRes.Params.MinSlashingTxFeeSat), - JuryPk: juryPk, - SlashingAddress: stakingParamRes.Params.SlashingAddress, - MinCommissionRate: stakingParamRes.Params.MinCommissionRate, - }, nil + return addr } -func (bc *BabylonController) reliablySendMsg(msg sdk.Msg) (*provider.RelayerTxResponse, error) { - return bc.reliablySendMsgs([]sdk.Msg{msg}) +func (bc *BabylonController) reliablySendMsg(msg sdk.Msg, expectedErrs []*sdkErr.Error, unrecoverableErrs []*sdkErr.Error) (*provider.RelayerTxResponse, error) { + return bc.reliablySendMsgs([]sdk.Msg{msg}, expectedErrs, unrecoverableErrs) } -func (bc *BabylonController) reliablySendMsgs(msgs []sdk.Msg) (*provider.RelayerTxResponse, error) { - var ( - rlyResp *provider.RelayerTxResponse - callbackErr error - wg sync.WaitGroup +func (bc *BabylonController) reliablySendMsgs(msgs []sdk.Msg, expectedErrs []*sdkErr.Error, unrecoverableErrs []*sdkErr.Error) (*provider.RelayerTxResponse, error) { + return bc.bbnClient.ReliablySendMsgs( + context.Background(), + msgs, + expectedErrs, + unrecoverableErrs, ) - - callback := func(rtr *provider.RelayerTxResponse, err error) { - rlyResp = rtr - callbackErr = err - wg.Done() - } - - wg.Add(1) - - // convert message type - relayerMsgs := []pv.RelayerMessage{} - for _, m := range msgs { - relayerMsg := cosmos.NewCosmosMessage(m, func(signer string) {}) - relayerMsgs = append(relayerMsgs, relayerMsg) - } - - ctx := context.Background() - if err := retry.Do(func() error { - var sendMsgErr error - krErr := bc.accessKeyWithLock(func() { - sendMsgErr = bc.provider.SendMessagesToMempool(ctx, relayerMsgs, "", ctx, []func(*provider.RelayerTxResponse, error){callback}) - }) - if krErr != nil { - bc.logger.WithFields(logrus.Fields{ - "error": krErr, - }).Error("unrecoverable err when submitting the tx, skip retrying") - return retry.Unrecoverable(krErr) - } - if sendMsgErr != nil { - sendMsgErr = ConvertErrType(sendMsgErr) - if IsUnrecoverable(sendMsgErr) { - bc.logger.WithFields(logrus.Fields{ - "error": sendMsgErr, - }).Error("unrecoverable err when submitting the tx, skip retrying") - return retry.Unrecoverable(sendMsgErr) - } - if IsExpected(sendMsgErr) { - // this is necessary because if err is returned - // the callback function will not be executed so - // that the inside wg.Done will not be executed - wg.Done() - bc.logger.WithFields(logrus.Fields{ - "error": sendMsgErr, - }).Error("expected err when submitting the tx, skip retrying") - return nil - } - return sendMsgErr - } - return nil - }, retry.Context(ctx), rtyAtt, rtyDel, rtyErr, retry.OnRetry(func(n uint, err error) { - bc.logger.WithFields(logrus.Fields{ - "attempt": n + 1, - "max_attempts": rtyAttNum, - "error": err, - }).Error() - })); err != nil { - return nil, err - } - - wg.Wait() - - if callbackErr != nil { - callbackErr = ConvertErrType(callbackErr) - if IsExpected(callbackErr) { - return nil, nil - } - return nil, callbackErr - } - - if rlyResp == nil { - // this case could happen if the error within the retry is an expected error - return nil, nil - } - - if rlyResp.Code != 0 { - return rlyResp, fmt.Errorf("transaction failed with code: %d", rlyResp.Code) - } - - return rlyResp, nil } -// RegisterValidator registers a BTC validator via a MsgCreateBTCValidator to Babylon +// RegisterFinalityProvider registers a finality provider via a MsgCreateFinalityProvider to Babylon // it returns tx hash and error -func (bc *BabylonController) RegisterValidator( - bbnPubKey *secp256k1.PubKey, - btcPubKey *bbntypes.BIP340PubKey, - pop *btcstakingtypes.ProofOfPossession, - commission *sdkTypes.Dec, - description *sttypes.Description, -) (*provider.RelayerTxResponse, error) { - - msg := &btcstakingtypes.MsgCreateBTCValidator{ - Signer: bc.MustGetTxSigner(), - BabylonPk: bbnPubKey, - BtcPk: btcPubKey, - Pop: pop, +func (bc *BabylonController) RegisterFinalityProvider( + chainPk []byte, + fpPk *btcec.PublicKey, + pop []byte, + commission *math.LegacyDec, + description []byte, +) (*types.TxResponse, error) { + var bbnPop btcstakingtypes.ProofOfPossession + if err := bbnPop.Unmarshal(pop); err != nil { + return nil, fmt.Errorf("invalid proof-of-possession: %w", err) + } + + var sdkDescription sttypes.Description + if err := sdkDescription.Unmarshal(description); err != nil { + return nil, fmt.Errorf("invalid description: %w", err) + } + + msg := &btcstakingtypes.MsgCreateFinalityProvider{ + Signer: bc.mustGetTxSigner(), + BabylonPk: &secp256k1.PubKey{Key: chainPk}, + BtcPk: bbntypes.NewBIP340PubKeyFromBTCPK(fpPk), + Pop: &bbnPop, Commission: commission, - Description: description, + Description: &sdkDescription, } - res, err := bc.reliablySendMsg(msg) + res, err := bc.reliablySendMsg(msg, emptyErrs, emptyErrs) if err != nil { return nil, err } - return res, nil + return &types.TxResponse{TxHash: res.TxHash, Events: res.Events}, nil } // CommitPubRandList commits a list of Schnorr public randomness via a MsgCommitPubRand to Babylon // it returns tx hash and error -func (bc *BabylonController) CommitPubRandList(btcPubKey *bbntypes.BIP340PubKey, startHeight uint64, pubRandList []bbntypes.SchnorrPubRand, sig *bbntypes.BIP340Signature) (*provider.RelayerTxResponse, error) { - msg := &finalitytypes.MsgCommitPubRandList{ - Signer: bc.MustGetTxSigner(), - ValBtcPk: btcPubKey, - StartHeight: startHeight, - PubRandList: pubRandList, - Sig: sig, - } - - res, err := bc.reliablySendMsg(msg) - if err != nil { - return nil, err +func (bc *BabylonController) CommitPubRandList( + fpPk *btcec.PublicKey, + startHeight uint64, + pubRandList []*btcec.FieldVal, + sig *schnorr.Signature, +) (*types.TxResponse, error) { + schnorrPubRandList := make([]bbntypes.SchnorrPubRand, 0, len(pubRandList)) + for _, r := range pubRandList { + schnorrPubRand := bbntypes.NewSchnorrPubRandFromFieldVal(r) + schnorrPubRandList = append(schnorrPubRandList, *schnorrPubRand) } - return res, nil -} + bip340Sig := bbntypes.NewBIP340SignatureFromBTCSig(sig) -// SubmitJurySig submits the Jury signature via a MsgAddJurySig to Babylon if the daemon runs in Jury mode -// it returns tx hash and error -func (bc *BabylonController) SubmitJurySig(btcPubKey *bbntypes.BIP340PubKey, delPubKey *bbntypes.BIP340PubKey, stakingTxHash string, sig *bbntypes.BIP340Signature) (*provider.RelayerTxResponse, error) { - msg := &btcstakingtypes.MsgAddJurySig{ - Signer: bc.MustGetTxSigner(), - ValPk: btcPubKey, - DelPk: delPubKey, - StakingTxHash: stakingTxHash, - Sig: sig, + msg := &finalitytypes.MsgCommitPubRandList{ + Signer: bc.mustGetTxSigner(), + FpBtcPk: bbntypes.NewBIP340PubKeyFromBTCPK(fpPk), + StartHeight: startHeight, + PubRandList: schnorrPubRandList, + Sig: bip340Sig, } - res, err := bc.reliablySendMsg(msg) - if err != nil { - return nil, err + unrecoverableErrs := []*sdkErr.Error{ + finalitytypes.ErrInvalidPubRand, + finalitytypes.ErrTooFewPubRand, + finalitytypes.ErrNoPubRandYet, + btcstakingtypes.ErrFpNotFound, } - return res, nil -} - -// SubmitJuryUnbondingSigs submits the Jury signatures via a MsgAddJuryUnbondingSigs to Babylon if the daemon runs in Jury mode -// it returns tx hash and error -func (bc *BabylonController) SubmitJuryUnbondingSigs( - btcPubKey *bbntypes.BIP340PubKey, - delPubKey *bbntypes.BIP340PubKey, - stakingTxHash string, - unbondingSig *bbntypes.BIP340Signature, - slashUnbondingSig *bbntypes.BIP340Signature, -) (*provider.RelayerTxResponse, error) { - msg := &btcstakingtypes.MsgAddJuryUnbondingSigs{ - Signer: bc.MustGetTxSigner(), - ValPk: btcPubKey, - DelPk: delPubKey, - StakingTxHash: stakingTxHash, - UnbondingTxSig: unbondingSig, - SlashingUnbondingTxSig: slashUnbondingSig, - } - - res, err := bc.reliablySendMsg(msg) + res, err := bc.reliablySendMsg(msg, emptyErrs, unrecoverableErrs) if err != nil { return nil, err } - return res, nil + return &types.TxResponse{TxHash: res.TxHash, Events: res.Events}, nil } // SubmitFinalitySig submits the finality signature via a MsgAddVote to Babylon -func (bc *BabylonController) SubmitFinalitySig(btcPubKey *bbntypes.BIP340PubKey, blockHeight uint64, blockHash []byte, sig *bbntypes.SchnorrEOTSSig) (*provider.RelayerTxResponse, error) { +func (bc *BabylonController) SubmitFinalitySig(fpPk *btcec.PublicKey, blockHeight uint64, blockHash []byte, sig *btcec.ModNScalar) (*types.TxResponse, error) { msg := &finalitytypes.MsgAddFinalitySig{ - Signer: bc.MustGetTxSigner(), - ValBtcPk: btcPubKey, - BlockHeight: blockHeight, - BlockLastCommitHash: blockHash, - FinalitySig: sig, + Signer: bc.mustGetTxSigner(), + FpBtcPk: bbntypes.NewBIP340PubKeyFromBTCPK(fpPk), + BlockHeight: blockHeight, + BlockAppHash: blockHash, + FinalitySig: bbntypes.NewSchnorrEOTSSigFromModNScalar(sig), } - res, err := bc.reliablySendMsg(msg) + unrecoverableErrs := []*sdkErr.Error{ + finalitytypes.ErrInvalidFinalitySig, + finalitytypes.ErrPubRandNotFound, + btcstakingtypes.ErrFpAlreadySlashed, + } + + res, err := bc.reliablySendMsg(msg, emptyErrs, unrecoverableErrs) if err != nil { return nil, err } - return res, nil + return &types.TxResponse{TxHash: res.TxHash, Events: res.Events}, nil } // SubmitBatchFinalitySigs submits a batch of finality signatures to Babylon -func (bc *BabylonController) SubmitBatchFinalitySigs(btcPubKey *bbntypes.BIP340PubKey, blocks []*types.BlockInfo, sigs []*bbntypes.SchnorrEOTSSig) (*provider.RelayerTxResponse, error) { +func (bc *BabylonController) SubmitBatchFinalitySigs(fpPk *btcec.PublicKey, blocks []*types.BlockInfo, sigs []*btcec.ModNScalar) (*types.TxResponse, error) { if len(blocks) != len(sigs) { return nil, fmt.Errorf("the number of blocks %v should match the number of finality signatures %v", len(blocks), len(sigs)) } @@ -380,545 +216,371 @@ func (bc *BabylonController) SubmitBatchFinalitySigs(btcPubKey *bbntypes.BIP340P msgs := make([]sdk.Msg, 0, len(blocks)) for i, b := range blocks { msg := &finalitytypes.MsgAddFinalitySig{ - Signer: bc.MustGetTxSigner(), - ValBtcPk: btcPubKey, - BlockHeight: b.Height, - BlockLastCommitHash: b.LastCommitHash, - FinalitySig: sigs[i], + Signer: bc.mustGetTxSigner(), + FpBtcPk: bbntypes.NewBIP340PubKeyFromBTCPK(fpPk), + BlockHeight: b.Height, + BlockAppHash: b.Hash, + FinalitySig: bbntypes.NewSchnorrEOTSSigFromModNScalar(sigs[i]), } msgs = append(msgs, msg) } - res, err := bc.reliablySendMsgs(msgs) + unrecoverableErrs := []*sdkErr.Error{ + finalitytypes.ErrInvalidFinalitySig, + finalitytypes.ErrPubRandNotFound, + btcstakingtypes.ErrFpAlreadySlashed, + } + + res, err := bc.reliablySendMsgs(msgs, emptyErrs, unrecoverableErrs) if err != nil { return nil, err } - return res, nil + return &types.TxResponse{TxHash: res.TxHash, Events: res.Events}, nil } -func (bc *BabylonController) SubmitValidatorUnbondingSig( - valPubKey *bbntypes.BIP340PubKey, - delPubKey *bbntypes.BIP340PubKey, - stakingTxHash string, - sig *bbntypes.BIP340Signature) (*provider.RelayerTxResponse, error) { - - msg := &btcstakingtypes.MsgAddValidatorUnbondingSig{ - Signer: bc.MustGetTxSigner(), - ValPk: valPubKey, - DelPk: delPubKey, - StakingTxHash: stakingTxHash, - UnbondingTxSig: sig, - } - - res, err := bc.reliablySendMsg(msg) - +func (bc *BabylonController) QueryFinalityProviderSlashed(fpPk *btcec.PublicKey) (bool, error) { + fpPubKey := bbntypes.NewBIP340PubKeyFromBTCPK(fpPk) + res, err := bc.bbnClient.QueryClient.FinalityProvider(fpPubKey.MarshalHex()) if err != nil { - return nil, err + return false, fmt.Errorf("failed to query the finality provider %s: %v", fpPubKey.MarshalHex(), err) } - bc.logger.WithFields(logrus.Fields{ - "validator": valPubKey.MarshalHex(), - "code": res.Code, - "height": res.Height, - "tx_hash": res.TxHash, - }).Debug("Succesfuly submitted validator signature for unbonding tx") + slashed := res.FinalityProvider.SlashedBtcHeight > 0 - return res, nil + return slashed, nil } -// Currently this is only used for e2e tests, probably does not need to add it into the interface -func (bc *BabylonController) CreateBTCDelegation( - delBabylonPk *secp256k1.PubKey, - pop *btcstakingtypes.ProofOfPossession, - stakingTx *btcstakingtypes.BabylonBTCTaprootTx, - stakingTxInfo *btcctypes.TransactionInfo, - slashingTx *btcstakingtypes.BTCSlashingTx, - delSig *bbntypes.BIP340Signature, -) (*provider.RelayerTxResponse, error) { - msg := &btcstakingtypes.MsgCreateBTCDelegation{ - Signer: bc.MustGetTxSigner(), - BabylonPk: delBabylonPk, - Pop: pop, - StakingTx: stakingTx, - StakingTxInfo: stakingTxInfo, - SlashingTx: slashingTx, - DelegatorSig: delSig, - } - - res, err := bc.reliablySendMsg(msg) +// QueryFinalityProviderVotingPower queries the voting power of the finality provider at a given height +func (bc *BabylonController) QueryFinalityProviderVotingPower(fpPk *btcec.PublicKey, blockHeight uint64) (uint64, error) { + res, err := bc.bbnClient.QueryClient.FinalityProviderPowerAtHeight( + bbntypes.NewBIP340PubKeyFromBTCPK(fpPk).MarshalHex(), + blockHeight, + ) if err != nil { - return nil, err + return 0, fmt.Errorf("failed to query BTC delegations: %w", err) } - bc.logger.Infof("successfully submitted a BTC delegation, code: %v, height: %v, tx hash: %s", res.Code, res.Height, res.TxHash) - return res, nil + return res.VotingPower, nil } -// Currently this is only used for e2e tests, probably does not need to add this into the interface -func (bc *BabylonController) CreateBTCUndelegation( - unbondingTx *btcstakingtypes.BabylonBTCTaprootTx, - slashingTx *btcstakingtypes.BTCSlashingTx, - delSig *bbntypes.BIP340Signature, -) (*provider.RelayerTxResponse, error) { - msg := &btcstakingtypes.MsgBTCUndelegate{ - Signer: bc.MustGetTxSigner(), - UnbondingTx: unbondingTx, - SlashingTx: slashingTx, - DelegatorSlashingSig: delSig, +func (bc *BabylonController) QueryLatestFinalizedBlocks(count uint64) ([]*types.BlockInfo, error) { + return bc.queryLatestBlocks(nil, count, finalitytypes.QueriedBlockStatus_FINALIZED, true) +} + +// QueryLastCommittedPublicRand returns the last committed public randomness +// TODO update the implementation when rpc-client supports ListPublicRandomness +func (bc *BabylonController) QueryLastCommittedPublicRand(fpPk *btcec.PublicKey, count uint64) (map[uint64]*btcec.FieldVal, error) { + fpBtcPk := bbntypes.NewBIP340PubKeyFromBTCPK(fpPk) + + pagination := &sdkquery.PageRequest{ + // NOTE: the count is limited by pagination queries + Limit: count, + Reverse: true, } - res, err := bc.reliablySendMsg(msg) + res, err := bc.bbnClient.QueryClient.ListPublicRandomness(fpBtcPk.MarshalHex(), pagination) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to query committed public randomness: %w", err) } - bc.logger.Infof("successfully submitted a BTC undelegation, code: %v, height: %v, tx hash: %s", res.Code, res.Height, res.TxHash) - return res, nil -} - -// Insert BTC block header using rpc client -// Currently this is only used for e2e tests, probably does not need to add it into the interface -func (bc *BabylonController) InsertBtcBlockHeaders(headers []*bbntypes.BTCHeaderBytes) (*provider.RelayerTxResponse, error) { - msgs := make([]sdk.Msg, 0, len(headers)) - for _, h := range headers { - msg := &btclctypes.MsgInsertHeader{ - Signer: bc.MustGetTxSigner(), - Header: h, + committedPubRand := make(map[uint64]*btcec.FieldVal, len(res.PubRandMap)) + for k, v := range res.PubRandMap { + if v == nil { + return nil, fmt.Errorf("invalid committed public randomness") } - msgs = append(msgs, msg) - } - - res, err := bc.reliablySendMsgs(msgs) - if err != nil { - return nil, err + committedPubRand[k] = v.ToFieldVal() } - return res, nil + return committedPubRand, nil } -// Note: the following queries are only for PoC -// QueryHeightWithLastPubRand queries the height of the last block with public randomness -func (bc *BabylonController) QueryHeightWithLastPubRand(btcPubKey *bbntypes.BIP340PubKey) (uint64, error) { - ctx, cancel := getContextWithCancel(bc.timeout) - defer cancel() - - clientCtx := sdkclient.Context{Client: bc.provider.RPCClient} - - queryClient := finalitytypes.NewQueryClient(clientCtx) - - // query the last committed public randomness - queryRequest := &finalitytypes.QueryListPublicRandomnessRequest{ - ValBtcPkHex: btcPubKey.MarshalHex(), - Pagination: &sdkquery.PageRequest{ - Limit: 1, - Reverse: true, - }, +func (bc *BabylonController) QueryBlocks(startHeight, endHeight, limit uint64) ([]*types.BlockInfo, error) { + if endHeight < startHeight { + return nil, fmt.Errorf("the startHeight %v should not be higher than the endHeight %v", startHeight, endHeight) + } + count := endHeight - startHeight + 1 + if count > limit { + count = limit } + return bc.queryLatestBlocks(sdk.Uint64ToBigEndian(startHeight), count, finalitytypes.QueriedBlockStatus_ANY, false) +} - res, err := queryClient.ListPublicRandomness(ctx, queryRequest) - if err != nil { - return 0, err +func (bc *BabylonController) queryLatestBlocks(startKey []byte, count uint64, status finalitytypes.QueriedBlockStatus, reverse bool) ([]*types.BlockInfo, error) { + var blocks []*types.BlockInfo + pagination := &sdkquery.PageRequest{ + Limit: count, + Reverse: reverse, + Key: startKey, } - if len(res.PubRandMap) == 0 { - return 0, nil + res, err := bc.bbnClient.QueryClient.ListBlocks(status, pagination) + if err != nil { + return nil, fmt.Errorf("failed to query finalized blocks: %v", err) } - ks := maps.Keys(res.PubRandMap) - if len(ks) > 1 { - return 0, fmt.Errorf("the query should not return more than one public rand item") + for _, b := range res.Blocks { + ib := &types.BlockInfo{ + Height: b.Height, + Hash: b.AppHash, + } + blocks = append(blocks, ib) } - return ks[0], nil + return blocks, nil } -// QueryPendingBTCDelegations queries BTC delegations that need a Jury sig -// it is only used when the program is running in Jury mode -func (bc *BabylonController) QueryPendingBTCDelegations() ([]*btcstakingtypes.BTCDelegation, error) { - ctx, cancel := getContextWithCancel(bc.timeout) - defer cancel() - - clientCtx := sdkclient.Context{Client: bc.provider.RPCClient} - - queryClient := btcstakingtypes.NewQueryClient(clientCtx) +func getContextWithCancel(timeout time.Duration) (context.Context, context.CancelFunc) { + ctx, cancel := context.WithTimeout(context.Background(), timeout) + return ctx, cancel +} - // query all the unsigned delegations - queryRequest := &btcstakingtypes.QueryPendingBTCDelegationsRequest{} - res, err := queryClient.PendingBTCDelegations(ctx, queryRequest) +func (bc *BabylonController) QueryBlock(height uint64) (*types.BlockInfo, error) { + res, err := bc.bbnClient.QueryClient.Block(height) if err != nil { - return nil, fmt.Errorf("failed to query BTC delegations: %v", err) + return nil, fmt.Errorf("failed to query indexed block at height %v: %w", height, err) } - return res.BtcDelegations, nil + return &types.BlockInfo{ + Height: height, + Hash: res.Block.AppHash, + Finalized: res.Block.Finalized, + }, nil } -// QueryUnbondindBTCDelegations queries BTC delegations that need a Jury sig for unbodning -// it is only used when the program is running in Jury mode -func (bc *BabylonController) QueryUnbondindBTCDelegations() ([]*btcstakingtypes.BTCDelegation, error) { - ctx, cancel := getContextWithCancel(bc.timeout) - defer cancel() - - clientCtx := sdkclient.Context{Client: bc.provider.RPCClient} - - queryClient := btcstakingtypes.NewQueryClient(clientCtx) - - // query all the unsigned delegations - queryRequest := &btcstakingtypes.QueryUnbondingBTCDelegationsRequest{} - res, err := queryClient.UnbondingBTCDelegations(ctx, queryRequest) +func (bc *BabylonController) QueryActivatedHeight() (uint64, error) { + res, err := bc.bbnClient.QueryClient.ActivatedHeight() if err != nil { - return nil, fmt.Errorf("failed to query BTC delegations: %v", err) + return 0, fmt.Errorf("failed to query activated height: %w", err) } - return res.BtcDelegations, nil + return res.Height, nil } -// QueryValidators queries BTC validators -func (bc *BabylonController) QueryValidators() ([]*btcstakingtypes.BTCValidator, error) { - var validators []*btcstakingtypes.BTCValidator - pagination := &sdkquery.PageRequest{ - Limit: 100, - } - - ctx, cancel := getContextWithCancel(bc.timeout) - defer cancel() - - clientCtx := sdkclient.Context{Client: bc.provider.RPCClient} - - queryClient := btcstakingtypes.NewQueryClient(clientCtx) - - for { - queryRequest := &btcstakingtypes.QueryBTCValidatorsRequest{ - Pagination: pagination, - } - res, err := queryClient.BTCValidators(ctx, queryRequest) - if err != nil { - return nil, fmt.Errorf("failed to query BTC validators: %v", err) - } - validators = append(validators, res.BtcValidators...) - if res.Pagination == nil || res.Pagination.NextKey == nil { - break - } - - pagination.Key = res.Pagination.NextKey +func (bc *BabylonController) QueryBestBlock() (*types.BlockInfo, error) { + blocks, err := bc.queryLatestBlocks(nil, 1, finalitytypes.QueriedBlockStatus_ANY, true) + if err != nil || len(blocks) != 1 { + // try query comet block if the index block query is not available + return bc.queryCometBestBlock() } - return validators, nil + return blocks[0], nil } -func (bc *BabylonController) QueryBtcLightClientTip() (*btclctypes.BTCHeaderInfo, error) { - ctx, cancel := getContextWithCancel(bc.timeout) +func (bc *BabylonController) queryCometBestBlock() (*types.BlockInfo, error) { + ctx, cancel := getContextWithCancel(bc.cfg.Timeout) + // this will return 20 items at max in the descending order (highest first) + chainInfo, err := bc.bbnClient.RPCClient.BlockchainInfo(ctx, 0, 0) defer cancel() - clientCtx := sdkclient.Context{Client: bc.provider.RPCClient} - - queryClient := btclctypes.NewQueryClient(clientCtx) - - queryRequest := &btclctypes.QueryTipRequest{} - res, err := queryClient.Tip(ctx, queryRequest) if err != nil { - return nil, fmt.Errorf("failed to query BTC tip: %v", err) + return nil, err } - return res.Header, nil + // Returning response directly, if header with specified number did not exist + // at request will contain nil header + return &types.BlockInfo{ + Height: uint64(chainInfo.BlockMetas[0].Header.Height), + Hash: chainInfo.BlockMetas[0].Header.AppHash, + }, nil } -func (bc *BabylonController) getNDelegations( - valBtcPk *bbntypes.BIP340PubKey, - startKey []byte, - n uint64, -) ([]*btcstakingtypes.BTCDelegation, []byte, error) { - pagination := &sdkquery.PageRequest{ - Key: startKey, - Limit: n, +func (bc *BabylonController) Close() error { + if !bc.bbnClient.IsRunning() { + return nil } - ctx, cancel := getContextWithCancel(bc.timeout) - defer cancel() - - clientCtx := sdkclient.Context{Client: bc.provider.RPCClient} + return bc.bbnClient.Stop() +} - queryClient := btcstakingtypes.NewQueryClient(clientCtx) +/* + Implementations for e2e tests only +*/ - queryRequest := &btcstakingtypes.QueryBTCValidatorDelegationsRequest{ - ValBtcPkHex: valBtcPk.MarshalHex(), - Pagination: pagination, +func (bc *BabylonController) CreateBTCDelegation( + delBabylonPk *secp256k1.PubKey, + delBtcPk *bbntypes.BIP340PubKey, + fpPks []*btcec.PublicKey, + pop *btcstakingtypes.ProofOfPossession, + stakingTime uint32, + stakingValue int64, + stakingTxInfo *btcctypes.TransactionInfo, + slashingTx *btcstakingtypes.BTCSlashingTx, + delSlashingSig *bbntypes.BIP340Signature, + unbondingTx []byte, + unbondingTime uint32, + unbondingValue int64, + unbondingSlashingTx *btcstakingtypes.BTCSlashingTx, + delUnbondingSlashingSig *bbntypes.BIP340Signature, +) (*types.TxResponse, error) { + fpBtcPks := make([]bbntypes.BIP340PubKey, 0, len(fpPks)) + for _, v := range fpPks { + fpBtcPks = append(fpBtcPks, *bbntypes.NewBIP340PubKeyFromBTCPK(v)) } - res, err := queryClient.BTCValidatorDelegations(ctx, queryRequest) - + msg := &btcstakingtypes.MsgCreateBTCDelegation{ + Signer: bc.mustGetTxSigner(), + BabylonPk: delBabylonPk, + Pop: pop, + BtcPk: delBtcPk, + FpBtcPkList: fpBtcPks, + StakingTime: stakingTime, + StakingValue: stakingValue, + StakingTx: stakingTxInfo, + SlashingTx: slashingTx, + DelegatorSlashingSig: delSlashingSig, + UnbondingTx: unbondingTx, + UnbondingTime: unbondingTime, + UnbondingValue: unbondingValue, + UnbondingSlashingTx: unbondingSlashingTx, + DelegatorUnbondingSlashingSig: delUnbondingSlashingSig, + } + + res, err := bc.reliablySendMsg(msg, emptyErrs, emptyErrs) if err != nil { - return nil, nil, fmt.Errorf("failed to query BTC delegations: %v", err) + return nil, err } - var delegations []*btcstakingtypes.BTCDelegation + return &types.TxResponse{TxHash: res.TxHash}, nil +} - for _, dels := range res.BtcDelegatorDelegations { - delegations = append(delegations, dels.Dels...) +func (bc *BabylonController) InsertBtcBlockHeaders(headers []bbntypes.BTCHeaderBytes) (*provider.RelayerTxResponse, error) { + msg := &btclctypes.MsgInsertHeaders{ + Signer: bc.mustGetTxSigner(), + Headers: headers, } - var nextKey []byte - - if res.Pagination != nil && res.Pagination.NextKey != nil { - nextKey = res.Pagination.NextKey + res, err := bc.reliablySendMsg(msg, emptyErrs, emptyErrs) + if err != nil { + return nil, err } - return delegations, nextKey, nil + return res, nil } -func (bc *BabylonController) getNValidatorDelegationsMatchingCriteria( - valBtcPk *bbntypes.BIP340PubKey, - n uint64, - match func(*btcstakingtypes.BTCDelegation) bool, -) ([]*btcstakingtypes.BTCDelegation, error) { - batchSize := 100 - var delegations []*btcstakingtypes.BTCDelegation - var startKey []byte +func (bc *BabylonController) QueryFinalityProviders() ([]*btcstakingtypes.FinalityProvider, error) { + var fps []*btcstakingtypes.FinalityProvider + pagination := &sdkquery.PageRequest{ + Limit: 100, + } for { - dels, nextKey, err := bc.getNDelegations(valBtcPk, startKey, uint64(batchSize)) + res, err := bc.bbnClient.QueryClient.FinalityProviders(pagination) if err != nil { - return nil, err - } - - for _, del := range dels { - if match(del) { - delegations = append(delegations, del) - } + return nil, fmt.Errorf("failed to query finality providers: %v", err) } - - if len(delegations) >= int(n) || len(nextKey) == 0 { + fps = append(fps, res.FinalityProviders...) + if res.Pagination == nil || res.Pagination.NextKey == nil { break } - startKey = nextKey - } - - if len(delegations) > int(n) { - // only return requested number of delegations - return delegations[:n], nil - } else { - return delegations, nil + pagination.Key = res.Pagination.NextKey } -} - -// Currently this is only used for e2e tests, probably does not need to add this into the interface -func (bc *BabylonController) QueryBTCValidatorDelegations(valBtcPk *bbntypes.BIP340PubKey, max uint64) ([]*btcstakingtypes.BTCDelegation, error) { - return bc.getNValidatorDelegationsMatchingCriteria( - valBtcPk, - max, - // fitlering function which always returns true as we want all delegations - func(*btcstakingtypes.BTCDelegation) bool { return true }, - ) -} -func (bc *BabylonController) QueryBTCValidatorUnbondingDelegations(valBtcPk *bbntypes.BIP340PubKey, max uint64) ([]*btcstakingtypes.BTCDelegation, error) { - // TODO Check what is the order of returned delegations. Ideally we would return - // delegation here from the first one which received undelegation - return bc.getNValidatorDelegationsMatchingCriteria( - valBtcPk, - max, - func(del *btcstakingtypes.BTCDelegation) bool { - return del.BtcUndelegation != nil && del.BtcUndelegation.ValidatorUnbondingSig == nil - }, - ) + return fps, nil } -// QueryValidatorVotingPower queries the voting power of the validator at a given height -func (bc *BabylonController) QueryValidatorVotingPower(btcPubKey *bbntypes.BIP340PubKey, blockHeight uint64) (uint64, error) { - ctx, cancel := getContextWithCancel(bc.timeout) - defer cancel() - - clientCtx := sdkclient.Context{Client: bc.provider.RPCClient} - - queryClient := btcstakingtypes.NewQueryClient(clientCtx) - - // query all the unsigned delegations - queryRequest := &btcstakingtypes.QueryBTCValidatorPowerAtHeightRequest{ - ValBtcPkHex: btcPubKey.MarshalHex(), - Height: blockHeight, - } - res, err := queryClient.BTCValidatorPowerAtHeight(ctx, queryRequest) +func (bc *BabylonController) QueryBtcLightClientTip() (*btclctypes.BTCHeaderInfo, error) { + res, err := bc.bbnClient.QueryClient.BTCHeaderChainTip() if err != nil { - return 0, fmt.Errorf("failed to query BTC delegations: %w", err) + return nil, fmt.Errorf("failed to query BTC tip: %v", err) } - return res.VotingPower, nil + return res.Header, nil } -// QueryBlockFinalization queries whether the block has been finalized -func (bc *BabylonController) QueryBlockFinalization(blockHeight uint64) (bool, error) { - ctx, cancel := getContextWithCancel(bc.timeout) - defer cancel() - - clientCtx := sdkclient.Context{Client: bc.provider.RPCClient} - - queryClient := finalitytypes.NewQueryClient(clientCtx) - - // query the indexed block at the given height - queryRequest := &finalitytypes.QueryBlockRequest{ - Height: blockHeight, - } - res, err := queryClient.Block(ctx, queryRequest) +func (bc *BabylonController) QueryVotesAtHeight(height uint64) ([]bbntypes.BIP340PubKey, error) { + res, err := bc.bbnClient.QueryClient.VotesAtHeight(height) if err != nil { - return false, fmt.Errorf("failed to query indexed block at height %v: %w", blockHeight, err) + return nil, fmt.Errorf("failed to query BTC delegations: %w", err) } - return res.Block.Finalized, nil + return res.BtcPks, nil } -func (bc *BabylonController) QueryLatestFinalizedBlocks(count uint64) ([]*types.BlockInfo, error) { - return bc.queryLatestBlocks(nil, count, finalitytypes.QueriedBlockStatus_FINALIZED, true) +func (bc *BabylonController) QueryPendingDelegations(limit uint64) ([]*btcstakingtypes.BTCDelegation, error) { + return bc.queryDelegationsWithStatus(btcstakingtypes.BTCDelegationStatus_PENDING, limit) } -func (bc *BabylonController) QueryBlocks(startHeight, endHeight, limit uint64) ([]*types.BlockInfo, error) { - if endHeight < startHeight { - return nil, fmt.Errorf("the startHeight %v should not be higher than the endHeight %v", startHeight, endHeight) - } - count := endHeight - startHeight + 1 - if count > limit { - count = limit - } - return bc.queryLatestBlocks(sdk.Uint64ToBigEndian(startHeight), count, finalitytypes.QueriedBlockStatus_ANY, false) +func (bc *BabylonController) QueryActiveDelegations(limit uint64) ([]*btcstakingtypes.BTCDelegation, error) { + return bc.queryDelegationsWithStatus(btcstakingtypes.BTCDelegationStatus_ACTIVE, limit) } -func (bc *BabylonController) queryLatestBlocks(startKey []byte, count uint64, status finalitytypes.QueriedBlockStatus, reverse bool) ([]*types.BlockInfo, error) { - var blocks []*types.BlockInfo +// queryDelegationsWithStatus queries BTC delegations +// with the given status (either pending or unbonding) +// it is only used when the program is running in Covenant mode +func (bc *BabylonController) queryDelegationsWithStatus(status btcstakingtypes.BTCDelegationStatus, limit uint64) ([]*btcstakingtypes.BTCDelegation, error) { pagination := &sdkquery.PageRequest{ - Limit: count, - Reverse: reverse, - Key: startKey, + Limit: limit, } - ctx, cancel := getContextWithCancel(bc.timeout) - defer cancel() - - clientCtx := sdkclient.Context{Client: bc.provider.RPCClient} - - queryClient := finalitytypes.NewQueryClient(clientCtx) - - queryRequest := &finalitytypes.QueryListBlocksRequest{ - Status: status, - Pagination: pagination, - } - res, err := queryClient.ListBlocks(ctx, queryRequest) + res, err := bc.bbnClient.QueryClient.BTCDelegations(status, pagination) if err != nil { - return nil, fmt.Errorf("failed to query finalized blocks: %v", err) - } - - for _, b := range res.Blocks { - ib := &types.BlockInfo{ - Height: b.Height, - LastCommitHash: b.LastCommitHash, - } - blocks = append(blocks, ib) + return nil, fmt.Errorf("failed to query BTC delegations: %v", err) } - return blocks, nil -} - -func getContextWithCancel(timeout time.Duration) (context.Context, context.CancelFunc) { - ctx, cancel := context.WithTimeout(context.Background(), timeout) - return ctx, cancel + return res.BtcDelegations, nil } -func (bc *BabylonController) QueryHeader(height int64) (*ctypes.ResultHeader, error) { - ctx, cancel := getContextWithCancel(bc.timeout) - headerResp, err := bc.provider.RPCClient.Header(ctx, &height) - defer cancel() - +func (bc *BabylonController) QueryStakingParams() (*types.StakingParams, error) { + // query btc checkpoint params + ckptParamRes, err := bc.bbnClient.QueryClient.BTCCheckpointParams() if err != nil { - return nil, err + return nil, fmt.Errorf("failed to query params of the btccheckpoint module: %v", err) } - // Returning response directly, if header with specified number did not exist - // at request will contain nil header - return headerResp, nil -} - -func (bc *BabylonController) QueryBestHeader() (*ctypes.ResultHeader, error) { - ctx, cancel := getContextWithCancel(bc.timeout) - // this will return 20 items at max in the descending order (highest first) - chainInfo, err := bc.provider.RPCClient.BlockchainInfo(ctx, 0, 0) - defer cancel() + // query btc staking params + stakingParamRes, err := bc.bbnClient.QueryClient.BTCStakingParams() + if err != nil { + return nil, fmt.Errorf("failed to query staking params: %v", err) + } + covenantPks := make([]*btcec.PublicKey, 0, len(stakingParamRes.Params.CovenantPks)) + for _, pk := range stakingParamRes.Params.CovenantPks { + covPk, err := pk.ToBTCPK() + if err != nil { + return nil, fmt.Errorf("invalid covenant public key") + } + covenantPks = append(covenantPks, covPk) + } + slashingAddress, err := btcutil.DecodeAddress(stakingParamRes.Params.SlashingAddress, bc.btcParams) if err != nil { return nil, err } - // Returning response directly, if header with specified number did not exist - // at request will contain nil header - return &ctypes.ResultHeader{ - Header: &chainInfo.BlockMetas[0].Header, + return &types.StakingParams{ + ComfirmationTimeBlocks: ckptParamRes.Params.BtcConfirmationDepth, + FinalizationTimeoutBlocks: ckptParamRes.Params.CheckpointFinalizationTimeout, + MinSlashingTxFeeSat: btcutil.Amount(stakingParamRes.Params.MinSlashingTxFeeSat), + CovenantPks: covenantPks, + SlashingAddress: slashingAddress, + CovenantQuorum: stakingParamRes.Params.CovenantQuorum, + SlashingRate: stakingParamRes.Params.SlashingRate, + MinUnbondingTime: stakingParamRes.Params.MinUnbondingTime, }, nil } -func (bc *BabylonController) QueryNodeStatus() (*ctypes.ResultStatus, error) { - ctx, cancel := getContextWithCancel(bc.timeout) - defer cancel() - - status, err := bc.provider.QueryStatus(ctx) +func (bc *BabylonController) SubmitCovenantSigs( + covPk *btcec.PublicKey, + stakingTxHash string, + slashingSigs [][]byte, + unbondingSig *schnorr.Signature, + unbondingSlashingSigs [][]byte, +) (*types.TxResponse, error) { + bip340UnbondingSig := bbntypes.NewBIP340SignatureFromBTCSig(unbondingSig) + + msg := &btcstakingtypes.MsgAddCovenantSigs{ + Signer: bc.mustGetTxSigner(), + Pk: bbntypes.NewBIP340PubKeyFromBTCPK(covPk), + StakingTxHash: stakingTxHash, + SlashingTxSigs: slashingSigs, + UnbondingTxSig: bip340UnbondingSig, + SlashingUnbondingTxSigs: unbondingSlashingSigs, + } + + res, err := bc.reliablySendMsg(msg, emptyErrs, emptyErrs) if err != nil { return nil, err } - return status, nil -} - -// accessKeyWithLock triggers a function that access key ring while acquiring -// the file system lock, in order to remain thread-safe when multiple concurrent -// relayers are running on the same machine and accessing the same keyring -// adapted from -// https://github.com/babylonchain/babylon-relayer/blob/f962d0940832a8f84f747c5d9cbc67bc1b156386/bbnrelayer/utils.go#L212 -func (bc *BabylonController) accessKeyWithLock(accessFunc func()) error { - // use lock file to guard concurrent access to the keyring - lockFilePath := path.Join(bc.provider.PCfg.KeyDirectory, "keys.lock") - lock := fslock.New(lockFilePath) - if err := lock.Lock(); err != nil { - return fmt.Errorf("failed to acquire file system lock (%s): %w", lockFilePath, err) - } - - // trigger function that access keyring - accessFunc() - - // unlock and release access - if err := lock.Unlock(); err != nil { - return fmt.Errorf("error unlocking file system lock (%s), please manually delete", lockFilePath) - } - - return nil -} - -func (bc *BabylonController) Close() error { - if !bc.provider.RPCClient.IsRunning() { - return nil - } - return bc.provider.RPCClient.Stop() -} - -func ConvertErrType(err error) error { - if err == nil { - return nil - } - switch { - case strings.Contains(err.Error(), btcstakingtypes.ErrBTCValAlreadySlashed.Error()): - return types.ErrValidatorSlashed - case strings.Contains(err.Error(), finalitytypes.ErrBlockNotFound.Error()): - return types.ErrBlockNotFound - case strings.Contains(err.Error(), finalitytypes.ErrInvalidFinalitySig.Error()): - return types.ErrInvalidFinalitySig - case strings.Contains(err.Error(), finalitytypes.ErrHeightTooHigh.Error()): - return types.ErrHeightTooHigh - case strings.Contains(err.Error(), finalitytypes.ErrNoPubRandYet.Error()): - return types.ErrNoPubRandYet - case strings.Contains(err.Error(), finalitytypes.ErrPubRandNotFound.Error()): - return types.ErrPubRandNotFound - case strings.Contains(err.Error(), finalitytypes.ErrTooFewPubRand.Error()): - return types.ErrTooFewPubRand - case strings.Contains(err.Error(), finalitytypes.ErrInvalidPubRand.Error()): - return types.ErrInvalidPubRand - case strings.Contains(err.Error(), finalitytypes.ErrDuplicatedFinalitySig.Error()): - return types.ErrDuplicatedFinalitySig - default: - return err - } + return &types.TxResponse{TxHash: res.TxHash, Events: res.Events}, nil } diff --git a/clientcontroller/interface.go b/clientcontroller/interface.go index 15bfa0f9..10d7fb2e 100644 --- a/clientcontroller/interface.go +++ b/clientcontroller/interface.go @@ -3,131 +3,80 @@ package clientcontroller import ( "fmt" - bbntypes "github.com/babylonchain/babylon/types" - btcstakingtypes "github.com/babylonchain/babylon/x/btcstaking/types" + "cosmossdk.io/math" "github.com/btcsuite/btcd/btcec/v2" - "github.com/btcsuite/btcd/btcutil" - ctypes "github.com/cometbft/cometbft/rpc/core/types" - "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - sdkTypes "github.com/cosmos/cosmos-sdk/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - "github.com/cosmos/relayer/v2/relayer/provider" - "github.com/sirupsen/logrus" - - "github.com/babylonchain/btc-validator/types" - "github.com/babylonchain/btc-validator/valcfg" + "github.com/btcsuite/btcd/btcec/v2/schnorr" + "github.com/btcsuite/btcd/chaincfg" + "go.uber.org/zap" + + "github.com/babylonchain/finality-provider/config" + "github.com/babylonchain/finality-provider/types" ) const ( babylonConsumerChainName = "babylon" ) -type StakingParams struct { - // K-deep - ComfirmationTimeBlocks uint64 - // W-deep - FinalizationTimeoutBlocks uint64 - - // Minimum amount of satoshis required for slashing transaction - MinSlashingTxFeeSat btcutil.Amount - - // Bitcoin public key of the current jury - JuryPk *btcec.PublicKey - - // Address to which slashing transactions are sent - SlashingAddress string - - // Minimum commission required by babylon - MinCommissionRate sdkTypes.Dec -} - -// TODO replace babylon types with general ones type ClientController interface { - GetStakingParams() (*StakingParams, error) - // RegisterValidator registers a BTC validator via a MsgCreateBTCValidator to Babylon - // it returns tx hash and error - RegisterValidator( - bbnPubKey *secp256k1.PubKey, - btcPubKey *bbntypes.BIP340PubKey, - pop *btcstakingtypes.ProofOfPossession, - commission *sdkTypes.Dec, - description *stakingtypes.Description, - ) (*provider.RelayerTxResponse, error) - // CommitPubRandList commits a list of Schnorr public randomness via a MsgCommitPubRand to Babylon + + // RegisterFinalityProvider registers a finality provider to the consumer chain // it returns tx hash and error - CommitPubRandList(btcPubKey *bbntypes.BIP340PubKey, startHeight uint64, pubRandList []bbntypes.SchnorrPubRand, sig *bbntypes.BIP340Signature) (*provider.RelayerTxResponse, error) - // SubmitJurySig submits the Jury signature via a MsgAddJurySig to Babylon if the daemon runs in Jury mode + RegisterFinalityProvider( + chainPk []byte, + fpPk *btcec.PublicKey, + pop []byte, + commission *math.LegacyDec, + description []byte, + ) (*types.TxResponse, error) + + // CommitPubRandList commits a list of EOTS public randomness the consumer chain // it returns tx hash and error - SubmitJurySig(btcPubKey *bbntypes.BIP340PubKey, delPubKey *bbntypes.BIP340PubKey, stakingTxHash string, sig *bbntypes.BIP340Signature) (*provider.RelayerTxResponse, error) + CommitPubRandList(fpPk *btcec.PublicKey, startHeight uint64, pubRandList []*btcec.FieldVal, sig *schnorr.Signature) (*types.TxResponse, error) - // SubmitJuryUnbondingSigs submits the Jury signatures via a MsgAddJuryUnbondingSigs to Babylon if the daemon runs in Jury mode - // it returns tx hash and error - SubmitJuryUnbondingSigs( - btcPubKey *bbntypes.BIP340PubKey, - delPubKey *bbntypes.BIP340PubKey, - stakingTxHash string, - unbondingSig *bbntypes.BIP340Signature, - slashUnbondingSig *bbntypes.BIP340Signature, - ) (*provider.RelayerTxResponse, error) - - // SubmitFinalitySig submits the finality signature via a MsgAddVote to Babylon - SubmitFinalitySig(btcPubKey *bbntypes.BIP340PubKey, blockHeight uint64, blockHash []byte, sig *bbntypes.SchnorrEOTSSig) (*provider.RelayerTxResponse, error) - // SubmitBatchFinalitySigs submits a batch of finality signatures to Babylon - SubmitBatchFinalitySigs(btcPubKey *bbntypes.BIP340PubKey, blocks []*types.BlockInfo, sigs []*bbntypes.SchnorrEOTSSig) (*provider.RelayerTxResponse, error) - - // SubmitValidatorUnbondingSig submits the validator signature for unbonding transaction - SubmitValidatorUnbondingSig( - valPubKey *bbntypes.BIP340PubKey, - delPubKey *bbntypes.BIP340PubKey, - stakingTxHash string, - sig *bbntypes.BIP340Signature) (*provider.RelayerTxResponse, error) + // SubmitFinalitySig submits the finality signature to the consumer chain + SubmitFinalitySig(fpPk *btcec.PublicKey, blockHeight uint64, blockHash []byte, sig *btcec.ModNScalar) (*types.TxResponse, error) + + // SubmitBatchFinalitySigs submits a batch of finality signatures to the consumer chain + SubmitBatchFinalitySigs(fpPk *btcec.PublicKey, blocks []*types.BlockInfo, sigs []*btcec.ModNScalar) (*types.TxResponse, error) // Note: the following queries are only for PoC - // QueryHeightWithLastPubRand queries the height of the last block with public randomness - QueryHeightWithLastPubRand(btcPubKey *bbntypes.BIP340PubKey) (uint64, error) - // QueryPendingBTCDelegations queries BTC delegations that need a Jury signature - // it is only used when the program is running in Jury mode - QueryPendingBTCDelegations() ([]*btcstakingtypes.BTCDelegation, error) + // QueryFinalityProviderVotingPower queries the voting power of the finality provider at a given height + QueryFinalityProviderVotingPower(fpPk *btcec.PublicKey, blockHeight uint64) (uint64, error) - // QueryUnbondindBTCDelegations queries BTC delegations that need a Jury sig for unbodning - // it is only used when the program is running in Jury mode - QueryUnbondindBTCDelegations() ([]*btcstakingtypes.BTCDelegation, error) + // QueryFinalityProviderSlashed queries if the finality provider is slashed + QueryFinalityProviderSlashed(fpPk *btcec.PublicKey) (bool, error) - // QueryValidatorVotingPower queries the voting power of the validator at a given height - QueryValidatorVotingPower(btcPubKey *bbntypes.BIP340PubKey, blockHeight uint64) (uint64, error) // QueryLatestFinalizedBlocks returns the latest finalized blocks QueryLatestFinalizedBlocks(count uint64) ([]*types.BlockInfo, error) + + // QueryLastCommittedPublicRand returns the last committed public randomness + QueryLastCommittedPublicRand(fpPk *btcec.PublicKey, count uint64) (map[uint64]*btcec.FieldVal, error) + + // QueryBlock queries the block at the given height + QueryBlock(height uint64) (*types.BlockInfo, error) + // QueryBlocks returns a list of blocks from startHeight to endHeight QueryBlocks(startHeight, endHeight, limit uint64) ([]*types.BlockInfo, error) - // QueryBlockFinalization queries whether the block has been finalized - QueryBlockFinalization(height uint64) (bool, error) - - // QueryBestHeader queries the tip header of the Babylon chain, if header is not found - // it returns result with nil header - QueryBestHeader() (*ctypes.ResultHeader, error) - // QueryNodeStatus returns current node status, with info about latest block - QueryNodeStatus() (*ctypes.ResultStatus, error) - // QueryHeader queries the header at the given height, if header is not found - // it returns result with nil header - QueryHeader(height int64) (*ctypes.ResultHeader, error) - - // QueryBTCValidatorUnbondingDelegations queries the unbonding delegations.UnbondingDelegations: - // - already received unbodning transaction on babylon chain - // - not received validator signature yet - QueryBTCValidatorUnbondingDelegations(valBtcPk *bbntypes.BIP340PubKey, max uint64) ([]*btcstakingtypes.BTCDelegation, error) + + // QueryBestBlock queries the tip block of the consumer chain + QueryBestBlock() (*types.BlockInfo, error) + + // QueryActivatedHeight returns the activated height of the consumer chain + // error will be returned if the consumer chain has not been activated + QueryActivatedHeight() (uint64, error) Close() error } -func NewClientController(cfg *valcfg.Config, logger *logrus.Logger) (ClientController, error) { +func NewClientController(chainName string, bbnConfig *config.BBNConfig, netParams *chaincfg.Params, logger *zap.Logger) (ClientController, error) { var ( cc ClientController err error ) - switch cfg.ChainName { + switch chainName { case babylonConsumerChainName: - cc, err = NewBabylonController(cfg.DataDir, cfg.BabylonConfig, logger) + cc, err = NewBabylonController(bbnConfig, netParams, logger) if err != nil { return nil, fmt.Errorf("failed to create Babylon rpc client: %w", err) } diff --git a/clientcontroller/retry_utils.go b/clientcontroller/retry_utils.go index 159e91f3..d216dabb 100644 --- a/clientcontroller/retry_utils.go +++ b/clientcontroller/retry_utils.go @@ -2,32 +2,21 @@ package clientcontroller import ( "errors" - "time" - "github.com/avast/retry-go/v4" - - "github.com/babylonchain/btc-validator/types" -) - -// Variables used for retries -var ( - rtyAttNum = uint(5) - rtyAtt = retry.Attempts(rtyAttNum) - rtyDel = retry.Delay(time.Millisecond * 400) - rtyErr = retry.LastErrorOnly(true) + sdkErr "cosmossdk.io/errors" + btcstakingtypes "github.com/babylonchain/babylon/x/btcstaking/types" + finalitytypes "github.com/babylonchain/babylon/x/finality/types" ) // these errors are considered unrecoverable because these indicate -// something critical in the validator program or the consumer chain -var unrecoverableErrors = []error{ - types.ErrBlockNotFound, - types.ErrInvalidFinalitySig, - types.ErrHeightTooHigh, - types.ErrInvalidPubRand, - types.ErrNoPubRandYet, - types.ErrPubRandNotFound, - types.ErrTooFewPubRand, - types.ErrValidatorSlashed, +// something critical in the finality provider program or the consumer chain +var unrecoverableErrors = []*sdkErr.Error{ + finalitytypes.ErrBlockNotFound, + finalitytypes.ErrInvalidFinalitySig, + finalitytypes.ErrNoPubRandYet, + finalitytypes.ErrPubRandNotFound, + finalitytypes.ErrTooFewPubRand, + btcstakingtypes.ErrFpAlreadySlashed, } // IsUnrecoverable returns true when the error is in the unrecoverableErrors list @@ -41,19 +30,33 @@ func IsUnrecoverable(err error) bool { return false } -var expectedErrors = []error{ - // if due to some low-level reason (e.g., network), we submit duplicated finality sig, - // we should just ignore the error - types.ErrDuplicatedFinalitySig, +type ExpectedError struct { + error } -// IsExpected returns true when the error is in the expectedErrors list -func IsExpected(err error) bool { - for _, e := range expectedErrors { - if errors.Is(err, e) { - return true - } +func (e ExpectedError) Error() string { + if e.error == nil { + return "expected error" } + return e.error.Error() +} - return false +func (e ExpectedError) Unwrap() error { + return e.error +} + +// Is adds support for errors.Is usage on isExpected +func (ExpectedError) Is(err error) bool { + _, isExpected := err.(ExpectedError) + return isExpected +} + +// Expected wraps an error in ExpectedError struct +func Expected(err error) error { + return ExpectedError{err} +} + +// IsExpected checks if error is an instance of ExpectedError +func IsExpected(err error) bool { + return errors.Is(err, ExpectedError{}) } diff --git a/clientcontroller/retry_utils_test.go b/clientcontroller/retry_utils_test.go new file mode 100644 index 00000000..d1f178a6 --- /dev/null +++ b/clientcontroller/retry_utils_test.go @@ -0,0 +1,15 @@ +package clientcontroller + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestExpectedErr(t *testing.T) { + expectedErr := Expected(fmt.Errorf("some error")) + require.True(t, IsExpected(expectedErr)) + wrappedErr := fmt.Errorf("expected: %w", expectedErr) + require.True(t, IsExpected(wrappedErr)) +} diff --git a/cmd/valcli/admin.go b/cmd/valcli/admin.go deleted file mode 100644 index ae535c7e..00000000 --- a/cmd/valcli/admin.go +++ /dev/null @@ -1,66 +0,0 @@ -package main - -import ( - "fmt" - - "github.com/jessevdk/go-flags" - "github.com/urfave/cli" - - "github.com/babylonchain/btc-validator/valcfg" -) - -var adminCommands = []cli.Command{ - { - Name: "admin", - ShortName: "ad", - Usage: "Different utility and admin commands.", - Category: "Admin", - Subcommands: []cli.Command{ - dumpCfgCommand, - }, - }, -} - -const ( - configFileDirFlag = "config-file-dir" -) - -var ( - defaultConfigPath = valcfg.DefaultConfigFile -) - -var dumpCfgCommand = cli.Command{ - Name: "dump-config", - ShortName: "dc", - Usage: "Dump default configuration file.", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: configFileDirFlag, - Usage: "Path to where the default config file will be dumped", - Value: defaultConfigPath, - }, - }, - Action: dumpCfg, -} - -func dumpCfg(c *cli.Context) error { - configPath := c.String(configFileDirFlag) - - if valcfg.FileExists(configPath) { - return cli.NewExitError( - fmt.Sprintf("config already exists under provided path: %s", configPath), - 1, - ) - } - - defaultConfig := valcfg.DefaultConfig() - fileParser := flags.NewParser(&defaultConfig, flags.Default) - - err := flags.NewIniParser(fileParser).WriteFile(configPath, flags.IniIncludeComments|flags.IniIncludeDefaults) - - if err != nil { - return err - } - - return nil -} diff --git a/cmd/valcli/daemoncmd.go b/cmd/valcli/daemoncmd.go deleted file mode 100644 index 465ea5be..00000000 --- a/cmd/valcli/daemoncmd.go +++ /dev/null @@ -1,357 +0,0 @@ -package main - -import ( - "context" - "encoding/hex" - "fmt" - "strconv" - - "cosmossdk.io/math" - "github.com/babylonchain/babylon/x/checkpointing/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - "github.com/urfave/cli" - - "github.com/babylonchain/btc-validator/proto" - dc "github.com/babylonchain/btc-validator/service/client" - "github.com/babylonchain/btc-validator/valcfg" -) - -var daemonCommands = []cli.Command{ - { - Name: "daemon", - ShortName: "dn", - Usage: "More advanced commands which require validator daemon to be running.", - Category: "Daemon commands", - Subcommands: []cli.Command{ - getDaemonInfoCmd, - createValDaemonCmd, - lsValDaemonCmd, - valInfoDaemonCmd, - registerValDaemonCmd, - addFinalitySigDaemonCmd, - }, - }, -} - -const ( - valdDaemonAddressFlag = "daemon-address" - keyNameFlag = "key-name" - valBabylonPkFlag = "babylon-pk" - blockHeightFlag = "height" - lastCommitHashFlag = "last-commit-hash" - - // flags for description - monikerFlag = "moniker" - identityFlag = "identity" - websiteFlag = "website" - securityContractFlag = "security-contract" - detailsFlag = "details" - - commissionRateFlag = "commission" -) - -var ( - defaultValdDaemonAddress = "127.0.0.1:" + strconv.Itoa(valcfg.DefaultRPCPort) - defaultLastCommitHashStr = "fd903d9baeb3ab1c734ee003de75f676c5a9a8d0574647e5385834d57d3e79ec" -) - -var getDaemonInfoCmd = cli.Command{ - Name: "get-info", - ShortName: "gi", - Usage: "Get information of the running daemon.", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: valdDaemonAddressFlag, - Usage: "Full address of the validator daemon in format tcp://:", - Value: defaultValdDaemonAddress, - }, - }, - Action: getInfo, -} - -func getInfo(ctx *cli.Context) error { - daemonAddress := ctx.String(valdDaemonAddressFlag) - client, cleanUp, err := dc.NewValidatorServiceGRpcClient(daemonAddress) - if err != nil { - return err - } - defer cleanUp() - - info, err := client.GetInfo(context.Background()) - - if err != nil { - return err - } - - printRespJSON(info) - - return nil -} - -var createValDaemonCmd = cli.Command{ - Name: "create-validator", - ShortName: "cv", - Usage: "Create a Bitcoin validator object and save it in database.", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: valdDaemonAddressFlag, - Usage: "Full address of the validator daemon in format tcp://:", - Value: defaultValdDaemonAddress, - }, - cli.StringFlag{ - Name: keyNameFlag, - Usage: "The unique name of the validator key", - Required: true, - }, - cli.StringFlag{ - Name: commissionRateFlag, - Usage: "The commission rate for the validator, e.g., 0.05", - Value: "0.05", - }, - cli.StringFlag{ - Name: monikerFlag, - Usage: "A human-readable name for the validator", - Value: "", - }, - cli.StringFlag{ - Name: identityFlag, - Usage: "An optional identity signature (ex. UPort or Keybase)", - Value: "", - }, - cli.StringFlag{ - Name: websiteFlag, - Usage: "An optional website link", - Value: "", - }, - cli.StringFlag{ - Name: securityContractFlag, - Usage: "An optional email for security contact", - Value: "", - }, - cli.StringFlag{ - Name: detailsFlag, - Usage: "Other optional details", - Value: "", - }, - }, - Action: createValDaemon, -} - -func createValDaemon(ctx *cli.Context) error { - daemonAddress := ctx.String(valdDaemonAddressFlag) - keyName := ctx.String(keyNameFlag) - - commissionRate, err := math.LegacyNewDecFromStr(ctx.String(commissionRateFlag)) - if err != nil { - return err - } - - description, err := getDesciptionFromContext(ctx) - if err != nil { - return err - } - - client, cleanUp, err := dc.NewValidatorServiceGRpcClient(daemonAddress) - if err != nil { - return err - } - defer cleanUp() - - info, err := client.CreateValidator(context.Background(), keyName, &description, &commissionRate) - - if err != nil { - return err - } - - printRespJSON(info) - - return nil -} - -func getDesciptionFromContext(ctx *cli.Context) (stakingtypes.Description, error) { - - // get information for description - monikerStr := ctx.String(monikerFlag) - identityStr := ctx.String(identityFlag) - websiteStr := ctx.String(websiteFlag) - securityContractStr := ctx.String(securityContractFlag) - detailsStr := ctx.String(detailsFlag) - - description := stakingtypes.NewDescription(monikerStr, identityStr, websiteStr, securityContractStr, detailsStr) - return description.EnsureLength() -} - -var lsValDaemonCmd = cli.Command{ - Name: "list-validators", - ShortName: "ls", - Usage: "List validators stored in the database.", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: valdDaemonAddressFlag, - Usage: "Full address of the validator daemon in format tcp://:", - Value: defaultValdDaemonAddress, - }, - }, - Action: lsValDaemon, -} - -func lsValDaemon(ctx *cli.Context) error { - daemonAddress := ctx.String(valdDaemonAddressFlag) - rpcClient, cleanUp, err := dc.NewValidatorServiceGRpcClient(daemonAddress) - if err != nil { - return err - } - defer cleanUp() - - resp, err := rpcClient.QueryValidatorList(context.Background()) - if err != nil { - return err - } - - printRespJSON(resp) - - return nil -} - -var valInfoDaemonCmd = cli.Command{ - Name: "validator-info", - ShortName: "vi", - Usage: "Show the information of the validator.", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: valdDaemonAddressFlag, - Usage: "Full address of the validator daemon in format tcp://:", - Value: defaultValdDaemonAddress, - }, - cli.StringFlag{ - Name: valBabylonPkFlag, - Usage: "The hex string of the Babylon public key", - Required: true, - }, - }, - Action: valInfoDaemon, -} - -func valInfoDaemon(ctx *cli.Context) error { - daemonAddress := ctx.String(valdDaemonAddressFlag) - rpcClient, cleanUp, err := dc.NewValidatorServiceGRpcClient(daemonAddress) - if err != nil { - return err - } - defer cleanUp() - - bbnPkBytes, err := hex.DecodeString(ctx.String(valBabylonPkFlag)) - if err != nil { - return err - } - - resp, err := rpcClient.QueryValidatorInfo(context.Background(), bbnPkBytes) - if err != nil { - return err - } - - printRespJSON(resp) - - return nil -} - -var registerValDaemonCmd = cli.Command{ - Name: "register-validator", - ShortName: "rv", - Usage: "Register a created Bitcoin validator to Babylon.", - UsageText: fmt.Sprintf("register-validator --%s [key-name]", keyNameFlag), - Flags: []cli.Flag{ - cli.StringFlag{ - Name: valdDaemonAddressFlag, - Usage: "Full address of the validator daemon in format tcp://:", - Value: defaultValdDaemonAddress, - }, - cli.StringFlag{ - Name: keyNameFlag, - Usage: "The unique name of the validator key", - Required: true, - }, - }, - Action: registerVal, -} - -func registerVal(ctx *cli.Context) error { - keyName := ctx.String(keyNameFlag) - - daemonAddress := ctx.String(valdDaemonAddressFlag) - rpcClient, cleanUp, err := dc.NewValidatorServiceGRpcClient(daemonAddress) - if err != nil { - return err - } - defer cleanUp() - - res, err := rpcClient.RegisterValidator(context.Background(), keyName) - if err != nil { - return err - } - - printRespJSON(res) - - return nil -} - -// addFinalitySigDaemonCmd allows manual submission of finality signatures -// NOTE: should only be used for presentation/testing purposes -var addFinalitySigDaemonCmd = cli.Command{ - Name: "add-finality-sig", - ShortName: "afs", - Usage: "Send a finality signature to Babylon. This command should only be used for presentation/testing purposes", - UsageText: fmt.Sprintf("add-finality-sig --%s [babylon_pk_hex]", valBabylonPkFlag), - Flags: []cli.Flag{ - cli.StringFlag{ - Name: valdDaemonAddressFlag, - Usage: "Full address of the validator daemon in format tcp://:", - Value: defaultValdDaemonAddress, - }, - cli.StringFlag{ - Name: valBabylonPkFlag, - Usage: "The hex string of the Babylon public key", - Required: true, - }, - cli.Uint64Flag{ - Name: blockHeightFlag, - Usage: "The height of the Babylon block", - Required: true, - }, - cli.StringFlag{ - Name: lastCommitHashFlag, - Usage: "The last commit hash of the Babylon block", - Value: defaultLastCommitHashStr, - }, - }, - Action: addFinalitySig, -} - -func addFinalitySig(ctx *cli.Context) error { - daemonAddress := ctx.String(valdDaemonAddressFlag) - rpcClient, cleanUp, err := dc.NewValidatorServiceGRpcClient(daemonAddress) - if err != nil { - return err - } - defer cleanUp() - - bbnPk, err := proto.NewBabylonPkFromHex(ctx.String(valBabylonPkFlag)) - if err != nil { - return err - } - - lch, err := types.NewLastCommitHashFromHex(ctx.String(lastCommitHashFlag)) - if err != nil { - return err - } - - res, err := rpcClient.AddFinalitySignature( - context.Background(), bbnPk.Key, ctx.Uint64(blockHeightFlag), lch) - if err != nil { - return err - } - - printRespJSON(res) - - return nil -} diff --git a/cmd/valcli/jury.go b/cmd/valcli/jury.go deleted file mode 100644 index 13a78c45..00000000 --- a/cmd/valcli/jury.go +++ /dev/null @@ -1,92 +0,0 @@ -package main - -import ( - "fmt" - "github.com/babylonchain/babylon/types" - - "github.com/urfave/cli" - - "github.com/babylonchain/btc-validator/service" - "github.com/babylonchain/btc-validator/val" -) - -type juryKey struct { - Name string `json:"name"` - PublicKey string `json:"public-key"` -} - -var juryCommands = []cli.Command{ - { - Name: "jury", - ShortName: "j", - Usage: "Control Babylon Jury.", - Category: "Jury", - Subcommands: []cli.Command{ - createJury, - }, - }, -} - -var createJury = cli.Command{ - Name: "create-jury", - ShortName: "cj", - Usage: "Create a Jury account in the keyring.", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: chainIdFlag, - Usage: "The chainID of the Babylonchain", - Value: defaultChainID, - }, - cli.StringFlag{ - Name: keyNameFlag, - Usage: "The unique name of the Jury key", - Required: true, - }, - cli.StringFlag{ - Name: keyringBackendFlag, - Usage: "Select keyring's backend (os|file|test)", - Value: defaultKeyringBackend, - }, - cli.StringFlag{ - Name: keyringDirFlag, - Usage: "The directory where the keyring is stored", - }, - }, - Action: createJuryKey, -} - -func createJuryKey(ctx *cli.Context) error { - sdkCtx, err := service.CreateClientCtx( - ctx.String(keyringDirFlag), - ctx.String(chainIdFlag), - ) - if err != nil { - return err - } - - krController, err := val.NewKeyringController( - sdkCtx, - ctx.String(keyNameFlag), - ctx.String(keyringBackendFlag), - ) - if err != nil { - return err - } - - if krController.JuryKeyTaken() { - return fmt.Errorf("the Jury key name %s is taken", krController.GetKeyName()) - } - - juryPk, err := krController.CreateJuryKey() - if err != nil { - return fmt.Errorf("failed to create Jury key: %w", err) - } - - bip340Key := types.NewBIP340PubKeyFromBTCPK(juryPk) - printRespJSON(&juryKey{ - Name: krController.GetKeyName(), - PublicKey: bip340Key.MarshalHex(), - }) - - return err -} diff --git a/cmd/valcli/main.go b/cmd/valcli/main.go deleted file mode 100644 index a5a593db..00000000 --- a/cmd/valcli/main.go +++ /dev/null @@ -1,64 +0,0 @@ -package main - -import ( - "encoding/json" - "fmt" - "os" - - "github.com/urfave/cli" - - "github.com/babylonchain/btc-validator/valcfg" -) - -func fatal(err error) { - fmt.Fprintf(os.Stderr, "[btc-validator] %v\n", err) - os.Exit(1) -} - -func printRespJSON(resp interface{}) { - jsonBytes, err := json.MarshalIndent(resp, "", " ") - if err != nil { - fmt.Println("unable to decode response: ", err) - return - } - - fmt.Printf("%s\n", jsonBytes) -} - -const ( - dbTypeFlag = "db-type" - dbPathFlag = "db-path" - dbNameFlag = "db-name" -) - -func main() { - app := cli.NewApp() - app.Name = "valcli" - app.Usage = "Control plane for the Bitcoin Validator Daemon (vald)." - app.Flags = []cli.Flag{ - cli.StringFlag{ - Name: dbTypeFlag, - Usage: "The type of the database", - Value: valcfg.DefaultBackend, - }, - cli.StringFlag{ - Name: dbPathFlag, - Usage: "The path of the database file", - Value: valcfg.DefaultDBPath, - }, - cli.StringFlag{ - Name: dbNameFlag, - Usage: "The name of the database bucket", - Value: valcfg.DefaultDBName, - }, - } - - app.Commands = append(app.Commands, daemonCommands...) - app.Commands = append(app.Commands, validatorsCommands...) - app.Commands = append(app.Commands, adminCommands...) - app.Commands = append(app.Commands, juryCommands...) - - if err := app.Run(os.Args); err != nil { - fatal(err) - } -} diff --git a/cmd/valcli/validators.go b/cmd/valcli/validators.go deleted file mode 100644 index a69accf9..00000000 --- a/cmd/valcli/validators.go +++ /dev/null @@ -1,220 +0,0 @@ -package main - -import ( - "encoding/hex" - "fmt" - - "cosmossdk.io/math" - "github.com/urfave/cli" - - "github.com/babylonchain/btc-validator/proto" - "github.com/babylonchain/btc-validator/service" - "github.com/babylonchain/btc-validator/val" - "github.com/babylonchain/btc-validator/valcfg" -) - -const ( - chainIdFlag = "chain-id" - keyringDirFlag = "keyring-dir" - keyringBackendFlag = "keyring-backend" - defaultChainID = "chain-test" - defaultKeyringBackend = "test" -) - -var validatorsCommands = []cli.Command{ - { - Name: "validators", - ShortName: "vals", - Usage: "Control Bitcoin validators.", - Category: "Validators", - Subcommands: []cli.Command{ - createValCmd, listValCmd, importValCmd, - }, - }, -} - -var createValCmd = cli.Command{ - Name: "create-validator", - ShortName: "cv", - Usage: "Create a Bitcoin validator object and save it in database.", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: chainIdFlag, - Usage: "The chainID of the Babylonchain", - Value: defaultChainID, - }, - cli.StringFlag{ - Name: keyNameFlag, - Usage: "The unique name of the validator key", - Required: true, - }, - cli.StringFlag{ - Name: keyringBackendFlag, - Usage: "Select keyring's backend (os|file|test)", - Value: defaultKeyringBackend, - }, - cli.StringFlag{ - Name: keyringDirFlag, - Usage: "The directory where the keyring is stored", - }, - cli.StringFlag{ - Name: commissionRateFlag, - Usage: "The commission rate for the validator, e.g., 0.05", - Value: "0.05", - }, - cli.StringFlag{ - Name: monikerFlag, - Usage: "A human-readable name for the validator", - Value: "", - }, - cli.StringFlag{ - Name: identityFlag, - Usage: "An optional identity signature (ex. UPort or Keybase)", - Value: "", - }, - cli.StringFlag{ - Name: websiteFlag, - Usage: "An optional website link", - Value: "", - }, - cli.StringFlag{ - Name: securityContractFlag, - Usage: "An optional email for security contact", - Value: "", - }, - cli.StringFlag{ - Name: detailsFlag, - Usage: "Other optional details", - Value: "", - }, - }, - Action: createVal, -} - -func createVal(ctx *cli.Context) error { - sdkCtx, err := service.CreateClientCtx( - ctx.String(keyringDirFlag), - ctx.String(chainIdFlag), - ) - if err != nil { - return err - } - - krController, err := val.NewKeyringController( - sdkCtx, - ctx.String(keyNameFlag), - ctx.String(keyringBackendFlag), - ) - if err != nil { - return err - } - - commissionRate, err := math.LegacyNewDecFromStr(ctx.String(commissionRateFlag)) - if err != nil { - return err - } - - if krController.ValidatorKeyNameTaken() { - return fmt.Errorf("the key name %s is taken", krController.GetKeyName()) - } - - description, err := getDesciptionFromContext(ctx) - if err != nil { - return err - } - - btcPk, bbnPk, err := krController.CreateValidatorKeys() - if err != nil { - return err - } - - pop, err := krController.CreatePop() - if err != nil { - return err - } - - validator := val.NewStoreValidator(bbnPk, btcPk, krController.GetKeyName(), pop, &description, &commissionRate) - - vs, err := getValStoreFromCtx(ctx) - if err != nil { - return err - } - defer func() { - err = vs.Close() - }() - - if err := vs.SaveValidator(validator); err != nil { - return err - } - - printRespJSON(&proto.CreateValidatorResponse{ - BabylonPk: hex.EncodeToString(validator.BabylonPk), - BtcPk: hex.EncodeToString(validator.BtcPk), - }) - - return err -} - -var listValCmd = cli.Command{ - Name: "list-validators", - ShortName: "ls", - Usage: "List validators stored in the database.", - Action: lsVal, -} - -func lsVal(ctx *cli.Context) error { - vs, err := getValStoreFromCtx(ctx) - if err != nil { - return err - } - defer func() { - err = vs.Close() - }() - - valList, err := vs.ListValidators() - if err != nil { - return err - } - - valsInfo := make([]*proto.ValidatorInfo, len(valList)) - for i, v := range valList { - valInfo := proto.NewValidatorInfo(v) - valsInfo[i] = valInfo - } - - printRespJSON(&proto.QueryValidatorListResponse{Validators: valsInfo}) - - return nil -} - -var importValCmd = cli.Command{ - Name: "import-validator", - ShortName: "iv", - Usage: "Import a Bitcoin validator object with given Bitcoin and Babylon addresses.", - Flags: []cli.Flag{ - // TODO: add flags - }, - Action: importVal, -} - -func importVal(ctx *cli.Context) error { - panic("implement me") -} - -func getValStoreFromCtx(ctx *cli.Context) (*val.ValidatorStore, error) { - dbcfg, err := valcfg.NewDatabaseConfig( - ctx.GlobalString(dbTypeFlag), - ctx.GlobalString(dbPathFlag), - ctx.GlobalString(dbNameFlag), - ) - if err != nil { - return nil, fmt.Errorf("invalid DB config: %w", err) - } - - valStore, err := val.NewValidatorStore(dbcfg) - if err != nil { - return nil, fmt.Errorf("failed to open the store: %w", err) - } - - return valStore, nil -} diff --git a/cmd/vald/main.go b/cmd/vald/main.go deleted file mode 100644 index 48afde5b..00000000 --- a/cmd/vald/main.go +++ /dev/null @@ -1,61 +0,0 @@ -package main - -import ( - "fmt" - "os" - - "github.com/jessevdk/go-flags" - "github.com/lightningnetwork/lnd/signal" - - "github.com/babylonchain/btc-validator/clientcontroller" - "github.com/babylonchain/btc-validator/service" - "github.com/babylonchain/btc-validator/valcfg" -) - -func main() { - // Hook interceptor for os signals. - shutdownInterceptor, err := signal.Intercept() - if err != nil { - _, _ = fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } - - cfg, cfgLogger, err := valcfg.LoadConfig() - if err != nil { - if e, ok := err.(*flags.Error); !ok || e.Type != flags.ErrHelp { - // Print error if not due to help request. - err = fmt.Errorf("failed to load config: %w", err) - _, _ = fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } - - // Help was requested, exit normally. - os.Exit(0) - } - - cc, err := clientcontroller.NewClientController(cfg, cfgLogger) - if err != nil { - cfgLogger.Errorf("failed to create rpc client for the consumer chain %s: %v", cfg.ChainName, err) - os.Exit(1) - } - - valApp, err := service.NewValidatorAppFromConfig(cfg, cfgLogger, cc) - if err != nil { - cfgLogger.Errorf("failed to create validator app: %v", err) - os.Exit(1) - } - // start app event loop - // TODO: graceful shutdown - if err := valApp.Start(); err != nil { - _, _ = fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } - - valServer := service.NewValidatorServer(cfg, cfgLogger, valApp, shutdownInterceptor) - - err = valServer.RunUntilShutdown() - if err != nil { - _, _ = fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } -} diff --git a/valcfg/babylon.go b/config/babylon.go similarity index 61% rename from valcfg/babylon.go rename to config/babylon.go index 12d40483..ee97f80b 100644 --- a/valcfg/babylon.go +++ b/config/babylon.go @@ -1,9 +1,9 @@ -package valcfg +package config import ( "time" - "github.com/cosmos/relayer/v2/relayer/chains/cosmos" + bbncfg "github.com/babylonchain/rpc-client/config" ) type BBNConfig struct { @@ -24,41 +24,42 @@ type BBNConfig struct { } func DefaultBBNConfig() BBNConfig { - //fill up the config from dc config + dc := bbncfg.DefaultBabylonConfig() + // fill up the config from dc config return BBNConfig{ - Key: "node0", - ChainID: "chain-test", - RPCAddr: "http://localhost:26657", - GRPCAddr: "https://localhost:9090", - AccountPrefix: "bbn", - KeyringBackend: "test", - GasAdjustment: 1.2, - GasPrices: "0.01ubbn", - KeyDirectory: defaultDataDir, - Debug: true, - Timeout: 20 * time.Second, + Key: dc.Key, + ChainID: dc.ChainID, + RPCAddr: dc.RPCAddr, + GRPCAddr: dc.GRPCAddr, + AccountPrefix: dc.AccountPrefix, + KeyringBackend: dc.KeyringBackend, + GasAdjustment: 1.5, + GasPrices: "0.002ubbn", + Debug: dc.Debug, + Timeout: dc.Timeout, // Setting this to relatively low value, out currnet babylon client (lens) will // block for this amout of time to wait for transaction inclusion in block BlockTimeout: 1 * time.Minute, - OutputFormat: "json", - SignModeStr: "direct", + OutputFormat: dc.OutputFormat, + SignModeStr: dc.SignModeStr, } } -func BBNConfigToCosmosProviderConfig(bc *BBNConfig) cosmos.CosmosProviderConfig { - return cosmos.CosmosProviderConfig{ - Key: bc.Key, - ChainID: bc.ChainID, - RPCAddr: bc.RPCAddr, - AccountPrefix: bc.AccountPrefix, - KeyringBackend: bc.KeyringBackend, - GasAdjustment: bc.GasAdjustment, - GasPrices: bc.GasPrices, - KeyDirectory: bc.KeyDirectory, - Debug: bc.Debug, - Timeout: bc.Timeout.String(), - BlockTimeout: bc.BlockTimeout.String(), - OutputFormat: bc.OutputFormat, - SignModeStr: bc.SignModeStr, +func BBNConfigToBabylonConfig(bc *BBNConfig) bbncfg.BabylonConfig { + return bbncfg.BabylonConfig{ + Key: bc.Key, + ChainID: bc.ChainID, + RPCAddr: bc.RPCAddr, + AccountPrefix: bc.AccountPrefix, + KeyringBackend: bc.KeyringBackend, + GasAdjustment: bc.GasAdjustment, + GasPrices: bc.GasPrices, + KeyDirectory: bc.KeyDirectory, + Debug: bc.Debug, + Timeout: bc.Timeout, + BlockTimeout: bc.BlockTimeout, + OutputFormat: bc.OutputFormat, + SignModeStr: bc.SignModeStr, + SubmitterAddress: "", } } diff --git a/valcfg/dbcfg.go b/config/db.go similarity index 67% rename from valcfg/dbcfg.go rename to config/db.go index 181fe994..e19be729 100644 --- a/valcfg/dbcfg.go +++ b/config/db.go @@ -1,36 +1,29 @@ -package valcfg +package config import "fmt" const ( DefaultBackend = "bbolt" - DefaultDBPath = "bbolt.db" DefaultDBName = "default" ) type DatabaseConfig struct { Backend string `long:"backend" description:"Possible database to choose as backend"` - Path string `long:"path" description:"The path that stores the database file"` Name string `long:"name" description:"The name of the database"` } -func NewDatabaseConfig(backend string, path string, name string) (*DatabaseConfig, error) { +func NewDatabaseConfig(backend string, name string) (*DatabaseConfig, error) { // TODO: add more supported DB types, currently we only support bbolt if backend != DefaultBackend { return nil, fmt.Errorf("unsupported DB backend") } - if path == "" { - return nil, fmt.Errorf("DB path should not be empty") - } - if name == "" { return nil, fmt.Errorf("bucket name should not be empty") } return &DatabaseConfig{ Backend: backend, - Path: path, Name: name, }, nil } @@ -38,7 +31,6 @@ func NewDatabaseConfig(backend string, path string, name string) (*DatabaseConfi func DefaultDatabaseConfig() DatabaseConfig { return DatabaseConfig{ Backend: DefaultBackend, - Path: DefaultDBPath, Name: DefaultDBName, } } diff --git a/docs/eots.md b/docs/eots.md new file mode 100644 index 00000000..b7f14dd3 --- /dev/null +++ b/docs/eots.md @@ -0,0 +1,107 @@ +# EOTS Manager + +## 1. Overview + +The EOTS daemon is responsible for managing EOTS keys, +producing EOTS randomness, and using them to produce EOTS signatures. + +**Note:** EOTS stands for Extractable One Time Signature. You can read more about it +in +the [Babylon BTC Staking Litepaper](https://docs.babylonchain.io/assets/files/btc_staking_litepaper-32bfea0c243773f0bfac63e148387aef.pdf). +In short, the EOTS manager produces EOTS public/private randomness pairs. +The finality provider commits the public part of this pairs to Babylon for +every future block height that they intend to provide a finality signature for. +If the finality provider votes for two different blocks on the same height, +they will have to reuse the same private randomness which will lead to their +underlying private key being exposed, leading to the slashing of them and all their delegators. + +The EOTS manager is responsible for the following operations: +1. **EOTS Key Management:** + - Generates [Schnorr](https://en.wikipedia.org/wiki/Schnorr_signature) key pairs + for a given finality provider using the + [BIP-340](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki) + standard. + - Persists generated key pairs in the + internal Cosmos keyring. +2. **Randomness Generation:** + - Generates lists of EOTS randomness pairs based on the EOTS key, chainID, and + block height. + - The randomness is deterministically generated and tied to specific parameters. +3. **Signature Generation:** + - Signs EOTS using the private key of the finality provider and the corresponding secret + randomness for a given chain at a specified height. + - Signs Schnorr signatures using the private key of the finality provider. + +The EOTS manager functions as a daemon controlled by the `eotsd` tool. + +## 2. Configuration + +The `eotsd init` command initializes a home directory for the EOTS +manager. This directory is created in the default home location or in a location +specified by the `--home` flag. + +```bash +eotsd init --home /path/to/eotsd/home/ +``` + +After initialization, the home directory will have the following structure + +```bash +ls /path/to/eotsd/home/ + ├── eotsd.conf # Eotsd-specific configuration file. + ├── logs # Eotsd logs +``` + +If the `--home` flag is not specified, then the default home location will +be used. For different operating systems, those are: + +- **MacOS** `~/Users//Library/Application Support/Eotsd` +- **Linux** `~/.Eotsd` +- **Windows** `C:\Users\\AppData\Local\Eotsd` + +Below are the `eotsd.conf` file contents: + +```bash +# Default address to listen for RPC connections +RpcListener = 127.0.0.1:12582 + +# Type of keyring to use +KeyringBackend = test + +# Possible database to choose as backend +Backend = bbolt + +# Path to the database +Path = bbolt-eots.db + +# Name of the database +Name = default +``` + +## 3. Starting the EOTS Daemon + +You can start the EOTS daemon using the following command: + +```bash +eotsd start --home /path/to/eotsd/home +``` + +This will start the rpc server at the address specified in the configuration under +the `RpcListener` field, which has a default value of `127.0.0.1:12582`. +You can also specify a custom address using the `--rpc-listener` flag. + +```bash +eotsd start + +time="2023-11-26T16:35:04-05:00" level=info msg="RPC server listening {"address": "127.0.0.1:12582"}" +time="2023-11-26T16:35:04-05:00" level=info msg="EOTS Manager Daemon is fully active!" +``` + +All the available cli options can be viewed using the `--help` flag. These options +can also be set in the configuration file. + +**Note**: It is recommended to run the `eotsd` daemon on a separate machine or +network segment to enhance security. This helps isolate the key management +functionality and reduces the potential attack surface. You can edit the +`EOTSManagerAddress` in the configuration file of the finality provider +to reference the address of the machine where `eotsd` is running. diff --git a/docs/finality-provider.md b/docs/finality-provider.md new file mode 100644 index 00000000..ecd4949c --- /dev/null +++ b/docs/finality-provider.md @@ -0,0 +1,226 @@ +# Finality Provider + +## 1. Overview + +The Finality Provider Daemon is responsible for +monitoring for new Babylon blocks, +committing public randomness for the blocks it +intends to provide finality signatures for, and +submitting finality signatures. + +The daemon can manage and perform the following operations for multiple +finality providers: +1. **Creation and Registration**: Creates and registers finality + providers to Babylon. +2. **EOTS Randomness Commitment**: The daemon monitors the Babylon chain and + commits EOTS public randomness for every Babylon block each + finality provider intends to vote for. The commit intervals can be specified + in the configuration. + The EOTS public randomness is retrieved through the finality provider daemon's + connection with the [EOTS daemon](eots.md). +3. **Finality Votes Submission**: The daemon monitors the Babylon chain + and produces finality votes for each block each maintained finality provider + has committed to vote for. + +The daemon is controlled by the `fpd` tool. +The `fpcli` tool implements commands for interacting with the daemon. + +## 2. Configuration + +The `fpd init` command initializes a home directory for the +finality provider daemon. +This directory is created in the default home location or in a +location specified by the `--home` flag. + +```bash +fpd init --home /path/to/fpd/home/ +``` + +After initialization, the home directory will have the following structure + +```bash +ls /path/to/fpd/home/ + ├── fpd.conf # Fpd-specific configuration file. + ├── logs # Fpd logs +``` + +If the `--home` flag is not specified, then the default home directory +will be used. For different operating systems, those are: + +- **MacOS** `~/Users//Library/Application Support/Fpd` +- **Linux** `~/.Fpd` +- **Windows** `C:\Users\\AppData\Local\Fpd` + +Below are some important parameters of the `fpd.conf` file. + +**Note**: +The configuration below requires to point to the path where this keyring is +stored `KeyDirectory`. This `Key` field stores the key name used for +interacting with the consumer chain and will be specified along with the +`KeyringBackend` field in the next [step](#3-add-key-for-the-consumer-chain). +So we can ignore the setting of the two fields in this step. + +```bash +# RPC Address of the EOTS Daemon +EOTSManagerAddress = 127.0.0.1:12582 + +# Babylon specific parameters + +# Babylon chain ID +ChainID = chain-test + +# Babylon node RPC endpoint +RPCAddr = http://127.0.0.1:26657 + +# Babylon node gRPC endpoint +GRPCAddr = https://127.0.0.1:9090 + +# Name of the key in the keyring to use for signing transactions +Key = + +# Type of keyring to use +KeyringBackend = test + +# Directory where keys will be retrieved from and stored +KeyDirectory = /path/to/fpd/home +``` + +To see the complete list of configuration options, check the `fpd.conf` file. + +**Additional Notes:** + +1. We strongly recommend that EOTS randomness commitments are limited to 500 + blocks (default value: 100 blocks) + + ```bash + ; The number of Schnorr public randomness for each commitment + NumPubRand = 100 + + ; The upper bound of the number of Schnorr public randomness for each commitment + NumPubRandMax = 100 + ``` + +2. If you encounter any gas-related errors while performing staking operations, + consider adjusting the `GasAdjustment` and `GasPrices` parameters. For example, + you can set: + + ```bash + GasAdjustment = 1.5 + GasPrices = 0.01ubbn + ``` + +## 3. Add key for the consumer chain + +The finality provider daemon requires the existence of a keyring that contains +an account with Babylon token funds to pay for transactions. +This key will be also used to pay for fees of transactions to the consumer chain. + +Use the following command to add the key: + +```bash +fpd keys add --key-name my-finality-provider --chain-id chain-test +``` + +After executing the above command, the key name will be saved in the config file +created in [step](#2-configuration). + +## 4. Starting the Finality Provider Daemon + +You can start the finality provider daemon using the following command: + +```bash +fpd start --home /path/to/fpd/home +``` + +This will start the RPC server at the address specified in the configuration +under the `RpcListener` field, which has a default value of `127.0.0.1:12581`. +You can also specify a custom address using the `--rpc-listener` flag. + +This will also start all the registered finality provider instances except for +slashed ones added in [step](#5-create-and-register-a-finality-provider). +To start the daemon with a specific finality provider instance, use the +`--btc-pk` flag followed by the hex string of the BTC public key of the +finality provider (`btc_pk_hex`) obtained in [step](#5-create-and-register-a-finality-provider). + +```bash +fpd start --rpc-listener '127.0.0.1:8088' + +time="2023-11-26T16:37:00-05:00" level=info msg="successfully connected to a remote EOTS manager {"address": "127.0.0.1:12582"}" +time="2023-11-26T16:37:00-05:00" level=info msg="Starting FinalityProviderApp" +time="2023-11-26T16:37:00-05:00" level=info msg="Starting RPC Server" +time="2023-11-26T16:37:00-05:00" level=info msg="RPC server listening {"address": "127.0.0.1:12581"}" +time="2023-11-26T16:37:00-05:00" level=info msg="Finality Provider Daemon is fully active!" +``` + +All the available CLI options can be viewed using the `--help` flag. +These options can also be set in the configuration file. + +## 5. Create and Register a Finality Provider + +We create a finality provider instance through the +`fpcli create-finality-provider` or `fpcli cfp` command. +The created instance is associated with a BTC public key which +serves as its unique identifier and +a Babylon account to which staking rewards will be directed. +Note that if the `--key-name` flag is not specified, the `Key` field of +config specified in [step](#3-add-key-for-the-consumer-chain) will be used. + +```bash +fpcli create-finality-provider --key-name my-finality-provider \ + --chain-id chain-test --moniker my-name +{ + "babylon_pk_hex": "02face5996b2792114677604ec9dfad4fe66eeace3df92dab834754add5bdd7077", + "btc_pk_hex": "d0fc4db48643fbb4339dc4bbf15f272411716b0d60f18bdfeb3861544bf5ef63", + "description": { + "moniker": "my-name" + }, + "status": "CREATED" +} +``` + +We register a created finality provider in Babylon through +the `fpcli register-finality-provider` or `fpcli rfp` command. +The output contains the hash of the Babylon finality provider registration +transaction. + +```bash +fpcli register-finality-provider \ + --btc-pk d0fc4db48643fbb4339dc4bbf15f272411716b0d60f18bdfeb3861544bf5ef63 +{ + "tx_hash": "800AE5BBDADE974C5FA5BD44336C7F1A952FAB9F5F9B43F7D4850BA449319BAA" +} +``` + +A finality provider instance will be initiated and start running right after +the finality provider is successfully registered in Babylon. + +We can view the status of all the running finality providers through +the `fpcli list-finality-providers` or `fpcli ls` command. +The `status` field can receive the following values: + +- `CREATED`: The finality provider is created but not registered yet +- `REGISTERED`: The finality provider is registered but has not received any + active delegations yet +- `ACTIVE`: The finality provider has active delegations and is empowered to + send finality signatures +- `INACTIVE`: The finality provider used to be ACTIVE but the voting power is + reduced to zero +- `SLASHED`: The finality provider is slashed due to malicious behavior + +```bash +fpcli list-finality-providers +{ + "finality-providers": [ + ... + { + "babylon_pk_hex": "02face5996b2792114677604ec9dfad4fe66eeace3df92dab834754add5bdd7077", + "btc_pk_hex": "d0fc4db48643fbb4339dc4bbf15f272411716b0d60f18bdfeb3861544bf5ef63", + "description": { + "moniker": "my-name" + }, + "last_vote_height": 1 + "status": "REGISTERED" + } + ] +} +``` diff --git a/docs/finality-toolset.png b/docs/finality-toolset.png new file mode 100644 index 00000000..c165ba21 Binary files /dev/null and b/docs/finality-toolset.png differ diff --git a/eotsmanager/Makefile b/eotsmanager/Makefile new file mode 100644 index 00000000..abc4da72 --- /dev/null +++ b/eotsmanager/Makefile @@ -0,0 +1,10 @@ +############################################################################### +### Protobuf ### +############################################################################### + +proto-all: proto-gen + +proto-gen: + ./proto/scripts/protocgen.sh + +.PHONY: proto-gen diff --git a/eotsmanager/client/rpcclient.go b/eotsmanager/client/rpcclient.go new file mode 100644 index 00000000..585e9daf --- /dev/null +++ b/eotsmanager/client/rpcclient.go @@ -0,0 +1,138 @@ +package client + +import ( + "context" + "fmt" + + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/schnorr" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + + "github.com/babylonchain/finality-provider/eotsmanager" + "github.com/babylonchain/finality-provider/eotsmanager/proto" + "github.com/babylonchain/finality-provider/eotsmanager/types" +) + +var _ eotsmanager.EOTSManager = &EOTSManagerGRpcClient{} + +type EOTSManagerGRpcClient struct { + client proto.EOTSManagerClient + conn *grpc.ClientConn +} + +func NewEOTSManagerGRpcClient(remoteAddr string) (*EOTSManagerGRpcClient, error) { + conn, err := grpc.Dial(remoteAddr, grpc.WithTransportCredentials(insecure.NewCredentials())) + if err != nil { + return nil, fmt.Errorf("failed to build gRPC connection to %s: %w", remoteAddr, err) + } + + gClient := &EOTSManagerGRpcClient{ + client: proto.NewEOTSManagerClient(conn), + conn: conn, + } + + if err := gClient.Ping(); err != nil { + return nil, fmt.Errorf("the EOTS manager server is not responding: %w", err) + } + + return gClient, nil +} + +func (c *EOTSManagerGRpcClient) Ping() error { + req := &proto.PingRequest{} + + _, err := c.client.Ping(context.Background(), req) + if err != nil { + return err + } + + return nil +} + +func (c *EOTSManagerGRpcClient) CreateKey(name, passphrase, hdPath string) ([]byte, error) { + req := &proto.CreateKeyRequest{Name: name, Passphrase: passphrase, HdPath: hdPath} + res, err := c.client.CreateKey(context.Background(), req) + if err != nil { + return nil, err + } + + return res.Pk, nil +} + +func (c *EOTSManagerGRpcClient) CreateRandomnessPairList(uid, chainID []byte, startHeight uint64, num uint32, passphrase string) ([]*btcec.FieldVal, error) { + req := &proto.CreateRandomnessPairListRequest{ + Uid: uid, + ChainId: chainID, + StartHeight: startHeight, + Num: num, + Passphrase: passphrase, + } + res, err := c.client.CreateRandomnessPairList(context.Background(), req) + if err != nil { + return nil, err + } + + pubRandFieldValList := make([]*btcec.FieldVal, 0, len(res.PubRandList)) + for _, r := range res.PubRandList { + var fieldVal btcec.FieldVal + fieldVal.SetByteSlice(r) + pubRandFieldValList = append(pubRandFieldValList, &fieldVal) + } + + return pubRandFieldValList, nil +} + +func (c *EOTSManagerGRpcClient) KeyRecord(uid []byte, passphrase string) (*types.KeyRecord, error) { + req := &proto.KeyRecordRequest{Uid: uid, Passphrase: passphrase} + + res, err := c.client.KeyRecord(context.Background(), req) + if err != nil { + return nil, err + } + + privKey, _ := btcec.PrivKeyFromBytes(res.PrivateKey) + + return &types.KeyRecord{ + Name: res.Name, + PrivKey: privKey, + }, nil +} + +func (c *EOTSManagerGRpcClient) SignEOTS(uid, chaiID, msg []byte, height uint64, passphrase string) (*btcec.ModNScalar, error) { + req := &proto.SignEOTSRequest{ + Uid: uid, + ChainId: chaiID, + Msg: msg, + Height: height, + Passphrase: passphrase, + } + res, err := c.client.SignEOTS(context.Background(), req) + if err != nil { + return nil, err + } + + var s btcec.ModNScalar + s.SetByteSlice(res.Sig) + + return &s, nil +} + +func (c *EOTSManagerGRpcClient) SignSchnorrSig(uid, msg []byte, passphrase string) (*schnorr.Signature, error) { + req := &proto.SignSchnorrSigRequest{Uid: uid, Msg: msg, Passphrase: passphrase} + res, err := c.client.SignSchnorrSig(context.Background(), req) + if err != nil { + return nil, err + } + + sig, err := schnorr.ParseSignature(res.Sig) + if err != nil { + return nil, err + } + + return sig, nil +} + +func (c *EOTSManagerGRpcClient) Close() error { + return c.conn.Close() +} diff --git a/eotsmanager/cmd/eotsd/flags.go b/eotsmanager/cmd/eotsd/flags.go new file mode 100644 index 00000000..5f0b2033 --- /dev/null +++ b/eotsmanager/cmd/eotsd/flags.go @@ -0,0 +1,7 @@ +package main + +const ( + homeFlag = "home" + forceFlag = "force" + rpcListenerFlag = "rpc-listener" +) diff --git a/eotsmanager/cmd/eotsd/init.go b/eotsmanager/cmd/eotsd/init.go new file mode 100644 index 00000000..faf0389a --- /dev/null +++ b/eotsmanager/cmd/eotsd/init.go @@ -0,0 +1,63 @@ +package main + +import ( + "fmt" + "path/filepath" + + "github.com/jessevdk/go-flags" + "github.com/urfave/cli" + + eotscfg "github.com/babylonchain/finality-provider/eotsmanager/config" + "github.com/babylonchain/finality-provider/util" +) + +var initCommand = cli.Command{ + Name: "init", + Usage: "Initialize the eotsd home directory.", + Flags: []cli.Flag{ + cli.StringFlag{ + Name: homeFlag, + Usage: "Path to where the home directory will be initialized", + Value: eotscfg.DefaultEOTSDir, + }, + cli.BoolFlag{ + Name: forceFlag, + Usage: "Override existing configuration", + Required: false, + }, + }, + Action: initHome, +} + +func initHome(c *cli.Context) error { + homePath, err := filepath.Abs(c.String(homeFlag)) + if err != nil { + return err + } + // Create home directory + homePath = util.CleanAndExpandPath(homePath) + force := c.Bool(forceFlag) + + if util.FileExists(homePath) && !force { + return fmt.Errorf("home path %s already exists", homePath) + } + + if err := util.MakeDirectory(homePath); err != nil { + return err + } + // Create log directory + logDir := eotscfg.LogDir(homePath) + if err := util.MakeDirectory(logDir); err != nil { + return err + } + // Create data directory + dataDir := eotscfg.DataDir(homePath) + if err := util.MakeDirectory(dataDir); err != nil { + return err + } + + defaultConfig := eotscfg.DefaultConfig() + fileParser := flags.NewParser(&defaultConfig, flags.Default) + + return flags.NewIniParser(fileParser).WriteFile(eotscfg.ConfigFile(homePath), flags.IniIncludeComments|flags.IniIncludeDefaults) +} diff --git a/eotsmanager/cmd/eotsd/main.go b/eotsmanager/cmd/eotsd/main.go new file mode 100644 index 00000000..e9380374 --- /dev/null +++ b/eotsmanager/cmd/eotsd/main.go @@ -0,0 +1,23 @@ +package main + +import ( + "fmt" + "github.com/urfave/cli" + "os" +) + +func fatal(err error) { + fmt.Fprintf(os.Stderr, "[eotsd] %v\n", err) + os.Exit(1) +} + +func main() { + app := cli.NewApp() + app.Name = "eotsd" + app.Usage = "Extractable One Time Signature Daemon (eotsd)." + app.Commands = append(app.Commands, startCommand, initCommand) + + if err := app.Run(os.Args); err != nil { + fatal(err) + } +} diff --git a/eotsmanager/cmd/eotsd/start.go b/eotsmanager/cmd/eotsd/start.go new file mode 100644 index 00000000..b8abf061 --- /dev/null +++ b/eotsmanager/cmd/eotsd/start.go @@ -0,0 +1,76 @@ +package main + +import ( + "fmt" + "net" + "path/filepath" + + "github.com/lightningnetwork/lnd/signal" + "github.com/urfave/cli" + + "github.com/babylonchain/finality-provider/eotsmanager" + "github.com/babylonchain/finality-provider/eotsmanager/config" + eotsservice "github.com/babylonchain/finality-provider/eotsmanager/service" + "github.com/babylonchain/finality-provider/log" + "github.com/babylonchain/finality-provider/util" +) + +var startCommand = cli.Command{ + Name: "start", + Usage: "Start the Extractable One Time Signature Daemon.", + Description: "Start the Extractable One Time Signature Daemon.", + Flags: []cli.Flag{ + cli.StringFlag{ + Name: homeFlag, + Usage: "The path to the eotsd home directory", + Value: config.DefaultEOTSDir, + }, + cli.StringFlag{ + Name: rpcListenerFlag, + Usage: "The address that the RPC server listens to", + }, + }, + Action: startFn, +} + +func startFn(ctx *cli.Context) error { + homePath, err := filepath.Abs(ctx.String(homeFlag)) + if err != nil { + return err + } + homePath = util.CleanAndExpandPath(homePath) + + cfg, err := config.LoadConfig(homePath) + if err != nil { + return fmt.Errorf("failed to load config at %s: %w", homePath, err) + } + + rpcListener := ctx.String(rpcListenerFlag) + if rpcListener != "" { + _, err := net.ResolveTCPAddr("tcp", rpcListener) + if err != nil { + return fmt.Errorf("invalid RPC listener address %s, %w", rpcListener, err) + } + cfg.RpcListener = rpcListener + } + + logger, err := log.NewRootLoggerWithFile(config.LogFile(homePath), cfg.LogLevel) + if err != nil { + return fmt.Errorf("failed to load the logger") + } + + eotsManager, err := eotsmanager.NewLocalEOTSManager(homePath, cfg, logger) + if err != nil { + return fmt.Errorf("failed to create EOTS manager: %w", err) + } + + // Hook interceptor for os signals. + shutdownInterceptor, err := signal.Intercept() + if err != nil { + return err + } + + eotsServer := eotsservice.NewEOTSManagerServer(cfg, logger, eotsManager, shutdownInterceptor) + + return eotsServer.RunUntilShutdown() +} diff --git a/eotsmanager/config/config.go b/eotsmanager/config/config.go new file mode 100644 index 00000000..ca7161b8 --- /dev/null +++ b/eotsmanager/config/config.go @@ -0,0 +1,128 @@ +package config + +import ( + "fmt" + "net" + "path/filepath" + "strconv" + + "github.com/btcsuite/btcd/btcutil" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + "github.com/jessevdk/go-flags" + + "github.com/babylonchain/finality-provider/config" + "github.com/babylonchain/finality-provider/util" +) + +const ( + defaultLogLevel = "debug" + defaultDataDirname = "data" + defaultLogDirname = "logs" + defaultLogFilename = "eotsd.log" + defaultDBPath = "bbolt-eots.db" + defaultConfigFileName = "eotsd.conf" + DefaultRPCPort = 12582 + defaultKeyringBackend = keyring.BackendTest +) + +var ( + // DefaultEOTSDir the default EOTS home directory: + // C:\Users\\AppData\Local\ on Windows + // ~/.eotsd on Linux + // ~/Library/Application Support/Eotsd on MacOS + DefaultEOTSDir = btcutil.AppDataDir("eotsd", false) + + defaultRpcListener = "127.0.0.1:" + strconv.Itoa(DefaultRPCPort) +) + +type Config struct { + LogLevel string `long:"loglevel" description:"Logging level for all subsystems" choice:"trace" choice:"debug" choice:"info" choice:"warn" choice:"error" choice:"fatal"` + KeyringBackend string `long:"keyring-type" description:"Type of keyring to use"` + + DatabaseConfig *config.DatabaseConfig + + RpcListener string `long:"rpclistener" description:"the listener for RPC connections, e.g., 127.0.0.1:1234"` +} + +// LoadConfig initializes and parses the config using a config file and command +// line options. +// +// The configuration proceeds as follows: +// 1. Start with a default config with sane settings +// 2. Pre-parse the command line to check for an alternative config file +// 3. Load configuration file overwriting defaults with any specified options +// 4. Parse CLI options and overwrite/add any specified options +func LoadConfig(homePath string) (*Config, error) { + // The home directory is required to have a configuration file with a specific name + // under it. + cfgFile := ConfigFile(homePath) + if !util.FileExists(cfgFile) { + return nil, fmt.Errorf("specified config file does "+ + "not exist in %s", cfgFile) + } + + // Next, load any additional configuration options from the file. + var cfg Config + fileParser := flags.NewParser(&cfg, flags.Default) + err := flags.NewIniParser(fileParser).ParseFile(cfgFile) + if err != nil { + return nil, err + } + + // Make sure everything we just loaded makes sense. + if err := cfg.Validate(); err != nil { + return nil, err + } + + return &cfg, nil +} + +// Validate check the given configuration to be sane. This makes sure no +// illegal values or combination of values are set. All file system paths are +// normalized. The cleaned up config is returned on success. +func (cfg *Config) Validate() error { + _, err := net.ResolveTCPAddr("tcp", cfg.RpcListener) + if err != nil { + return fmt.Errorf("invalid RPC listener address %s, %w", cfg.RpcListener, err) + } + + if cfg.KeyringBackend == "" { + return fmt.Errorf("the keyring backend should not be empty") + } + + return nil +} + +func ConfigFile(homePath string) string { + return filepath.Join(homePath, defaultConfigFileName) +} + +func LogDir(homePath string) string { + return filepath.Join(homePath, defaultLogDirname) +} + +func LogFile(homePath string) string { + return filepath.Join(LogDir(homePath), defaultLogFilename) +} + +func DataDir(homePath string) string { + return filepath.Join(homePath, defaultDataDirname) +} + +func DBPath(homePath string) string { + return filepath.Join(DataDir(homePath), defaultDBPath) +} + +func DefaultConfig() Config { + dbCfg := config.DefaultDatabaseConfig() + cfg := Config{ + LogLevel: defaultLogLevel, + KeyringBackend: defaultKeyringBackend, + DatabaseConfig: &dbCfg, + RpcListener: defaultRpcListener, + } + if err := cfg.Validate(); err != nil { + panic(err) + } + return cfg +} diff --git a/eotsmanager/eotsmanager.go b/eotsmanager/eotsmanager.go new file mode 100644 index 00000000..2e8e1619 --- /dev/null +++ b/eotsmanager/eotsmanager.go @@ -0,0 +1,40 @@ +package eotsmanager + +import ( + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/schnorr" + + "github.com/babylonchain/finality-provider/eotsmanager/types" +) + +type EOTSManager interface { + // CreateKey generates a key pair at the given name and persists it in storage. + // The key pair is formatted by BIP-340 (Schnorr Signatures) + // It fails if there is an existing key Info with the same name or public key. + CreateKey(name, passphrase, hdPath string) ([]byte, error) + + // CreateRandomnessPairList generates a list of Schnorr randomness pairs from + // startHeight to startHeight+(num-1) where num means the number of public randomness + // It fails if the finality provider does not exist or a randomness pair has been created before + // or passPhrase is incorrect + // NOTE: the randomness is deterministically generated based on the EOTS key, chainID and + // block height + CreateRandomnessPairList(uid []byte, chainID []byte, startHeight uint64, num uint32, passphrase string) ([]*btcec.FieldVal, error) + + // KeyRecord returns the finality provider record + // It fails if the finality provider does not exist or passPhrase is incorrect + KeyRecord(uid []byte, passphrase string) (*types.KeyRecord, error) + + // SignEOTS signs an EOTS using the private key of the finality provider and the corresponding + // secret randomness of the give chain at the given height + // It fails if the finality provider does not exist or there's no randomness committed to the given height + // or passPhrase is incorrect + SignEOTS(uid []byte, chainID []byte, msg []byte, height uint64, passphrase string) (*btcec.ModNScalar, error) + + // SignSchnorrSig signs a Schnorr signature using the private key of the finality provider + // It fails if the finality provider does not exist or the message size is not 32 bytes + // or passPhrase is incorrect + SignSchnorrSig(uid []byte, msg []byte, passphrase string) (*schnorr.Signature, error) + + Close() error +} diff --git a/eotsmanager/eotsstore.go b/eotsmanager/eotsstore.go new file mode 100644 index 00000000..40cf8401 --- /dev/null +++ b/eotsmanager/eotsstore.go @@ -0,0 +1,70 @@ +package eotsmanager + +import ( + "fmt" + + "github.com/babylonchain/finality-provider/eotsmanager/types" + "github.com/babylonchain/finality-provider/store" +) + +const ( + finalityProviderKeyNamePrefix = "fp-key" +) + +type EOTSStore struct { + s store.Store +} + +func NewEOTSStore(dbPath string, dbName string, dbBackend string) (*EOTSStore, error) { + s, err := openStore(dbPath, dbName, dbBackend) + if err != nil { + return nil, err + } + + return &EOTSStore{s: s}, nil +} + +func (es *EOTSStore) Close() error { + if err := es.s.Close(); err != nil { + return err + } + + return nil +} + +func (es *EOTSStore) saveFinalityProviderKey(pk []byte, keyName string) error { + k := getFinalityProviderKeyNameKey(pk) + + exists, err := es.s.Exists(k) + if err != nil { + return nil + } + if exists { + return types.ErrFinalityProviderAlreadyExisted + } + + return es.s.Put(k, []byte(keyName)) +} + +func (es *EOTSStore) getFinalityProviderKeyName(pk []byte) (string, error) { + k := getFinalityProviderKeyNameKey(pk) + v, err := es.s.Get(k) + if err != nil { + return "", err + } + + return string(v), nil +} + +func getFinalityProviderKeyNameKey(pk []byte) []byte { + return append([]byte(finalityProviderKeyNamePrefix), pk...) +} + +func openStore(dbPath string, dbName string, dbBackend string) (store.Store, error) { + switch dbBackend { + case "bbolt": + return store.NewBboltStore(dbPath, dbName) + default: + return nil, fmt.Errorf("unsupported database type") + } +} diff --git a/eotsmanager/localmanager.go b/eotsmanager/localmanager.go new file mode 100644 index 00000000..4d07a980 --- /dev/null +++ b/eotsmanager/localmanager.go @@ -0,0 +1,240 @@ +package eotsmanager + +import ( + "fmt" + "github.com/babylonchain/finality-provider/util" + "strings" + + "github.com/babylonchain/babylon/crypto/eots" + bbntypes "github.com/babylonchain/babylon/types" + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/schnorr" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + "github.com/cosmos/go-bip39" + "go.uber.org/zap" + + "github.com/babylonchain/finality-provider/codec" + "github.com/babylonchain/finality-provider/eotsmanager/config" + "github.com/babylonchain/finality-provider/eotsmanager/randgenerator" + eotstypes "github.com/babylonchain/finality-provider/eotsmanager/types" +) + +const ( + secp256k1Type = "secp256k1" + mnemonicEntropySize = 256 +) + +var _ EOTSManager = &LocalEOTSManager{} + +type LocalEOTSManager struct { + kr keyring.Keyring + es *EOTSStore + logger *zap.Logger + // input is to send passphrase to kr + input *strings.Reader +} + +func NewLocalEOTSManager(homeDir string, eotsCfg *config.Config, logger *zap.Logger) (*LocalEOTSManager, error) { + inputReader := strings.NewReader("") + + store, err := initEotsStore(homeDir, eotsCfg) + if err != nil { + return nil, fmt.Errorf("failed to initialize store: %w", err) + } + + kr, err := initKeyring(homeDir, eotsCfg, inputReader) + if err != nil { + return nil, fmt.Errorf("failed to initialize keyring: %w", err) + } + + return &LocalEOTSManager{ + kr: kr, + es: store, + logger: logger, + input: inputReader, + }, nil +} + +func initEotsStore(homeDir string, eotsCfg *config.Config) (*EOTSStore, error) { + // Create the directory that will store the data + if err := util.MakeDirectory(config.DataDir(homeDir)); err != nil { + return nil, err + } + + return NewEOTSStore(config.DBPath(homeDir), eotsCfg.DatabaseConfig.Name, eotsCfg.DatabaseConfig.Backend) +} + +func initKeyring(homeDir string, eotsCfg *config.Config, inputReader *strings.Reader) (keyring.Keyring, error) { + return keyring.New( + "eots-manager", + eotsCfg.KeyringBackend, + homeDir, + inputReader, + codec.MakeCodec(), + ) +} + +func (lm *LocalEOTSManager) CreateKey(name, passphrase, hdPath string) ([]byte, error) { + if lm.keyExists(name) { + return nil, eotstypes.ErrFinalityProviderAlreadyExisted + } + + keyringAlgos, _ := lm.kr.SupportedAlgorithms() + algo, err := keyring.NewSigningAlgoFromString(secp256k1Type, keyringAlgos) + if err != nil { + return nil, err + } + + // read entropy seed straight from tmcrypto.Rand and convert to mnemonic + entropySeed, err := bip39.NewEntropy(mnemonicEntropySize) + if err != nil { + return nil, err + } + + mnemonic, err := bip39.NewMnemonic(entropySeed) + if err != nil { + return nil, err + } + + // we need to repeat the passphrase to mock the re-entry + // as when creating an account, passphrase will be asked twice + // by the keyring + lm.input.Reset(passphrase + "\n" + passphrase) + record, err := lm.kr.NewAccount(name, mnemonic, passphrase, hdPath, algo) + if err != nil { + return nil, err + } + + pubKey, err := record.GetPubKey() + if err != nil { + return nil, err + } + + var eotsPk *bbntypes.BIP340PubKey + switch v := pubKey.(type) { + case *secp256k1.PubKey: + pk, err := btcec.ParsePubKey(v.Key) + if err != nil { + return nil, err + } + eotsPk = bbntypes.NewBIP340PubKeyFromBTCPK(pk) + default: + return nil, fmt.Errorf("unsupported key type in keyring") + } + + if err := lm.es.saveFinalityProviderKey(eotsPk.MustMarshal(), name); err != nil { + return nil, err + } + + lm.logger.Info( + "successfully created an EOTS key", + zap.String("key name", name), + zap.String("pk", eotsPk.MarshalHex()), + ) + + return eotsPk.MustMarshal(), nil +} + +// TODO the current implementation is a PoC, which does not contain any anti-slasher mechanism +// +// a simple anti-slasher mechanism could be that the manager remembers the tuple (fpPk, chainID, height) or +// the hash of each generated randomness and return error if the same randomness is requested tweice +func (lm *LocalEOTSManager) CreateRandomnessPairList(fpPk []byte, chainID []byte, startHeight uint64, num uint32, passphrase string) ([]*btcec.FieldVal, error) { + prList := make([]*btcec.FieldVal, 0, num) + + for i := uint32(0); i < num; i++ { + height := startHeight + uint64(i) + _, pubRand, err := lm.getRandomnessPair(fpPk, chainID, height, passphrase) + if err != nil { + return nil, err + } + + prList = append(prList, pubRand) + } + + return prList, nil +} + +func (lm *LocalEOTSManager) SignEOTS(fpPk []byte, chainID []byte, msg []byte, height uint64, passphrase string) (*btcec.ModNScalar, error) { + privRand, _, err := lm.getRandomnessPair(fpPk, chainID, height, passphrase) + if err != nil { + return nil, fmt.Errorf("failed to get private randomness: %w", err) + } + + privKey, err := lm.getEOTSPrivKey(fpPk, passphrase) + if err != nil { + return nil, fmt.Errorf("failed to get EOTS private key: %w", err) + } + + return eots.Sign(privKey, privRand, msg) +} + +func (lm *LocalEOTSManager) SignSchnorrSig(fpPk []byte, msg []byte, passphrase string) (*schnorr.Signature, error) { + privKey, err := lm.getEOTSPrivKey(fpPk, passphrase) + if err != nil { + return nil, fmt.Errorf("failed to get EOTS private key: %w", err) + } + + return schnorr.Sign(privKey, msg) +} + +func (lm *LocalEOTSManager) Close() error { + return lm.es.Close() +} + +// getRandomnessPair returns a randomness pair generated based on the given finality provider key, chainID and height +func (lm *LocalEOTSManager) getRandomnessPair(fpPk []byte, chainID []byte, height uint64, passphrase string) (*eots.PrivateRand, *eots.PublicRand, error) { + record, err := lm.KeyRecord(fpPk, passphrase) + if err != nil { + return nil, nil, err + } + privRand, pubRand := randgenerator.GenerateRandomness(record.PrivKey.Serialize(), chainID, height) + return privRand, pubRand, nil +} + +// TODO: we ignore passPhrase in local implementation for now +func (lm *LocalEOTSManager) KeyRecord(fpPk []byte, passphrase string) (*eotstypes.KeyRecord, error) { + name, err := lm.es.getFinalityProviderKeyName(fpPk) + if err != nil { + return nil, err + } + privKey, err := lm.getEOTSPrivKey(fpPk, passphrase) + if err != nil { + return nil, err + } + + return &eotstypes.KeyRecord{ + Name: name, + PrivKey: privKey, + }, nil +} + +func (lm *LocalEOTSManager) getEOTSPrivKey(fpPk []byte, passphrase string) (*btcec.PrivateKey, error) { + keyName, err := lm.es.getFinalityProviderKeyName(fpPk) + if err != nil { + return nil, err + } + + lm.input.Reset(passphrase) + k, err := lm.kr.Key(keyName) + if err != nil { + return nil, err + } + + privKeyCached := k.GetLocal().PrivKey.GetCachedValue() + + var privKey *btcec.PrivateKey + switch v := privKeyCached.(type) { + case *secp256k1.PrivKey: + privKey, _ = btcec.PrivKeyFromBytes(v.Key) + return privKey, nil + default: + return nil, fmt.Errorf("unsupported key type in keyring") + } +} + +func (lm *LocalEOTSManager) keyExists(name string) bool { + _, err := lm.kr.Key(name) + return err == nil +} diff --git a/eotsmanager/localmanager_test.go b/eotsmanager/localmanager_test.go new file mode 100644 index 00000000..29f5d43f --- /dev/null +++ b/eotsmanager/localmanager_test.go @@ -0,0 +1,87 @@ +package eotsmanager_test + +import ( + "go.uber.org/zap" + "math/rand" + "os" + "path/filepath" + "testing" + + "github.com/babylonchain/babylon/testutil/datagen" + "github.com/babylonchain/finality-provider/eotsmanager" + "github.com/babylonchain/finality-provider/eotsmanager/types" + "github.com/babylonchain/finality-provider/testutil" + "github.com/stretchr/testify/require" +) + +var ( + passphrase = "testpass" + hdPath = "" +) + +// FuzzCreateKey tests the creation of an EOTS key +func FuzzCreateKey(f *testing.F) { + testutil.AddRandomSeedsToFuzzer(f, 10) + f.Fuzz(func(t *testing.T, seed int64) { + r := rand.New(rand.NewSource(seed)) + + fpName := testutil.GenRandomHexStr(r, 4) + homeDir := filepath.Join(t.TempDir(), "eots-home") + eotsCfg := testutil.GenEOTSConfig(r, t) + defer func() { + err := os.RemoveAll(homeDir) + require.NoError(t, err) + }() + + lm, err := eotsmanager.NewLocalEOTSManager(homeDir, eotsCfg, zap.NewNop()) + require.NoError(t, err) + + fpPk, err := lm.CreateKey(fpName, passphrase, hdPath) + require.NoError(t, err) + + fpRecord, err := lm.KeyRecord(fpPk, passphrase) + require.NoError(t, err) + require.Equal(t, fpName, fpRecord.Name) + + sig, err := lm.SignSchnorrSig(fpPk, datagen.GenRandomByteArray(r, 32), passphrase) + require.NoError(t, err) + require.NotNil(t, sig) + + _, err = lm.CreateKey(fpName, passphrase, hdPath) + require.ErrorIs(t, err, types.ErrFinalityProviderAlreadyExisted) + }) +} + +func FuzzCreateRandomnessPairList(f *testing.F) { + testutil.AddRandomSeedsToFuzzer(f, 10) + f.Fuzz(func(t *testing.T, seed int64) { + r := rand.New(rand.NewSource(seed)) + + fpName := testutil.GenRandomHexStr(r, 4) + homeDir := filepath.Join(t.TempDir(), "eots-home") + eotsCfg := testutil.GenEOTSConfig(r, t) + defer func() { + err := os.RemoveAll(homeDir) + require.NoError(t, err) + }() + + lm, err := eotsmanager.NewLocalEOTSManager(homeDir, eotsCfg, zap.NewNop()) + require.NoError(t, err) + + fpPk, err := lm.CreateKey(fpName, passphrase, hdPath) + require.NoError(t, err) + + chainID := datagen.GenRandomByteArray(r, 10) + startHeight := datagen.RandomInt(r, 100) + num := r.Intn(10) + 1 + pubRandList, err := lm.CreateRandomnessPairList(fpPk, chainID, startHeight, uint32(num), passphrase) + require.NoError(t, err) + require.Len(t, pubRandList, num) + + for i := 0; i < num; i++ { + sig, err := lm.SignEOTS(fpPk, chainID, datagen.GenRandomByteArray(r, 32), startHeight+uint64(i), passphrase) + require.NoError(t, err) + require.NotNil(t, sig) + } + }) +} diff --git a/proto/.clang-format b/eotsmanager/proto/.clang-format similarity index 100% rename from proto/.clang-format rename to eotsmanager/proto/.clang-format diff --git a/proto/buf.gen.yaml b/eotsmanager/proto/buf.gen.yaml similarity index 100% rename from proto/buf.gen.yaml rename to eotsmanager/proto/buf.gen.yaml diff --git a/eotsmanager/proto/buf.lock b/eotsmanager/proto/buf.lock new file mode 100644 index 00000000..c91b5810 --- /dev/null +++ b/eotsmanager/proto/buf.lock @@ -0,0 +1,2 @@ +# Generated by buf. DO NOT EDIT. +version: v1 diff --git a/eotsmanager/proto/buf.yaml b/eotsmanager/proto/buf.yaml new file mode 100644 index 00000000..5ab32f06 --- /dev/null +++ b/eotsmanager/proto/buf.yaml @@ -0,0 +1,24 @@ +version: v1 +name: buf.build/babylonchain/eotsmanager +deps: +breaking: + use: + - FILE +lint: + use: + - DEFAULT + - COMMENTS + - FILE_LOWER_SNAKE_CASE + - COMMENT_MESSAGE + - COMMENT_ENUM_VALUE + - COMMENT_ENUM + - COMMENT_RPC + - COMMENT_ONEOF + except: + - UNARY_RPC + - COMMENT_FIELD + - SERVICE_SUFFIX + - PACKAGE_VERSION_SUFFIX + - RPC_REQUEST_STANDARD_NAME + - ENUM_VALUE_PREFIX + - ENUM_ZERO_VALUE_SUFFIX diff --git a/eotsmanager/proto/eotsmanager.pb.go b/eotsmanager/proto/eotsmanager.pb.go new file mode 100644 index 00000000..0be2f1d2 --- /dev/null +++ b/eotsmanager/proto/eotsmanager.pb.go @@ -0,0 +1,1014 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.31.0 +// protoc (unknown) +// source: eotsmanager.proto + +package proto + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type PingRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *PingRequest) Reset() { + *x = PingRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_eotsmanager_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PingRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PingRequest) ProtoMessage() {} + +func (x *PingRequest) ProtoReflect() protoreflect.Message { + mi := &file_eotsmanager_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PingRequest.ProtoReflect.Descriptor instead. +func (*PingRequest) Descriptor() ([]byte, []int) { + return file_eotsmanager_proto_rawDescGZIP(), []int{0} +} + +type PingResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *PingResponse) Reset() { + *x = PingResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_eotsmanager_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PingResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PingResponse) ProtoMessage() {} + +func (x *PingResponse) ProtoReflect() protoreflect.Message { + mi := &file_eotsmanager_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PingResponse.ProtoReflect.Descriptor instead. +func (*PingResponse) Descriptor() ([]byte, []int) { + return file_eotsmanager_proto_rawDescGZIP(), []int{1} +} + +type CreateKeyRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // name is the identifier key in keyring + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // passphrase is used to encrypt the EOTS key + Passphrase string `protobuf:"bytes,2,opt,name=passphrase,proto3" json:"passphrase,omitempty"` + // hd_path is the hd path for private key derivation + HdPath string `protobuf:"bytes,3,opt,name=hd_path,json=hdPath,proto3" json:"hd_path,omitempty"` +} + +func (x *CreateKeyRequest) Reset() { + *x = CreateKeyRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_eotsmanager_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CreateKeyRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateKeyRequest) ProtoMessage() {} + +func (x *CreateKeyRequest) ProtoReflect() protoreflect.Message { + mi := &file_eotsmanager_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateKeyRequest.ProtoReflect.Descriptor instead. +func (*CreateKeyRequest) Descriptor() ([]byte, []int) { + return file_eotsmanager_proto_rawDescGZIP(), []int{2} +} + +func (x *CreateKeyRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *CreateKeyRequest) GetPassphrase() string { + if x != nil { + return x.Passphrase + } + return "" +} + +func (x *CreateKeyRequest) GetHdPath() string { + if x != nil { + return x.HdPath + } + return "" +} + +type CreateKeyResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // pk is the EOTS public key following BIP-340 spec + Pk []byte `protobuf:"bytes,1,opt,name=pk,proto3" json:"pk,omitempty"` +} + +func (x *CreateKeyResponse) Reset() { + *x = CreateKeyResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_eotsmanager_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CreateKeyResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateKeyResponse) ProtoMessage() {} + +func (x *CreateKeyResponse) ProtoReflect() protoreflect.Message { + mi := &file_eotsmanager_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateKeyResponse.ProtoReflect.Descriptor instead. +func (*CreateKeyResponse) Descriptor() ([]byte, []int) { + return file_eotsmanager_proto_rawDescGZIP(), []int{3} +} + +func (x *CreateKeyResponse) GetPk() []byte { + if x != nil { + return x.Pk + } + return nil +} + +type CreateRandomnessPairListRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // uid is the identifier of an EOTS key, i.e., public key following BIP-340 spec + Uid []byte `protobuf:"bytes,1,opt,name=uid,proto3" json:"uid,omitempty"` + // chain_id is the identifier of the consumer chain that the randomness is committed to + ChainId []byte `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + // start_height is the start height of the randomness pair list + StartHeight uint64 `protobuf:"varint,3,opt,name=start_height,json=startHeight,proto3" json:"start_height,omitempty"` + // num is the number of randomness pair list + Num uint32 `protobuf:"varint,4,opt,name=num,proto3" json:"num,omitempty"` + // passphrase is used to decrypt the EOTS key + Passphrase string `protobuf:"bytes,5,opt,name=passphrase,proto3" json:"passphrase,omitempty"` +} + +func (x *CreateRandomnessPairListRequest) Reset() { + *x = CreateRandomnessPairListRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_eotsmanager_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CreateRandomnessPairListRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateRandomnessPairListRequest) ProtoMessage() {} + +func (x *CreateRandomnessPairListRequest) ProtoReflect() protoreflect.Message { + mi := &file_eotsmanager_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateRandomnessPairListRequest.ProtoReflect.Descriptor instead. +func (*CreateRandomnessPairListRequest) Descriptor() ([]byte, []int) { + return file_eotsmanager_proto_rawDescGZIP(), []int{4} +} + +func (x *CreateRandomnessPairListRequest) GetUid() []byte { + if x != nil { + return x.Uid + } + return nil +} + +func (x *CreateRandomnessPairListRequest) GetChainId() []byte { + if x != nil { + return x.ChainId + } + return nil +} + +func (x *CreateRandomnessPairListRequest) GetStartHeight() uint64 { + if x != nil { + return x.StartHeight + } + return 0 +} + +func (x *CreateRandomnessPairListRequest) GetNum() uint32 { + if x != nil { + return x.Num + } + return 0 +} + +func (x *CreateRandomnessPairListRequest) GetPassphrase() string { + if x != nil { + return x.Passphrase + } + return "" +} + +type CreateRandomnessPairListResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // pub_rand_list is a list of Schnorr public randomness + PubRandList [][]byte `protobuf:"bytes,1,rep,name=pub_rand_list,json=pubRandList,proto3" json:"pub_rand_list,omitempty"` +} + +func (x *CreateRandomnessPairListResponse) Reset() { + *x = CreateRandomnessPairListResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_eotsmanager_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CreateRandomnessPairListResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateRandomnessPairListResponse) ProtoMessage() {} + +func (x *CreateRandomnessPairListResponse) ProtoReflect() protoreflect.Message { + mi := &file_eotsmanager_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateRandomnessPairListResponse.ProtoReflect.Descriptor instead. +func (*CreateRandomnessPairListResponse) Descriptor() ([]byte, []int) { + return file_eotsmanager_proto_rawDescGZIP(), []int{5} +} + +func (x *CreateRandomnessPairListResponse) GetPubRandList() [][]byte { + if x != nil { + return x.PubRandList + } + return nil +} + +type KeyRecordRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // uid is the identifier of an EOTS key, i.e., public key following BIP-340 spec + Uid []byte `protobuf:"bytes,1,opt,name=uid,proto3" json:"uid,omitempty"` + // passphrase is used to decrypt the EOTS key + Passphrase string `protobuf:"bytes,2,opt,name=passphrase,proto3" json:"passphrase,omitempty"` +} + +func (x *KeyRecordRequest) Reset() { + *x = KeyRecordRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_eotsmanager_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *KeyRecordRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*KeyRecordRequest) ProtoMessage() {} + +func (x *KeyRecordRequest) ProtoReflect() protoreflect.Message { + mi := &file_eotsmanager_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use KeyRecordRequest.ProtoReflect.Descriptor instead. +func (*KeyRecordRequest) Descriptor() ([]byte, []int) { + return file_eotsmanager_proto_rawDescGZIP(), []int{6} +} + +func (x *KeyRecordRequest) GetUid() []byte { + if x != nil { + return x.Uid + } + return nil +} + +func (x *KeyRecordRequest) GetPassphrase() string { + if x != nil { + return x.Passphrase + } + return "" +} + +type KeyRecordResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // name is the identifier key in keyring + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // private_key is the private EOTS key encoded in secp256k1 spec + PrivateKey []byte `protobuf:"bytes,2,opt,name=private_key,json=privateKey,proto3" json:"private_key,omitempty"` +} + +func (x *KeyRecordResponse) Reset() { + *x = KeyRecordResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_eotsmanager_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *KeyRecordResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*KeyRecordResponse) ProtoMessage() {} + +func (x *KeyRecordResponse) ProtoReflect() protoreflect.Message { + mi := &file_eotsmanager_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use KeyRecordResponse.ProtoReflect.Descriptor instead. +func (*KeyRecordResponse) Descriptor() ([]byte, []int) { + return file_eotsmanager_proto_rawDescGZIP(), []int{7} +} + +func (x *KeyRecordResponse) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *KeyRecordResponse) GetPrivateKey() []byte { + if x != nil { + return x.PrivateKey + } + return nil +} + +type SignEOTSRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // uid is the identifier of an EOTS key, i.e., public key following BIP-340 spec + Uid []byte `protobuf:"bytes,1,opt,name=uid,proto3" json:"uid,omitempty"` + // chain_id is the identifier of the consumer chain that the randomness is committed to + ChainId []byte `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + // the message which the EOTS signs + Msg []byte `protobuf:"bytes,3,opt,name=msg,proto3" json:"msg,omitempty"` + // the block height which the EOTS signs + Height uint64 `protobuf:"varint,4,opt,name=height,proto3" json:"height,omitempty"` + // passphrase is used to decrypt the EOTS key + Passphrase string `protobuf:"bytes,5,opt,name=passphrase,proto3" json:"passphrase,omitempty"` +} + +func (x *SignEOTSRequest) Reset() { + *x = SignEOTSRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_eotsmanager_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SignEOTSRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SignEOTSRequest) ProtoMessage() {} + +func (x *SignEOTSRequest) ProtoReflect() protoreflect.Message { + mi := &file_eotsmanager_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SignEOTSRequest.ProtoReflect.Descriptor instead. +func (*SignEOTSRequest) Descriptor() ([]byte, []int) { + return file_eotsmanager_proto_rawDescGZIP(), []int{8} +} + +func (x *SignEOTSRequest) GetUid() []byte { + if x != nil { + return x.Uid + } + return nil +} + +func (x *SignEOTSRequest) GetChainId() []byte { + if x != nil { + return x.ChainId + } + return nil +} + +func (x *SignEOTSRequest) GetMsg() []byte { + if x != nil { + return x.Msg + } + return nil +} + +func (x *SignEOTSRequest) GetHeight() uint64 { + if x != nil { + return x.Height + } + return 0 +} + +func (x *SignEOTSRequest) GetPassphrase() string { + if x != nil { + return x.Passphrase + } + return "" +} + +type SignEOTSResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // sig is the EOTS signature + Sig []byte `protobuf:"bytes,1,opt,name=sig,proto3" json:"sig,omitempty"` +} + +func (x *SignEOTSResponse) Reset() { + *x = SignEOTSResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_eotsmanager_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SignEOTSResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SignEOTSResponse) ProtoMessage() {} + +func (x *SignEOTSResponse) ProtoReflect() protoreflect.Message { + mi := &file_eotsmanager_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SignEOTSResponse.ProtoReflect.Descriptor instead. +func (*SignEOTSResponse) Descriptor() ([]byte, []int) { + return file_eotsmanager_proto_rawDescGZIP(), []int{9} +} + +func (x *SignEOTSResponse) GetSig() []byte { + if x != nil { + return x.Sig + } + return nil +} + +type SignSchnorrSigRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // uid is the identifier of an EOTS key, i.e., public key following BIP-340 spec + Uid []byte `protobuf:"bytes,1,opt,name=uid,proto3" json:"uid,omitempty"` + // the message which the Schnorr signature signs + Msg []byte `protobuf:"bytes,2,opt,name=msg,proto3" json:"msg,omitempty"` + // passphrase is used to decrypt the EOTS key + Passphrase string `protobuf:"bytes,3,opt,name=passphrase,proto3" json:"passphrase,omitempty"` +} + +func (x *SignSchnorrSigRequest) Reset() { + *x = SignSchnorrSigRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_eotsmanager_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SignSchnorrSigRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SignSchnorrSigRequest) ProtoMessage() {} + +func (x *SignSchnorrSigRequest) ProtoReflect() protoreflect.Message { + mi := &file_eotsmanager_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SignSchnorrSigRequest.ProtoReflect.Descriptor instead. +func (*SignSchnorrSigRequest) Descriptor() ([]byte, []int) { + return file_eotsmanager_proto_rawDescGZIP(), []int{10} +} + +func (x *SignSchnorrSigRequest) GetUid() []byte { + if x != nil { + return x.Uid + } + return nil +} + +func (x *SignSchnorrSigRequest) GetMsg() []byte { + if x != nil { + return x.Msg + } + return nil +} + +func (x *SignSchnorrSigRequest) GetPassphrase() string { + if x != nil { + return x.Passphrase + } + return "" +} + +type SignSchnorrSigResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // sig is the Schnorr signature + Sig []byte `protobuf:"bytes,1,opt,name=sig,proto3" json:"sig,omitempty"` +} + +func (x *SignSchnorrSigResponse) Reset() { + *x = SignSchnorrSigResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_eotsmanager_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SignSchnorrSigResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SignSchnorrSigResponse) ProtoMessage() {} + +func (x *SignSchnorrSigResponse) ProtoReflect() protoreflect.Message { + mi := &file_eotsmanager_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SignSchnorrSigResponse.ProtoReflect.Descriptor instead. +func (*SignSchnorrSigResponse) Descriptor() ([]byte, []int) { + return file_eotsmanager_proto_rawDescGZIP(), []int{11} +} + +func (x *SignSchnorrSigResponse) GetSig() []byte { + if x != nil { + return x.Sig + } + return nil +} + +var File_eotsmanager_proto protoreflect.FileDescriptor + +var file_eotsmanager_proto_rawDesc = []byte{ + 0x0a, 0x11, 0x65, 0x6f, 0x74, 0x73, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x0d, 0x0a, 0x0b, 0x50, 0x69, + 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x0e, 0x0a, 0x0c, 0x50, 0x69, 0x6e, + 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x5f, 0x0a, 0x10, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, + 0x65, 0x12, 0x17, 0x0a, 0x07, 0x68, 0x64, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x68, 0x64, 0x50, 0x61, 0x74, 0x68, 0x22, 0x23, 0x0a, 0x11, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x0e, 0x0a, 0x02, 0x70, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x70, 0x6b, 0x22, + 0xa3, 0x01, 0x0a, 0x1f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x61, 0x6e, 0x64, 0x6f, 0x6d, + 0x6e, 0x65, 0x73, 0x73, 0x50, 0x61, 0x69, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, + 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x73, 0x74, 0x61, 0x72, 0x74, 0x48, 0x65, 0x69, + 0x67, 0x68, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6e, 0x75, 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x03, 0x6e, 0x75, 0x6d, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, + 0x61, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, 0x73, 0x73, 0x70, + 0x68, 0x72, 0x61, 0x73, 0x65, 0x22, 0x46, 0x0a, 0x20, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, + 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x6e, 0x65, 0x73, 0x73, 0x50, 0x61, 0x69, 0x72, 0x4c, 0x69, 0x73, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x70, 0x75, 0x62, + 0x5f, 0x72, 0x61, 0x6e, 0x64, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, + 0x52, 0x0b, 0x70, 0x75, 0x62, 0x52, 0x61, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x44, 0x0a, + 0x10, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, + 0x75, 0x69, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, + 0x61, 0x73, 0x65, 0x22, 0x48, 0x0a, 0x11, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, + 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x0a, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x22, 0x88, 0x01, + 0x0a, 0x0f, 0x53, 0x69, 0x67, 0x6e, 0x45, 0x4f, 0x54, 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, + 0x75, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x10, + 0x0a, 0x03, 0x6d, 0x73, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6d, 0x73, 0x67, + 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x61, 0x73, 0x73, + 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, + 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x22, 0x24, 0x0a, 0x10, 0x53, 0x69, 0x67, 0x6e, + 0x45, 0x4f, 0x54, 0x53, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, + 0x73, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x73, 0x69, 0x67, 0x22, 0x5b, + 0x0a, 0x15, 0x53, 0x69, 0x67, 0x6e, 0x53, 0x63, 0x68, 0x6e, 0x6f, 0x72, 0x72, 0x53, 0x69, 0x67, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x73, 0x67, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6d, 0x73, 0x67, 0x12, 0x1e, 0x0a, 0x0a, 0x70, + 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0a, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x22, 0x2a, 0x0a, 0x16, 0x53, + 0x69, 0x67, 0x6e, 0x53, 0x63, 0x68, 0x6e, 0x6f, 0x72, 0x72, 0x53, 0x69, 0x67, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x03, 0x73, 0x69, 0x67, 0x32, 0xb7, 0x03, 0x0a, 0x0b, 0x45, 0x4f, 0x54, 0x53, + 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x12, 0x2f, 0x0a, 0x04, 0x50, 0x69, 0x6e, 0x67, 0x12, + 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x69, 0x6e, 0x67, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x09, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6b, 0x0a, 0x18, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x52, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x6e, 0x65, 0x73, 0x73, 0x50, 0x61, 0x69, 0x72, + 0x4c, 0x69, 0x73, 0x74, 0x12, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x52, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x6e, 0x65, 0x73, 0x73, 0x50, 0x61, 0x69, + 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x61, 0x6e, 0x64, 0x6f, + 0x6d, 0x6e, 0x65, 0x73, 0x73, 0x50, 0x61, 0x69, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x09, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x63, 0x6f, + 0x72, 0x64, 0x12, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4b, 0x65, 0x79, 0x52, 0x65, + 0x63, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x08, 0x53, 0x69, 0x67, 0x6e, 0x45, 0x4f, 0x54, + 0x53, 0x12, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x45, 0x4f, + 0x54, 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x45, 0x4f, 0x54, 0x53, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x0e, 0x53, 0x69, 0x67, 0x6e, 0x53, 0x63, 0x68, 0x6e, 0x6f, 0x72, + 0x72, 0x53, 0x69, 0x67, 0x12, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x69, 0x67, + 0x6e, 0x53, 0x63, 0x68, 0x6e, 0x6f, 0x72, 0x72, 0x53, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x53, + 0x63, 0x68, 0x6e, 0x6f, 0x72, 0x72, 0x53, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x62, 0x61, 0x62, 0x79, 0x6c, 0x6f, 0x6e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x2f, 0x62, 0x74, 0x63, + 0x2d, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x2d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, + 0x65, 0x72, 0x2f, 0x65, 0x6f, 0x74, 0x73, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2f, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_eotsmanager_proto_rawDescOnce sync.Once + file_eotsmanager_proto_rawDescData = file_eotsmanager_proto_rawDesc +) + +func file_eotsmanager_proto_rawDescGZIP() []byte { + file_eotsmanager_proto_rawDescOnce.Do(func() { + file_eotsmanager_proto_rawDescData = protoimpl.X.CompressGZIP(file_eotsmanager_proto_rawDescData) + }) + return file_eotsmanager_proto_rawDescData +} + +var file_eotsmanager_proto_msgTypes = make([]protoimpl.MessageInfo, 12) +var file_eotsmanager_proto_goTypes = []interface{}{ + (*PingRequest)(nil), // 0: proto.PingRequest + (*PingResponse)(nil), // 1: proto.PingResponse + (*CreateKeyRequest)(nil), // 2: proto.CreateKeyRequest + (*CreateKeyResponse)(nil), // 3: proto.CreateKeyResponse + (*CreateRandomnessPairListRequest)(nil), // 4: proto.CreateRandomnessPairListRequest + (*CreateRandomnessPairListResponse)(nil), // 5: proto.CreateRandomnessPairListResponse + (*KeyRecordRequest)(nil), // 6: proto.KeyRecordRequest + (*KeyRecordResponse)(nil), // 7: proto.KeyRecordResponse + (*SignEOTSRequest)(nil), // 8: proto.SignEOTSRequest + (*SignEOTSResponse)(nil), // 9: proto.SignEOTSResponse + (*SignSchnorrSigRequest)(nil), // 10: proto.SignSchnorrSigRequest + (*SignSchnorrSigResponse)(nil), // 11: proto.SignSchnorrSigResponse +} +var file_eotsmanager_proto_depIdxs = []int32{ + 0, // 0: proto.EOTSManager.Ping:input_type -> proto.PingRequest + 2, // 1: proto.EOTSManager.CreateKey:input_type -> proto.CreateKeyRequest + 4, // 2: proto.EOTSManager.CreateRandomnessPairList:input_type -> proto.CreateRandomnessPairListRequest + 6, // 3: proto.EOTSManager.KeyRecord:input_type -> proto.KeyRecordRequest + 8, // 4: proto.EOTSManager.SignEOTS:input_type -> proto.SignEOTSRequest + 10, // 5: proto.EOTSManager.SignSchnorrSig:input_type -> proto.SignSchnorrSigRequest + 1, // 6: proto.EOTSManager.Ping:output_type -> proto.PingResponse + 3, // 7: proto.EOTSManager.CreateKey:output_type -> proto.CreateKeyResponse + 5, // 8: proto.EOTSManager.CreateRandomnessPairList:output_type -> proto.CreateRandomnessPairListResponse + 7, // 9: proto.EOTSManager.KeyRecord:output_type -> proto.KeyRecordResponse + 9, // 10: proto.EOTSManager.SignEOTS:output_type -> proto.SignEOTSResponse + 11, // 11: proto.EOTSManager.SignSchnorrSig:output_type -> proto.SignSchnorrSigResponse + 6, // [6:12] is the sub-list for method output_type + 0, // [0:6] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_eotsmanager_proto_init() } +func file_eotsmanager_proto_init() { + if File_eotsmanager_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_eotsmanager_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PingRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_eotsmanager_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PingResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_eotsmanager_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CreateKeyRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_eotsmanager_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CreateKeyResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_eotsmanager_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CreateRandomnessPairListRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_eotsmanager_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CreateRandomnessPairListResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_eotsmanager_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*KeyRecordRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_eotsmanager_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*KeyRecordResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_eotsmanager_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SignEOTSRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_eotsmanager_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SignEOTSResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_eotsmanager_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SignSchnorrSigRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_eotsmanager_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SignSchnorrSigResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_eotsmanager_proto_rawDesc, + NumEnums: 0, + NumMessages: 12, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_eotsmanager_proto_goTypes, + DependencyIndexes: file_eotsmanager_proto_depIdxs, + MessageInfos: file_eotsmanager_proto_msgTypes, + }.Build() + File_eotsmanager_proto = out.File + file_eotsmanager_proto_rawDesc = nil + file_eotsmanager_proto_goTypes = nil + file_eotsmanager_proto_depIdxs = nil +} diff --git a/eotsmanager/proto/eotsmanager.proto b/eotsmanager/proto/eotsmanager.proto new file mode 100644 index 00000000..866a9de0 --- /dev/null +++ b/eotsmanager/proto/eotsmanager.proto @@ -0,0 +1,111 @@ +syntax = "proto3"; + +package proto; + +option go_package = "github.com/babylonchain/btc-finality-provider/eotsmanager/proto"; + +service EOTSManager { + rpc Ping (PingRequest) returns (PingResponse); + + // CreateKey generates and saves an EOTS key + rpc CreateKey (CreateKeyRequest) + returns (CreateKeyResponse); + + // CreateRandomnessPairList returns a list of Schnorr randomness pairs + rpc CreateRandomnessPairList (CreateRandomnessPairListRequest) + returns (CreateRandomnessPairListResponse); + + // KeyRecord returns the key record + rpc KeyRecord(KeyRecordRequest) + returns (KeyRecordResponse); + + // SignEOTS signs an EOTS with the EOTS private key and the relevant randomness + rpc SignEOTS (SignEOTSRequest) + returns (SignEOTSResponse); + + // SignSchnorrSig signs a Schnorr sig with the EOTS private key + rpc SignSchnorrSig (SignSchnorrSigRequest) + returns (SignSchnorrSigResponse); +} + +message PingRequest {} + +message PingResponse {} + +message CreateKeyRequest { + // name is the identifier key in keyring + string name = 1; + // passphrase is used to encrypt the EOTS key + string passphrase = 2; + // hd_path is the hd path for private key derivation + string hd_path = 3; +} + +message CreateKeyResponse { + // pk is the EOTS public key following BIP-340 spec + bytes pk = 1; +} + +message CreateRandomnessPairListRequest { + // uid is the identifier of an EOTS key, i.e., public key following BIP-340 spec + bytes uid = 1; + // chain_id is the identifier of the consumer chain that the randomness is committed to + bytes chain_id = 2; + // start_height is the start height of the randomness pair list + uint64 start_height = 3; + // num is the number of randomness pair list + uint32 num = 4; + // passphrase is used to decrypt the EOTS key + string passphrase = 5; +} + +message CreateRandomnessPairListResponse { + // pub_rand_list is a list of Schnorr public randomness + repeated bytes pub_rand_list = 1; +} + +message KeyRecordRequest { + // uid is the identifier of an EOTS key, i.e., public key following BIP-340 spec + bytes uid = 1; + // passphrase is used to decrypt the EOTS key + string passphrase = 2; +} + +message KeyRecordResponse { + // name is the identifier key in keyring + string name = 1; + // private_key is the private EOTS key encoded in secp256k1 spec + bytes private_key = 2; +} + +message SignEOTSRequest { + // uid is the identifier of an EOTS key, i.e., public key following BIP-340 spec + bytes uid = 1; + // chain_id is the identifier of the consumer chain that the randomness is committed to + bytes chain_id = 2; + // the message which the EOTS signs + bytes msg = 3; + // the block height which the EOTS signs + uint64 height = 4; + // passphrase is used to decrypt the EOTS key + string passphrase = 5; +} + +message SignEOTSResponse { + // sig is the EOTS signature + bytes sig = 1; +} + +message SignSchnorrSigRequest { + // uid is the identifier of an EOTS key, i.e., public key following BIP-340 spec + bytes uid = 1; + // the message which the Schnorr signature signs + bytes msg = 2; + // passphrase is used to decrypt the EOTS key + string passphrase = 3; +} + +message SignSchnorrSigResponse { + // sig is the Schnorr signature + bytes sig = 1; +} diff --git a/eotsmanager/proto/eotsmanager_grpc.pb.go b/eotsmanager/proto/eotsmanager_grpc.pb.go new file mode 100644 index 00000000..0a8814ad --- /dev/null +++ b/eotsmanager/proto/eotsmanager_grpc.pb.go @@ -0,0 +1,304 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.3.0 +// - protoc (unknown) +// source: eotsmanager.proto + +package proto + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +const ( + EOTSManager_Ping_FullMethodName = "/proto.EOTSManager/Ping" + EOTSManager_CreateKey_FullMethodName = "/proto.EOTSManager/CreateKey" + EOTSManager_CreateRandomnessPairList_FullMethodName = "/proto.EOTSManager/CreateRandomnessPairList" + EOTSManager_KeyRecord_FullMethodName = "/proto.EOTSManager/KeyRecord" + EOTSManager_SignEOTS_FullMethodName = "/proto.EOTSManager/SignEOTS" + EOTSManager_SignSchnorrSig_FullMethodName = "/proto.EOTSManager/SignSchnorrSig" +) + +// EOTSManagerClient is the client API for EOTSManager service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type EOTSManagerClient interface { + Ping(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*PingResponse, error) + // CreateKey generates and saves an EOTS key + CreateKey(ctx context.Context, in *CreateKeyRequest, opts ...grpc.CallOption) (*CreateKeyResponse, error) + // CreateRandomnessPairList returns a list of Schnorr randomness pairs + CreateRandomnessPairList(ctx context.Context, in *CreateRandomnessPairListRequest, opts ...grpc.CallOption) (*CreateRandomnessPairListResponse, error) + // KeyRecord returns the key record + KeyRecord(ctx context.Context, in *KeyRecordRequest, opts ...grpc.CallOption) (*KeyRecordResponse, error) + // SignEOTS signs an EOTS with the EOTS private key and the relevant randomness + SignEOTS(ctx context.Context, in *SignEOTSRequest, opts ...grpc.CallOption) (*SignEOTSResponse, error) + // SignSchnorrSig signs a Schnorr sig with the EOTS private key + SignSchnorrSig(ctx context.Context, in *SignSchnorrSigRequest, opts ...grpc.CallOption) (*SignSchnorrSigResponse, error) +} + +type eOTSManagerClient struct { + cc grpc.ClientConnInterface +} + +func NewEOTSManagerClient(cc grpc.ClientConnInterface) EOTSManagerClient { + return &eOTSManagerClient{cc} +} + +func (c *eOTSManagerClient) Ping(ctx context.Context, in *PingRequest, opts ...grpc.CallOption) (*PingResponse, error) { + out := new(PingResponse) + err := c.cc.Invoke(ctx, EOTSManager_Ping_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *eOTSManagerClient) CreateKey(ctx context.Context, in *CreateKeyRequest, opts ...grpc.CallOption) (*CreateKeyResponse, error) { + out := new(CreateKeyResponse) + err := c.cc.Invoke(ctx, EOTSManager_CreateKey_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *eOTSManagerClient) CreateRandomnessPairList(ctx context.Context, in *CreateRandomnessPairListRequest, opts ...grpc.CallOption) (*CreateRandomnessPairListResponse, error) { + out := new(CreateRandomnessPairListResponse) + err := c.cc.Invoke(ctx, EOTSManager_CreateRandomnessPairList_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *eOTSManagerClient) KeyRecord(ctx context.Context, in *KeyRecordRequest, opts ...grpc.CallOption) (*KeyRecordResponse, error) { + out := new(KeyRecordResponse) + err := c.cc.Invoke(ctx, EOTSManager_KeyRecord_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *eOTSManagerClient) SignEOTS(ctx context.Context, in *SignEOTSRequest, opts ...grpc.CallOption) (*SignEOTSResponse, error) { + out := new(SignEOTSResponse) + err := c.cc.Invoke(ctx, EOTSManager_SignEOTS_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *eOTSManagerClient) SignSchnorrSig(ctx context.Context, in *SignSchnorrSigRequest, opts ...grpc.CallOption) (*SignSchnorrSigResponse, error) { + out := new(SignSchnorrSigResponse) + err := c.cc.Invoke(ctx, EOTSManager_SignSchnorrSig_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// EOTSManagerServer is the server API for EOTSManager service. +// All implementations must embed UnimplementedEOTSManagerServer +// for forward compatibility +type EOTSManagerServer interface { + Ping(context.Context, *PingRequest) (*PingResponse, error) + // CreateKey generates and saves an EOTS key + CreateKey(context.Context, *CreateKeyRequest) (*CreateKeyResponse, error) + // CreateRandomnessPairList returns a list of Schnorr randomness pairs + CreateRandomnessPairList(context.Context, *CreateRandomnessPairListRequest) (*CreateRandomnessPairListResponse, error) + // KeyRecord returns the key record + KeyRecord(context.Context, *KeyRecordRequest) (*KeyRecordResponse, error) + // SignEOTS signs an EOTS with the EOTS private key and the relevant randomness + SignEOTS(context.Context, *SignEOTSRequest) (*SignEOTSResponse, error) + // SignSchnorrSig signs a Schnorr sig with the EOTS private key + SignSchnorrSig(context.Context, *SignSchnorrSigRequest) (*SignSchnorrSigResponse, error) + mustEmbedUnimplementedEOTSManagerServer() +} + +// UnimplementedEOTSManagerServer must be embedded to have forward compatible implementations. +type UnimplementedEOTSManagerServer struct { +} + +func (UnimplementedEOTSManagerServer) Ping(context.Context, *PingRequest) (*PingResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Ping not implemented") +} +func (UnimplementedEOTSManagerServer) CreateKey(context.Context, *CreateKeyRequest) (*CreateKeyResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CreateKey not implemented") +} +func (UnimplementedEOTSManagerServer) CreateRandomnessPairList(context.Context, *CreateRandomnessPairListRequest) (*CreateRandomnessPairListResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CreateRandomnessPairList not implemented") +} +func (UnimplementedEOTSManagerServer) KeyRecord(context.Context, *KeyRecordRequest) (*KeyRecordResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method KeyRecord not implemented") +} +func (UnimplementedEOTSManagerServer) SignEOTS(context.Context, *SignEOTSRequest) (*SignEOTSResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SignEOTS not implemented") +} +func (UnimplementedEOTSManagerServer) SignSchnorrSig(context.Context, *SignSchnorrSigRequest) (*SignSchnorrSigResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SignSchnorrSig not implemented") +} +func (UnimplementedEOTSManagerServer) mustEmbedUnimplementedEOTSManagerServer() {} + +// UnsafeEOTSManagerServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to EOTSManagerServer will +// result in compilation errors. +type UnsafeEOTSManagerServer interface { + mustEmbedUnimplementedEOTSManagerServer() +} + +func RegisterEOTSManagerServer(s grpc.ServiceRegistrar, srv EOTSManagerServer) { + s.RegisterService(&EOTSManager_ServiceDesc, srv) +} + +func _EOTSManager_Ping_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PingRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EOTSManagerServer).Ping(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: EOTSManager_Ping_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EOTSManagerServer).Ping(ctx, req.(*PingRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _EOTSManager_CreateKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateKeyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EOTSManagerServer).CreateKey(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: EOTSManager_CreateKey_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EOTSManagerServer).CreateKey(ctx, req.(*CreateKeyRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _EOTSManager_CreateRandomnessPairList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateRandomnessPairListRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EOTSManagerServer).CreateRandomnessPairList(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: EOTSManager_CreateRandomnessPairList_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EOTSManagerServer).CreateRandomnessPairList(ctx, req.(*CreateRandomnessPairListRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _EOTSManager_KeyRecord_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(KeyRecordRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EOTSManagerServer).KeyRecord(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: EOTSManager_KeyRecord_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EOTSManagerServer).KeyRecord(ctx, req.(*KeyRecordRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _EOTSManager_SignEOTS_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SignEOTSRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EOTSManagerServer).SignEOTS(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: EOTSManager_SignEOTS_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EOTSManagerServer).SignEOTS(ctx, req.(*SignEOTSRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _EOTSManager_SignSchnorrSig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SignSchnorrSigRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EOTSManagerServer).SignSchnorrSig(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: EOTSManager_SignSchnorrSig_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EOTSManagerServer).SignSchnorrSig(ctx, req.(*SignSchnorrSigRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// EOTSManager_ServiceDesc is the grpc.ServiceDesc for EOTSManager service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var EOTSManager_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "proto.EOTSManager", + HandlerType: (*EOTSManagerServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Ping", + Handler: _EOTSManager_Ping_Handler, + }, + { + MethodName: "CreateKey", + Handler: _EOTSManager_CreateKey_Handler, + }, + { + MethodName: "CreateRandomnessPairList", + Handler: _EOTSManager_CreateRandomnessPairList_Handler, + }, + { + MethodName: "KeyRecord", + Handler: _EOTSManager_KeyRecord_Handler, + }, + { + MethodName: "SignEOTS", + Handler: _EOTSManager_SignEOTS_Handler, + }, + { + MethodName: "SignSchnorrSig", + Handler: _EOTSManager_SignSchnorrSig_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "eotsmanager.proto", +} diff --git a/proto/scripts/protocgen.sh b/eotsmanager/proto/scripts/protocgen.sh similarity index 100% rename from proto/scripts/protocgen.sh rename to eotsmanager/proto/scripts/protocgen.sh diff --git a/eotsmanager/randgenerator/randgenerator.go b/eotsmanager/randgenerator/randgenerator.go new file mode 100644 index 00000000..570031f0 --- /dev/null +++ b/eotsmanager/randgenerator/randgenerator.go @@ -0,0 +1,29 @@ +package randgenerator + +import ( + "crypto/hmac" + "crypto/sha256" + + "github.com/babylonchain/babylon/crypto/eots" + "github.com/btcsuite/btcd/btcec/v2" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/decred/dcrd/dcrec/secp256k1/v4" +) + +// GenerateRandomness generates a random scalar with the given key and src +// the result is deterministic with each given input +func GenerateRandomness(key []byte, chainID []byte, height uint64) (*eots.PrivateRand, *eots.PublicRand) { + // calculate the randomn hash of the key concatenated with chainID and height + digest := hmac.New(sha256.New, key) + digest.Write(append(sdk.Uint64ToBigEndian(height), chainID...)) + randPre := digest.Sum(nil) + + // convert the hash into private random + var randScalar btcec.ModNScalar + randScalar.SetByteSlice(randPre) + privRand := secp256k1.NewPrivateKey(&randScalar) + var j secp256k1.JacobianPoint + privRand.PubKey().AsJacobian(&j) + + return &privRand.Key, &j.X +} diff --git a/eotsmanager/service/rpcserver.go b/eotsmanager/service/rpcserver.go new file mode 100644 index 00000000..b8cc4990 --- /dev/null +++ b/eotsmanager/service/rpcserver.go @@ -0,0 +1,116 @@ +package service + +import ( + "context" + + "google.golang.org/grpc" + + "github.com/babylonchain/finality-provider/eotsmanager" + "github.com/babylonchain/finality-provider/eotsmanager/proto" +) + +// rpcServer is the main RPC server for the EOTS daemon that handles +// gRPC incoming requests. +type rpcServer struct { + proto.UnimplementedEOTSManagerServer + + em eotsmanager.EOTSManager +} + +// newRPCServer creates a new RPC sever from the set of input dependencies. +func newRPCServer( + em eotsmanager.EOTSManager, +) *rpcServer { + + return &rpcServer{ + em: em, + } +} + +// RegisterWithGrpcServer registers the rpcServer with the passed root gRPC +// server. +func (r *rpcServer) RegisterWithGrpcServer(grpcServer *grpc.Server) error { + // Register the main RPC server. + proto.RegisterEOTSManagerServer(grpcServer, r) + return nil +} + +func (r *rpcServer) Ping(ctx context.Context, req *proto.PingRequest) (*proto.PingResponse, error) { + return &proto.PingResponse{}, nil +} + +// CreateKey generates and saves an EOTS key +func (r *rpcServer) CreateKey(ctx context.Context, req *proto.CreateKeyRequest) ( + *proto.CreateKeyResponse, error) { + + pk, err := r.em.CreateKey(req.Name, req.Passphrase, req.HdPath) + + if err != nil { + return nil, err + } + + return &proto.CreateKeyResponse{Pk: pk}, nil +} + +// CreateRandomnessPairList returns a list of Schnorr randomness pairs +func (r *rpcServer) CreateRandomnessPairList(ctx context.Context, req *proto.CreateRandomnessPairListRequest) ( + *proto.CreateRandomnessPairListResponse, error) { + + pubRandList, err := r.em.CreateRandomnessPairList(req.Uid, req.ChainId, req.StartHeight, req.Num, req.Passphrase) + + if err != nil { + return nil, err + } + + pubRandBytesList := make([][]byte, 0, len(pubRandList)) + for _, p := range pubRandList { + pubRandBytesList = append(pubRandBytesList, p.Bytes()[:]) + } + + return &proto.CreateRandomnessPairListResponse{ + PubRandList: pubRandBytesList, + }, nil +} + +// KeyRecord returns the key record +func (r *rpcServer) KeyRecord(ctx context.Context, req *proto.KeyRecordRequest) ( + *proto.KeyRecordResponse, error) { + + record, err := r.em.KeyRecord(req.Uid, req.Passphrase) + if err != nil { + return nil, err + } + + res := &proto.KeyRecordResponse{ + Name: record.Name, + PrivateKey: record.PrivKey.Serialize(), + } + + return res, nil +} + +// SignEOTS signs an EOTS with the EOTS private key and the relevant randomness +func (r *rpcServer) SignEOTS(ctx context.Context, req *proto.SignEOTSRequest) ( + *proto.SignEOTSResponse, error) { + + sig, err := r.em.SignEOTS(req.Uid, req.ChainId, req.Msg, req.Height, req.Passphrase) + if err != nil { + return nil, err + } + + sigBytes := sig.Bytes() + + return &proto.SignEOTSResponse{Sig: sigBytes[:]}, nil +} + +// SignSchnorrSig signs a Schnorr sig with the EOTS private key +func (r *rpcServer) SignSchnorrSig(ctx context.Context, req *proto.SignSchnorrSigRequest) ( + *proto.SignSchnorrSigResponse, error) { + + sig, err := r.em.SignSchnorrSig(req.Uid, req.Msg, req.Passphrase) + if err != nil { + return nil, err + } + + return &proto.SignSchnorrSigResponse{Sig: sig.Serialize()}, nil +} diff --git a/eotsmanager/service/server.go b/eotsmanager/service/server.go new file mode 100644 index 00000000..f16008c8 --- /dev/null +++ b/eotsmanager/service/server.go @@ -0,0 +1,109 @@ +package service + +import ( + "fmt" + "net" + "sync" + "sync/atomic" + + "github.com/lightningnetwork/lnd/signal" + "go.uber.org/zap" + "google.golang.org/grpc" + + "github.com/babylonchain/finality-provider/eotsmanager" + "github.com/babylonchain/finality-provider/eotsmanager/config" +) + +// Server is the main daemon construct for the EOTS manager server. It handles +// spinning up the RPC sever, the database, and any other components that the +// EOTS manager server needs to function. +type Server struct { + started int32 + + cfg *config.Config + logger *zap.Logger + + rpcServer *rpcServer + interceptor signal.Interceptor + + quit chan struct{} +} + +// NewEOTSManagerServer creates a new server with the given config. +func NewEOTSManagerServer(cfg *config.Config, l *zap.Logger, em eotsmanager.EOTSManager, sig signal.Interceptor) *Server { + return &Server{ + cfg: cfg, + logger: l, + rpcServer: newRPCServer(em), + interceptor: sig, + quit: make(chan struct{}, 1), + } +} + +// RunUntilShutdown runs the main EOTS manager server loop until a signal is +// received to shut down the process. +func (s *Server) RunUntilShutdown() error { + if atomic.AddInt32(&s.started, 1) != 1 { + return nil + } + + defer func() { + s.logger.Info("Shutdown complete") + }() + + listenAddr := s.cfg.RpcListener + // we create listeners from the RPCListeners defined + // in the config. + lis, err := net.Listen("tcp", listenAddr) + if err != nil { + return fmt.Errorf("failed to listen on %s: %w", listenAddr, err) + } + defer lis.Close() + + grpcServer := grpc.NewServer() + defer grpcServer.Stop() + + if err := s.rpcServer.RegisterWithGrpcServer(grpcServer); err != nil { + return fmt.Errorf("failed to register gRPC server: %w", err) + } + + // All the necessary components have been registered, so we can + // actually start listening for requests. + if err := s.startGrpcListen(grpcServer, []net.Listener{lis}); err != nil { + return fmt.Errorf("failed to start gRPC listener: %v", err) + } + + s.logger.Info("EOTS Manager Daemon is fully active!") + + // Wait for shutdown signal from either a graceful server stop or from + // the interrupt handler. + <-s.interceptor.ShutdownChannel() + + return nil +} + +// startGrpcListen starts the GRPC server on the passed listeners. +func (s *Server) startGrpcListen(grpcServer *grpc.Server, listeners []net.Listener) error { + + // Use a WaitGroup so we can be sure the instructions on how to input the + // password is the last thing to be printed to the console. + var wg sync.WaitGroup + + for _, lis := range listeners { + wg.Add(1) + go func(lis net.Listener) { + s.logger.Info("RPC server listening", zap.String("address", lis.Addr().String())) + + // Close the ready chan to indicate we are listening. + defer lis.Close() + + wg.Done() + _ = grpcServer.Serve(lis) + }(lis) + } + + // Wait for gRPC servers to be up running. + wg.Wait() + + return nil +} diff --git a/eotsmanager/types/errors.go b/eotsmanager/types/errors.go new file mode 100644 index 00000000..2d2879fd --- /dev/null +++ b/eotsmanager/types/errors.go @@ -0,0 +1,7 @@ +package types + +import "errors" + +var ( + ErrFinalityProviderAlreadyExisted = errors.New("the finality provider has already existed") +) diff --git a/eotsmanager/types/val_record.go b/eotsmanager/types/val_record.go new file mode 100644 index 00000000..44a0c77c --- /dev/null +++ b/eotsmanager/types/val_record.go @@ -0,0 +1,8 @@ +package types + +import "github.com/btcsuite/btcd/btcec/v2" + +type KeyRecord struct { + Name string + PrivKey *btcec.PrivateKey +} diff --git a/finality-provider/Makefile b/finality-provider/Makefile new file mode 100644 index 00000000..abc4da72 --- /dev/null +++ b/finality-provider/Makefile @@ -0,0 +1,10 @@ +############################################################################### +### Protobuf ### +############################################################################### + +proto-all: proto-gen + +proto-gen: + ./proto/scripts/protocgen.sh + +.PHONY: proto-gen diff --git a/finality-provider/cmd/fpcli/daemoncmd.go b/finality-provider/cmd/fpcli/daemoncmd.go new file mode 100644 index 00000000..f058764a --- /dev/null +++ b/finality-provider/cmd/fpcli/daemoncmd.go @@ -0,0 +1,371 @@ +package main + +import ( + "context" + "encoding/hex" + "fmt" + + "cosmossdk.io/math" + bbntypes "github.com/babylonchain/babylon/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/urfave/cli" + + fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" + dc "github.com/babylonchain/finality-provider/finality-provider/service/client" +) + +var ( + defaultAppHashStr = "fd903d9baeb3ab1c734ee003de75f676c5a9a8d0574647e5385834d57d3e79ec" +) + +var getDaemonInfoCmd = cli.Command{ + Name: "get-info", + ShortName: "gi", + Usage: "Get information of the running daemon.", + Action: getInfo, + Flags: []cli.Flag{ + cli.StringFlag{ + Name: fpdDaemonAddressFlag, + Usage: "The RPC server address of fpd", + Value: defaultFpdDaemonAddress, + }, + }, +} + +func getInfo(ctx *cli.Context) error { + daemonAddress := ctx.String(fpdDaemonAddressFlag) + client, cleanUp, err := dc.NewFinalityProviderServiceGRpcClient(daemonAddress) + if err != nil { + return err + } + defer cleanUp() + + info, err := client.GetInfo(context.Background()) + + if err != nil { + return err + } + + printRespJSON(info) + + return nil +} + +var createFpDaemonCmd = cli.Command{ + Name: "create-finality-provider", + ShortName: "cfp", + Usage: "Create a finality provider object and save it in database.", + Flags: []cli.Flag{ + cli.StringFlag{ + Name: fpdDaemonAddressFlag, + Usage: "The RPC server address of fpd", + Value: defaultFpdDaemonAddress, + }, + cli.StringFlag{ + Name: keyNameFlag, + Usage: "The unique name of the finality provider key", + }, + cli.StringFlag{ + Name: homeFlag, + Usage: "The home path of the finality provider daemon (fpd)", + Value: fpcfg.DefaultFpdDir, + }, + cli.StringFlag{ + Name: chainIdFlag, + Usage: "The identifier of the consumer chain", + Required: true, + }, + cli.StringFlag{ + Name: passphraseFlag, + Usage: "The pass phrase used to encrypt the keys", + Value: defaultPassphrase, + }, + cli.StringFlag{ + Name: hdPathFlag, + Usage: "The hd path used to derive the private key", + Value: defaultHdPath, + }, + cli.StringFlag{ + Name: commissionRateFlag, + Usage: "The commission rate for the finality provider, e.g., 0.05", + Value: "0.05", + }, + cli.StringFlag{ + Name: monikerFlag, + Usage: "A human-readable name for the finality provider", + Value: "", + }, + cli.StringFlag{ + Name: identityFlag, + Usage: "An optional identity signature (ex. UPort or Keybase)", + Value: "", + }, + cli.StringFlag{ + Name: websiteFlag, + Usage: "An optional website link", + Value: "", + }, + cli.StringFlag{ + Name: securityContractFlag, + Usage: "An optional email for security contact", + Value: "", + }, + cli.StringFlag{ + Name: detailsFlag, + Usage: "Other optional details", + Value: "", + }, + }, + Action: createFpDaemon, +} + +func createFpDaemon(ctx *cli.Context) error { + daemonAddress := ctx.String(fpdDaemonAddressFlag) + + commissionRate, err := math.LegacyNewDecFromStr(ctx.String(commissionRateFlag)) + if err != nil { + return fmt.Errorf("invalid commission rate: %w", err) + } + + description, err := getDescriptionFromContext(ctx) + if err != nil { + return fmt.Errorf("invalid description: %w", err) + } + + // we add the following check to ensure that the chain key is created + // beforehand + cfg, err := fpcfg.LoadConfig(ctx.String(homeFlag)) + if err != nil { + return fmt.Errorf("failed to load config from %s: %w", fpcfg.ConfigFile(ctx.String(homeFlag)), err) + } + + keyName := ctx.String(keyNameFlag) + // if key name is not specified, we use the key of the config + if keyName == "" { + keyName = cfg.BabylonConfig.Key + if keyName == "" { + return fmt.Errorf("the key in config is empty") + } + } + + client, cleanUp, err := dc.NewFinalityProviderServiceGRpcClient(daemonAddress) + if err != nil { + return err + } + defer cleanUp() + + info, err := client.CreateFinalityProvider( + context.Background(), + keyName, + ctx.String(chainIdFlag), + ctx.String(passphraseFlag), + ctx.String(hdPathFlag), + description, + &commissionRate, + ) + + if err != nil { + return err + } + + printRespJSON(info.FinalityProvider) + + return nil +} + +func getDescriptionFromContext(ctx *cli.Context) (stakingtypes.Description, error) { + // get information for description + monikerStr := ctx.String(monikerFlag) + identityStr := ctx.String(identityFlag) + websiteStr := ctx.String(websiteFlag) + securityContractStr := ctx.String(securityContractFlag) + detailsStr := ctx.String(detailsFlag) + + description := stakingtypes.NewDescription(monikerStr, identityStr, websiteStr, securityContractStr, detailsStr) + + return description.EnsureLength() +} + +var lsFpDaemonCmd = cli.Command{ + Name: "list-finality-providers", + ShortName: "ls", + Usage: "List finality providers stored in the database.", + Action: lsFpDaemon, + Flags: []cli.Flag{ + cli.StringFlag{ + Name: fpdDaemonAddressFlag, + Usage: "The RPC server address of fpd", + Value: defaultFpdDaemonAddress, + }, + }, +} + +func lsFpDaemon(ctx *cli.Context) error { + daemonAddress := ctx.String(fpdDaemonAddressFlag) + rpcClient, cleanUp, err := dc.NewFinalityProviderServiceGRpcClient(daemonAddress) + if err != nil { + return err + } + defer cleanUp() + + resp, err := rpcClient.QueryFinalityProviderList(context.Background()) + if err != nil { + return err + } + + printRespJSON(resp) + + return nil +} + +var fpInfoDaemonCmd = cli.Command{ + Name: "finality-provider-info", + ShortName: "fpi", + Usage: "Show the information of the finality provider.", + Flags: []cli.Flag{ + cli.StringFlag{ + Name: fpdDaemonAddressFlag, + Usage: "The RPC server address of fpd", + Value: defaultFpdDaemonAddress, + }, + cli.StringFlag{ + Name: fpBTCPkFlag, + Usage: "The hex string of the BTC public key", + Required: true, + }, + }, + Action: fpInfoDaemon, +} + +func fpInfoDaemon(ctx *cli.Context) error { + daemonAddress := ctx.String(fpdDaemonAddressFlag) + rpcClient, cleanUp, err := dc.NewFinalityProviderServiceGRpcClient(daemonAddress) + if err != nil { + return err + } + defer cleanUp() + + fpPk, err := bbntypes.NewBIP340PubKeyFromHex(ctx.String(fpBTCPkFlag)) + if err != nil { + return err + } + + resp, err := rpcClient.QueryFinalityProviderInfo(context.Background(), fpPk) + if err != nil { + return err + } + + printRespJSON(resp.FinalityProvider) + + return nil +} + +var registerFpDaemonCmd = cli.Command{ + Name: "register-finality-provider", + ShortName: "rfp", + Usage: "Register a created finality provider to Babylon.", + UsageText: fmt.Sprintf("register-finality-provider --%s [btc-pk]", fpBTCPkFlag), + Flags: []cli.Flag{ + cli.StringFlag{ + Name: fpdDaemonAddressFlag, + Usage: "The RPC server address of fpd", + Value: defaultFpdDaemonAddress, + }, + cli.StringFlag{ + Name: fpBTCPkFlag, + Usage: "The hex string of the finality provider BTC public key", + Required: true, + }, + cli.StringFlag{ + Name: passphraseFlag, + Usage: "The pass phrase used to encrypt the keys", + Value: defaultPassphrase, + }, + }, + Action: registerFp, +} + +func registerFp(ctx *cli.Context) error { + fpPkStr := ctx.String(fpBTCPkFlag) + fpPk, err := bbntypes.NewBIP340PubKeyFromHex(fpPkStr) + if err != nil { + return fmt.Errorf("invalid BTC public key: %w", err) + } + + daemonAddress := ctx.String(fpdDaemonAddressFlag) + rpcClient, cleanUp, err := dc.NewFinalityProviderServiceGRpcClient(daemonAddress) + if err != nil { + return err + } + defer cleanUp() + + res, err := rpcClient.RegisterFinalityProvider(context.Background(), fpPk, ctx.String(passphraseFlag)) + if err != nil { + return err + } + + printRespJSON(res) + + return nil +} + +// addFinalitySigDaemonCmd allows manual submission of finality signatures +// NOTE: should only be used for presentation/testing purposes +var addFinalitySigDaemonCmd = cli.Command{ + Name: "add-finality-sig", + ShortName: "afs", + Usage: "Send a finality signature to the consumer chain. This command should only be used for presentation/testing purposes", + UsageText: fmt.Sprintf("add-finality-sig --%s [btc_pk_hex]", fpBTCPkFlag), + Flags: []cli.Flag{ + cli.StringFlag{ + Name: fpdDaemonAddressFlag, + Usage: "The RPC server address of fpd", + Value: defaultFpdDaemonAddress, + }, + cli.StringFlag{ + Name: fpBTCPkFlag, + Usage: "The hex string of the BTC public key", + Required: true, + }, + cli.Uint64Flag{ + Name: blockHeightFlag, + Usage: "The height of the chain block", + Required: true, + }, + cli.StringFlag{ + Name: appHashFlag, + Usage: "The last commit hash of the chain block", + Value: defaultAppHashStr, + }, + }, + Action: addFinalitySig, +} + +func addFinalitySig(ctx *cli.Context) error { + daemonAddress := ctx.String(fpdDaemonAddressFlag) + rpcClient, cleanUp, err := dc.NewFinalityProviderServiceGRpcClient(daemonAddress) + if err != nil { + return err + } + defer cleanUp() + + fpPk, err := bbntypes.NewBIP340PubKeyFromHex(ctx.String(fpBTCPkFlag)) + if err != nil { + return err + } + + appHash, err := hex.DecodeString(ctx.String(appHashFlag)) + if err != nil { + return err + } + + res, err := rpcClient.AddFinalitySignature( + context.Background(), fpPk.MarshalHex(), ctx.Uint64(blockHeightFlag), appHash) + if err != nil { + return err + } + + printRespJSON(res) + + return nil +} diff --git a/finality-provider/cmd/fpcli/flags.go b/finality-provider/cmd/fpcli/flags.go new file mode 100644 index 00000000..81170016 --- /dev/null +++ b/finality-provider/cmd/fpcli/flags.go @@ -0,0 +1,23 @@ +package main + +const ( + fpdDaemonAddressFlag = "daemon-address" + keyNameFlag = "key-name" + homeFlag = "home" + fpBTCPkFlag = "btc-pk" + blockHeightFlag = "height" + appHashFlag = "app-hash" + passphraseFlag = "passphrase" + hdPathFlag = "hd-path" + chainIdFlag = "chain-id" + defaultPassphrase = "" + defaultHdPath = "" + + // flags for description + monikerFlag = "moniker" + identityFlag = "identity" + websiteFlag = "website" + securityContractFlag = "security-contract" + detailsFlag = "details" + commissionRateFlag = "commission" +) diff --git a/finality-provider/cmd/fpcli/main.go b/finality-provider/cmd/fpcli/main.go new file mode 100644 index 00000000..a4d84e9c --- /dev/null +++ b/finality-provider/cmd/fpcli/main.go @@ -0,0 +1,50 @@ +package main + +import ( + "encoding/json" + "fmt" + "os" + "strconv" + + "github.com/urfave/cli" + + fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" +) + +var ( + defaultFpdDaemonAddress = "127.0.0.1:" + strconv.Itoa(fpcfg.DefaultRPCPort) +) + +func fatal(err error) { + fmt.Fprintf(os.Stderr, "[fpd] %v\n", err) + os.Exit(1) +} + +func printRespJSON(resp interface{}) { + jsonBytes, err := json.MarshalIndent(resp, "", " ") + if err != nil { + fmt.Println("unable to decode response: ", err) + return + } + + fmt.Printf("%s\n", jsonBytes) +} + +func main() { + app := cli.NewApp() + app.Name = "fpcli" + app.Usage = "Control plane for the Finality Provider Daemon (fpd)." + + app.Commands = append(app.Commands, + getDaemonInfoCmd, + createFpDaemonCmd, + lsFpDaemonCmd, + fpInfoDaemonCmd, + registerFpDaemonCmd, + addFinalitySigDaemonCmd, + ) + + if err := app.Run(os.Args); err != nil { + fatal(err) + } +} diff --git a/finality-provider/cmd/fpd/flags.go b/finality-provider/cmd/fpd/flags.go new file mode 100644 index 00000000..9d79f802 --- /dev/null +++ b/finality-provider/cmd/fpd/flags.go @@ -0,0 +1,19 @@ +package main + +import "github.com/cosmos/cosmos-sdk/crypto/keyring" + +const ( + homeFlag = "home" + forceFlag = "force" + passphraseFlag = "passphrase" + fpPkFlag = "btc-pk" + keyNameFlag = "key-name" + hdPathFlag = "hd-path" + chainIdFlag = "chain-id" + keyringBackendFlag = "keyring-backend" + rpcListenerFlag = "rpc-listener" + + defaultKeyringBackend = keyring.BackendTest + defaultHdPath = "" + defaultPassphrase = "" +) diff --git a/finality-provider/cmd/fpd/init.go b/finality-provider/cmd/fpd/init.go new file mode 100644 index 00000000..6216eef7 --- /dev/null +++ b/finality-provider/cmd/fpd/init.go @@ -0,0 +1,58 @@ +package main + +import ( + "fmt" + "path/filepath" + + "github.com/jessevdk/go-flags" + "github.com/urfave/cli" + + fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" + "github.com/babylonchain/finality-provider/util" +) + +var initCommand = cli.Command{ + Name: "init", + Usage: "Initialize a finality-provider home directory.", + Flags: []cli.Flag{ + cli.StringFlag{ + Name: homeFlag, + Usage: "Path to where the home directory will be initialized", + Value: fpcfg.DefaultFpdDir, + }, + cli.BoolFlag{ + Name: forceFlag, + Usage: "Override existing configuration", + Required: false, + }, + }, + Action: initHome, +} + +func initHome(c *cli.Context) error { + homePath, err := filepath.Abs(c.String(homeFlag)) + if err != nil { + return err + } + // Create home directory + homePath = util.CleanAndExpandPath(homePath) + force := c.Bool(forceFlag) + + if util.FileExists(homePath) && !force { + return fmt.Errorf("home path %s already exists", homePath) + } + + if err := util.MakeDirectory(homePath); err != nil { + return err + } + // Create log directory + logDir := fpcfg.LogDir(homePath) + if err := util.MakeDirectory(logDir); err != nil { + return err + } + + defaultConfig := fpcfg.DefaultConfigWithHome(homePath) + fileParser := flags.NewParser(&defaultConfig, flags.Default) + + return flags.NewIniParser(fileParser).WriteFile(fpcfg.ConfigFile(homePath), flags.IniIncludeComments|flags.IniIncludeDefaults) +} diff --git a/finality-provider/cmd/fpd/keys.go b/finality-provider/cmd/fpd/keys.go new file mode 100644 index 00000000..c39dacd3 --- /dev/null +++ b/finality-provider/cmd/fpd/keys.go @@ -0,0 +1,120 @@ +package main + +import ( + "encoding/json" + "fmt" + + "github.com/jessevdk/go-flags" + "github.com/urfave/cli" + + fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" + "github.com/babylonchain/finality-provider/finality-provider/service" +) + +type KeyOutput struct { + Name string `json:"name" yaml:"name"` + Address string `json:"address" yaml:"address"` + Mnemonic string `json:"mnemonic,omitempty" yaml:"mnemonic"` +} + +var keysCommands = []cli.Command{ + { + Name: "keys", + Usage: "Command sets of managing keys for interacting with the consumer chain.", + Category: "Key management", + Subcommands: []cli.Command{ + addKeyCmd, + }, + }, +} + +var addKeyCmd = cli.Command{ + Name: "add", + Usage: "Add a key to the consumer chain's keyring. Note that this will change the config file in place.", + Flags: []cli.Flag{ + cli.StringFlag{ + Name: homeFlag, + Usage: "Path to the keyring directory", + Value: fpcfg.DefaultFpdDir, + }, + cli.StringFlag{ + Name: keyNameFlag, + Required: true, + }, + cli.StringFlag{ + Name: chainIdFlag, + Usage: "The identifier of the consumer chain", + Required: true, + }, + cli.StringFlag{ + Name: keyringBackendFlag, + Usage: "Select keyring's backend", + Value: defaultKeyringBackend, + }, + cli.StringFlag{ + Name: passphraseFlag, + Usage: "The pass phrase used to encrypt the keys", + Value: defaultPassphrase, + }, + cli.StringFlag{ + Name: hdPathFlag, + Usage: "The hd path used to derive the private key", + Value: defaultHdPath, + }, + }, + Action: addKey, +} + +func addKey(ctx *cli.Context) error { + homePath := ctx.String(homeFlag) + chainID := ctx.String(chainIdFlag) + keyName := ctx.String(keyNameFlag) + backend := ctx.String(keyringBackendFlag) + passphrase := ctx.String(passphraseFlag) + hdPath := ctx.String(hdPathFlag) + keyBackend := ctx.String(keyringBackendFlag) + + // check the config file exists + cfg, err := fpcfg.LoadConfig(homePath) + if err != nil { + return fmt.Errorf("failed to load the config from %s: %w", fpcfg.ConfigFile(homePath), err) + } + + keyInfo, err := service.CreateChainKey( + homePath, + chainID, + keyName, + backend, + passphrase, + hdPath, + ) + if err != nil { + return fmt.Errorf("failed to create the chain key: %w", err) + } + + printRespJSON( + KeyOutput{ + Name: keyName, + Address: keyInfo.AccAddress.String(), + Mnemonic: keyInfo.Mnemonic, + }, + ) + + // write the updated config into the config file + cfg.BabylonConfig.Key = keyName + cfg.BabylonConfig.KeyringBackend = keyBackend + fileParser := flags.NewParser(cfg, flags.Default) + + return flags.NewIniParser(fileParser).WriteFile(fpcfg.ConfigFile(homePath), flags.IniIncludeComments|flags.IniIncludeDefaults) +} + +func printRespJSON(resp interface{}) { + jsonBytes, err := json.MarshalIndent(resp, "", " ") + if err != nil { + fmt.Println("unable to decode response: ", err) + return + } + + fmt.Printf("New key for the consumer chain is created "+ + "(mnemonic should be kept in a safe place for recovery):\n%s\n", jsonBytes) +} diff --git a/finality-provider/cmd/fpd/main.go b/finality-provider/cmd/fpd/main.go new file mode 100644 index 00000000..1594b07c --- /dev/null +++ b/finality-provider/cmd/fpd/main.go @@ -0,0 +1,25 @@ +package main + +import ( + "fmt" + "os" + + "github.com/urfave/cli" +) + +func fatal(err error) { + fmt.Fprintf(os.Stderr, "[btc-finality-provider] %v\n", err) + os.Exit(1) +} + +func main() { + app := cli.NewApp() + app.Name = "fpd" + app.Usage = "Finality Provider Daemon (fpd)." + app.Commands = append(app.Commands, startCommand, initCommand) + app.Commands = append(app.Commands, keysCommands...) + + if err := app.Run(os.Args); err != nil { + fatal(err) + } +} diff --git a/finality-provider/cmd/fpd/start.go b/finality-provider/cmd/fpd/start.go new file mode 100644 index 00000000..86868164 --- /dev/null +++ b/finality-provider/cmd/fpd/start.go @@ -0,0 +1,109 @@ +package main + +import ( + "fmt" + "net" + "path/filepath" + + "github.com/babylonchain/babylon/types" + "github.com/lightningnetwork/lnd/signal" + "github.com/urfave/cli" + + fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" + "github.com/babylonchain/finality-provider/finality-provider/service" + "github.com/babylonchain/finality-provider/log" + "github.com/babylonchain/finality-provider/util" +) + +var startCommand = cli.Command{ + Name: "start", + Usage: "Start the finality-provider app", + Description: "Start the finality-provider app. Note that eotsd should be started beforehand", + Flags: []cli.Flag{ + cli.StringFlag{ + Name: passphraseFlag, + Usage: "The pass phrase used to decrypt the private key", + Value: defaultPassphrase, + }, + cli.StringFlag{ + Name: homeFlag, + Usage: "The path to the finality-provider home directory", + Value: fpcfg.DefaultFpdDir, + }, + cli.StringFlag{ + Name: fpPkFlag, + Usage: "The public key of the finality-provider to start", + }, + cli.StringFlag{ + Name: rpcListenerFlag, + Usage: "The address that the RPC server listens to", + }, + }, + Action: start, +} + +func start(ctx *cli.Context) error { + homePath, err := filepath.Abs(ctx.String(homeFlag)) + if err != nil { + return err + } + homePath = util.CleanAndExpandPath(homePath) + + passphrase := ctx.String(passphraseFlag) + fpPkStr := ctx.String(fpPkFlag) + rpcListener := ctx.String(rpcListenerFlag) + + cfg, err := fpcfg.LoadConfig(homePath) + if err != nil { + return fmt.Errorf("failed to load configuration: %w", err) + } + + if rpcListener != "" { + _, err := net.ResolveTCPAddr("tcp", rpcListener) + if err != nil { + return fmt.Errorf("invalid RPC listener address %s, %w", rpcListener, err) + } + cfg.RpcListener = rpcListener + } + + logger, err := log.NewRootLoggerWithFile(fpcfg.LogFile(homePath), cfg.LogLevel) + if err != nil { + return fmt.Errorf("failed to initialize the logger") + } + + fpApp, err := service.NewFinalityProviderAppFromConfig(homePath, cfg, logger) + if err != nil { + return fmt.Errorf("failed to create finality-provider app: %v", err) + } + + // only start the app without starting any finality-provider instance + // as there might be no finality-provider registered yet + if err := fpApp.Start(); err != nil { + return fmt.Errorf("failed to start the finality-provider app: %w", err) + } + + if fpPkStr != "" { + // start the finality-provider instance with the given public key + fpPk, err := types.NewBIP340PubKeyFromHex(fpPkStr) + if err != nil { + return fmt.Errorf("invalid finality-provider public key %s: %w", fpPkStr, err) + } + if err := fpApp.StartHandlingFinalityProvider(fpPk, passphrase); err != nil { + return fmt.Errorf("failed to start the finality-provider instance %s: %w", fpPkStr, err) + } + } else { + if err := fpApp.StartHandlingAll(); err != nil { + return err + } + } + + // Hook interceptor for os signals. + shutdownInterceptor, err := signal.Intercept() + if err != nil { + return err + } + + fpServer := service.NewFinalityProviderServer(cfg, logger, fpApp, shutdownInterceptor) + + return fpServer.RunUntilShutdown() +} diff --git a/finality-provider/config/config.go b/finality-provider/config/config.go new file mode 100644 index 00000000..24bec710 --- /dev/null +++ b/finality-provider/config/config.go @@ -0,0 +1,210 @@ +package fpcfg + +import ( + "fmt" + "net" + "path/filepath" + "strconv" + "time" + + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg" + "github.com/jessevdk/go-flags" + + "github.com/babylonchain/finality-provider/config" + eotscfg "github.com/babylonchain/finality-provider/eotsmanager/config" + "github.com/babylonchain/finality-provider/util" +) + +const ( + defaultChainName = "babylon" + defaultLogLevel = "info" + defaultLogDirname = "logs" + defaultLogFilename = "fpd.log" + defaultFinalityProviderKeyName = "finality-provider" + DefaultRPCPort = 12581 + defaultConfigFileName = "fpd.conf" + defaultNumPubRand = 100 + defaultNumPubRandMax = 200 + defaultMinRandHeightGap = 20 + defaultStatusUpdateInterval = 20 * time.Second + defaultRandomInterval = 30 * time.Second + defaultSubmitRetryInterval = 1 * time.Second + defaultFastSyncInterval = 10 * time.Second + defaultFastSyncLimit = 10 + defaultFastSyncGap = 3 + defaultMaxSubmissionRetries = 20 + defaultBitcoinNetwork = "signet" + defaultDataDirname = "data" + defaultDBPath = "bbolt-fpd.db" + defaultMaxNumFinalityProviders = 3 +) + +var ( + // C:\Users\\AppData\Local\ on Windows + // ~/.fpd on Linux + // ~/Users//Library/Application Support/Fpd on MacOS + DefaultFpdDir = btcutil.AppDataDir("fpd", false) + + defaultBTCNetParams = chaincfg.SigNetParams + defaultEOTSManagerAddress = "127.0.0.1:" + strconv.Itoa(eotscfg.DefaultRPCPort) + DefaultRpcListener = "127.0.0.1:" + strconv.Itoa(DefaultRPCPort) +) + +// Config is the main config for the fpd cli command +type Config struct { + LogLevel string `long:"loglevel" description:"Logging level for all subsystems" choice:"trace" choice:"debug" choice:"info" choice:"warn" choice:"error" choice:"fatal"` + // ChainName and ChainID (if any) of the chain config identify a consumer chain + ChainName string `long:"chainname" description:"the name of the consumer chain" choice:"babylon"` + NumPubRand uint64 `long:"numPubRand" description:"The number of Schnorr public randomness for each commitment"` + NumPubRandMax uint64 `long:"numpubrandmax" description:"The upper bound of the number of Schnorr public randomness for each commitment"` + MinRandHeightGap uint64 `long:"minrandheightgap" description:"The minimum gap between the last committed rand height and the current Babylon block height"` + StatusUpdateInterval time.Duration `long:"statusupdateinterval" description:"The interval between each update of finality-provider status"` + RandomnessCommitInterval time.Duration `long:"randomnesscommitinterval" description:"The interval between each attempt to commit public randomness"` + SubmissionRetryInterval time.Duration `long:"submissionretryinterval" description:"The interval between each attempt to submit finality signature or public randomness after a failure"` + MaxSubmissionRetries uint64 `long:"maxsubmissionretries" description:"The maximum number of retries to submit finality signature or public randomness"` + FastSyncInterval time.Duration `long:"fastsyncinterval" description:"The interval between each try of fast sync, which is disabled if the value is 0"` + FastSyncLimit uint64 `long:"fastsynclimit" description:"The maximum number of blocks to catch up for each fast sync"` + FastSyncGap uint64 `long:"fastsyncgap" description:"The block gap that will trigger the fast sync"` + EOTSManagerAddress string `long:"eotsmanageraddress" description:"The address of the remote EOTS manager; Empty if the EOTS manager is running locally"` + MaxNumFinalityProviders uint32 `long:"maxnumfinalityproviders" description:"The maximum number of finality-provider instances running concurrently within the daemon"` + + BitcoinNetwork string `long:"bitcoinnetwork" description:"Bitcoin network to run on" choise:"mainnet" choice:"regtest" choice:"testnet" choice:"simnet" choice:"signet"` + + BTCNetParams chaincfg.Params + + PollerConfig *ChainPollerConfig `group:"chainpollerconfig" namespace:"chainpollerconfig"` + + DatabaseConfig *config.DatabaseConfig `group:"databaseconfig" namespace:"databaseconfig"` + + BabylonConfig *config.BBNConfig `group:"babylon" namespace:"babylon"` + + RpcListener string `long:"rpclistener" description:"the listener for RPC connections, e.g., 127.0.0.1:1234"` +} + +func DefaultConfigWithHome(homePath string) Config { + bbnCfg := config.DefaultBBNConfig() + bbnCfg.Key = defaultFinalityProviderKeyName + bbnCfg.KeyDirectory = homePath + dbCfg := config.DefaultDatabaseConfig() + pollerCfg := DefaultChainPollerConfig() + cfg := Config{ + ChainName: defaultChainName, + LogLevel: defaultLogLevel, + DatabaseConfig: &dbCfg, + BabylonConfig: &bbnCfg, + PollerConfig: &pollerCfg, + NumPubRand: defaultNumPubRand, + NumPubRandMax: defaultNumPubRandMax, + MinRandHeightGap: defaultMinRandHeightGap, + StatusUpdateInterval: defaultStatusUpdateInterval, + RandomnessCommitInterval: defaultRandomInterval, + SubmissionRetryInterval: defaultSubmitRetryInterval, + FastSyncInterval: defaultFastSyncInterval, + FastSyncLimit: defaultFastSyncLimit, + FastSyncGap: defaultFastSyncGap, + MaxSubmissionRetries: defaultMaxSubmissionRetries, + BitcoinNetwork: defaultBitcoinNetwork, + BTCNetParams: defaultBTCNetParams, + EOTSManagerAddress: defaultEOTSManagerAddress, + RpcListener: DefaultRpcListener, + MaxNumFinalityProviders: defaultMaxNumFinalityProviders, + } + + if err := cfg.Validate(); err != nil { + panic(err) + } + + return cfg +} + +func DefaultConfig() Config { + return DefaultConfigWithHome(DefaultFpdDir) +} + +func ConfigFile(homePath string) string { + return filepath.Join(homePath, defaultConfigFileName) +} + +func LogDir(homePath string) string { + return filepath.Join(homePath, defaultLogDirname) +} + +func LogFile(homePath string) string { + return filepath.Join(LogDir(homePath), defaultLogFilename) +} + +func DataDir(homePath string) string { + return filepath.Join(homePath, defaultDataDirname) +} + +func DBPath(homePath string) string { + return filepath.Join(DataDir(homePath), defaultDBPath) +} + +// LoadConfig initializes and parses the config using a config file and command +// line options. +// +// The configuration proceeds as follows: +// 1. Start with a default config with sane settings +// 2. Pre-parse the command line to check for an alternative config file +// 3. Load configuration file overwriting defaults with any specified options +// 4. Parse CLI options and overwrite/add any specified options +func LoadConfig(homePath string) (*Config, error) { + // The home directory is required to have a configuration file with a specific name + // under it. + cfgFile := ConfigFile(homePath) + if !util.FileExists(cfgFile) { + return nil, fmt.Errorf("specified config file does "+ + "not exist in %s", cfgFile) + } + + // Next, load any additional configuration options from the file. + var cfg Config + fileParser := flags.NewParser(&cfg, flags.Default) + err := flags.NewIniParser(fileParser).ParseFile(cfgFile) + if err != nil { + return nil, err + } + + // Make sure everything we just loaded makes sense. + if err := cfg.Validate(); err != nil { + return nil, err + } + + return &cfg, nil +} + +// Validate checks the given configuration to be sane. This makes sure no +// illegal values or combination of values are set. All file system paths are +// normalized. The cleaned up config is returned on success. +func (cfg *Config) Validate() error { + if cfg.EOTSManagerAddress == "" { + return fmt.Errorf("EOTS manager address not specified") + } + // Multiple networks can't be selected simultaneously. Count number of + // network flags passed; assign active network params + // while we're at it. + switch cfg.BitcoinNetwork { + case "mainnet": + cfg.BTCNetParams = chaincfg.MainNetParams + case "testnet": + cfg.BTCNetParams = chaincfg.TestNet3Params + case "regtest": + cfg.BTCNetParams = chaincfg.RegressionNetParams + case "simnet": + cfg.BTCNetParams = chaincfg.SimNetParams + case "signet": + cfg.BTCNetParams = chaincfg.SigNetParams + default: + return fmt.Errorf("invalid network: %v", cfg.BitcoinNetwork) + } + + _, err := net.ResolveTCPAddr("tcp", cfg.RpcListener) + if err != nil { + return fmt.Errorf("invalid RPC listener address %s, %w", cfg.RpcListener, err) + } + + // All good, return the sanitized result. + return nil +} diff --git a/finality-provider/config/poller.go b/finality-provider/config/poller.go new file mode 100644 index 00000000..6184ccfc --- /dev/null +++ b/finality-provider/config/poller.go @@ -0,0 +1,25 @@ +package fpcfg + +import "time" + +var ( + defaultBufferSize = uint32(1000) + defaultPollingInterval = 20 * time.Second + defaultStaticStartHeight = uint64(1) +) + +type ChainPollerConfig struct { + BufferSize uint32 `long:"buffersize" description:"The maximum number of Babylon blocks that can be stored in the buffer"` + PollInterval time.Duration `long:"pollinterval" description:"The interval between each polling of Babylon blocks"` + StaticChainScanningStartHeight uint64 `long:"staticchainscanningstartheight" description:"The static height from which we start polling the chain"` + AutoChainScanningMode bool `long:"autochainscanningmode" description:"Automatically discover the height from which to start polling the chain"` +} + +func DefaultChainPollerConfig() ChainPollerConfig { + return ChainPollerConfig{ + BufferSize: defaultBufferSize, + PollInterval: defaultPollingInterval, + StaticChainScanningStartHeight: defaultStaticStartHeight, + AutoChainScanningMode: true, + } +} diff --git a/finality-provider/proto/.clang-format b/finality-provider/proto/.clang-format new file mode 100644 index 00000000..f1914278 --- /dev/null +++ b/finality-provider/proto/.clang-format @@ -0,0 +1,7 @@ +--- +Language: Proto +BasedOnStyle: Google +IndentWidth: 4 +AllowShortFunctionsOnASingleLine: None +SpaceBeforeParens: Always +CompactNamespaces: false diff --git a/finality-provider/proto/buf.gen.yaml b/finality-provider/proto/buf.gen.yaml new file mode 100644 index 00000000..7461833c --- /dev/null +++ b/finality-provider/proto/buf.gen.yaml @@ -0,0 +1,8 @@ +version: v1 +plugins: + - plugin: go + out: . + opt: paths=source_relative + - name: go-grpc + out: . + opt: paths=source_relative diff --git a/proto/buf.lock b/finality-provider/proto/buf.lock similarity index 82% rename from proto/buf.lock rename to finality-provider/proto/buf.lock index 7a2810e6..bdb2a63a 100644 --- a/proto/buf.lock +++ b/finality-provider/proto/buf.lock @@ -9,8 +9,8 @@ deps: - remote: buf.build owner: cosmos repository: cosmos-sdk - commit: 954f7b05f38440fc8250134b15adec47 - digest: shake256:2ab4404fd04a7d1d52df0e2d0f2d477a3d83ffd88d876957bf3fedfd702c8e52833d65b3ce1d89a3c5adf2aab512616b0e4f51d8463f07eda9a8a3317ee3ac54 + commit: 5a6ab7bc14314acaa912d5e53aef1c2f + digest: shake256:02c00c73493720055f9b57553a35b5550023a3c1914123b247956288a78fb913aff70e66552777ae14d759467e119079d484af081264a5dd607a94d9fbc8116b - remote: buf.build owner: cosmos repository: gogo-proto diff --git a/proto/buf.yaml b/finality-provider/proto/buf.yaml similarity index 87% rename from proto/buf.yaml rename to finality-provider/proto/buf.yaml index 4b16d8ad..baa1a86c 100644 --- a/proto/buf.yaml +++ b/finality-provider/proto/buf.yaml @@ -1,7 +1,7 @@ version: v1 -name: buf.build/babylonchain/btc-validator +name: buf.build/babylonchain/btc-finality-provider deps: - - buf.build/cosmos/cosmos-sdk:v0.47.0 + - buf.build/cosmos/cosmos-sdk:v0.50.0 - buf.build/cosmos/cosmos-proto:1935555c206d4afb9e94615dfd0fad31 - buf.build/googleapis/googleapis:8d7204855ec14631a499bd7393ce1970 - buf.build/cosmos/gogo-proto:a14993478f40695898ed8a86931094b6656e8a5d diff --git a/finality-provider/proto/finality_providers.go b/finality-provider/proto/finality_providers.go new file mode 100644 index 00000000..975535c0 --- /dev/null +++ b/finality-provider/proto/finality_providers.go @@ -0,0 +1,55 @@ +package proto + +import ( + "encoding/hex" + "fmt" + + bbn "github.com/babylonchain/babylon/types" + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/schnorr" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + "github.com/cosmos/cosmos-sdk/x/staking/types" +) + +func (sfp *StoreFinalityProvider) GetBabylonPK() *secp256k1.PubKey { + return &secp256k1.PubKey{ + Key: sfp.BabylonPk, + } +} + +func (sfp *StoreFinalityProvider) GetBabylonPkHexString() string { + return hex.EncodeToString(sfp.BabylonPk) +} + +func (sfp *StoreFinalityProvider) MustGetBTCPK() *btcec.PublicKey { + btcPubKey, err := schnorr.ParsePubKey(sfp.BtcPk) + if err != nil { + panic(fmt.Errorf("failed to parse BTC PK: %w", err)) + } + return btcPubKey +} + +func (sfp *StoreFinalityProvider) MustGetBIP340BTCPK() *bbn.BIP340PubKey { + btcPK := sfp.MustGetBTCPK() + return bbn.NewBIP340PubKeyFromBTCPK(btcPK) +} + +func NewFinalityProviderInfo(sfp *StoreFinalityProvider) (*FinalityProviderInfo, error) { + var des types.Description + if err := des.Unmarshal(sfp.Description); err != nil { + return nil, err + } + return &FinalityProviderInfo{ + BabylonPkHex: sfp.GetBabylonPkHexString(), + BtcPkHex: sfp.MustGetBIP340BTCPK().MarshalHex(), + Description: &Description{ + Moniker: des.Moniker, + Identity: des.Identity, + Website: des.Website, + SecurityContact: des.SecurityContact, + Details: des.Details, + }, + LastVotedHeight: sfp.LastVotedHeight, + Status: sfp.Status.String(), + }, nil +} diff --git a/finality-provider/proto/finality_providers.pb.go b/finality-provider/proto/finality_providers.pb.go new file mode 100644 index 00000000..01c48ce6 --- /dev/null +++ b/finality-provider/proto/finality_providers.pb.go @@ -0,0 +1,1654 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.31.0 +// protoc (unknown) +// source: finality_providers.proto + +package proto + +import ( + _ "github.com/cosmos/cosmos-proto" + _ "github.com/cosmos/cosmos-sdk/x/staking/types" + _ "github.com/cosmos/gogoproto/gogoproto" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// FinalityProviderStatus is the status of a finality provider +// a FinalityProvider object has 4 states: +// - Created - created and managed by finality provider client, not registered to +// babylon yet +// - Registered - created and registered to Babylon, but not voting yet (No +// delegated stake) +// - Active - created and registered to Babylon with stake to vote +// - Inactive - created and registered to Babylon with no stake to vote. +// Finality Provider was already active. +// +// Valid State Transactions: +// - Created -> Registered +// - Registered -> Active +// - Active -> Inactive +// - Inactive -> Active +type FinalityProviderStatus int32 + +const ( + // CREATED defines a finality provider that is awaiting registration + FinalityProviderStatus_CREATED FinalityProviderStatus = 0 + // REGISTERED defines a finality provider that has been registered + // to Babylon but has no delegated stake + FinalityProviderStatus_REGISTERED FinalityProviderStatus = 1 + // ACTIVE defines a finality provider that is delegated to vote + FinalityProviderStatus_ACTIVE FinalityProviderStatus = 2 + // INACTIVE defines a finality provider whose delegations are reduced to zero but not slashed + FinalityProviderStatus_INACTIVE FinalityProviderStatus = 3 + // SLASHED defines a finality provider that has been slashed + FinalityProviderStatus_SLASHED FinalityProviderStatus = 4 +) + +// Enum value maps for FinalityProviderStatus. +var ( + FinalityProviderStatus_name = map[int32]string{ + 0: "CREATED", + 1: "REGISTERED", + 2: "ACTIVE", + 3: "INACTIVE", + 4: "SLASHED", + } + FinalityProviderStatus_value = map[string]int32{ + "CREATED": 0, + "REGISTERED": 1, + "ACTIVE": 2, + "INACTIVE": 3, + "SLASHED": 4, + } +) + +func (x FinalityProviderStatus) Enum() *FinalityProviderStatus { + p := new(FinalityProviderStatus) + *p = x + return p +} + +func (x FinalityProviderStatus) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (FinalityProviderStatus) Descriptor() protoreflect.EnumDescriptor { + return file_finality_providers_proto_enumTypes[0].Descriptor() +} + +func (FinalityProviderStatus) Type() protoreflect.EnumType { + return &file_finality_providers_proto_enumTypes[0] +} + +func (x FinalityProviderStatus) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use FinalityProviderStatus.Descriptor instead. +func (FinalityProviderStatus) EnumDescriptor() ([]byte, []int) { + return file_finality_providers_proto_rawDescGZIP(), []int{0} +} + +type GetInfoRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *GetInfoRequest) Reset() { + *x = GetInfoRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_finality_providers_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetInfoRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetInfoRequest) ProtoMessage() {} + +func (x *GetInfoRequest) ProtoReflect() protoreflect.Message { + mi := &file_finality_providers_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetInfoRequest.ProtoReflect.Descriptor instead. +func (*GetInfoRequest) Descriptor() ([]byte, []int) { + return file_finality_providers_proto_rawDescGZIP(), []int{0} +} + +type GetInfoResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` +} + +func (x *GetInfoResponse) Reset() { + *x = GetInfoResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_finality_providers_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetInfoResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetInfoResponse) ProtoMessage() {} + +func (x *GetInfoResponse) ProtoReflect() protoreflect.Message { + mi := &file_finality_providers_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetInfoResponse.ProtoReflect.Descriptor instead. +func (*GetInfoResponse) Descriptor() ([]byte, []int) { + return file_finality_providers_proto_rawDescGZIP(), []int{1} +} + +func (x *GetInfoResponse) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +type CreateFinalityProviderRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // key_name is the identifier key in keyring + KeyName string `protobuf:"bytes,1,opt,name=key_name,json=keyName,proto3" json:"key_name,omitempty"` + // passphrase is used to encrypt the keys + Passphrase string `protobuf:"bytes,2,opt,name=passphrase,proto3" json:"passphrase,omitempty"` + // hd_path is the hd path for private key derivation + HdPath string `protobuf:"bytes,3,opt,name=hd_path,json=hdPath,proto3" json:"hd_path,omitempty"` + // chain_id is the identifier of the consumer chain that the finality provider connected to + ChainId string `protobuf:"bytes,4,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + // description defines the description terms for the finality provider + Description []byte `protobuf:"bytes,5,opt,name=description,proto3" json:"description,omitempty"` + // commission defines the commission rate for the finality provider + Commission string `protobuf:"bytes,6,opt,name=commission,proto3" json:"commission,omitempty"` +} + +func (x *CreateFinalityProviderRequest) Reset() { + *x = CreateFinalityProviderRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_finality_providers_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CreateFinalityProviderRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateFinalityProviderRequest) ProtoMessage() {} + +func (x *CreateFinalityProviderRequest) ProtoReflect() protoreflect.Message { + mi := &file_finality_providers_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateFinalityProviderRequest.ProtoReflect.Descriptor instead. +func (*CreateFinalityProviderRequest) Descriptor() ([]byte, []int) { + return file_finality_providers_proto_rawDescGZIP(), []int{2} +} + +func (x *CreateFinalityProviderRequest) GetKeyName() string { + if x != nil { + return x.KeyName + } + return "" +} + +func (x *CreateFinalityProviderRequest) GetPassphrase() string { + if x != nil { + return x.Passphrase + } + return "" +} + +func (x *CreateFinalityProviderRequest) GetHdPath() string { + if x != nil { + return x.HdPath + } + return "" +} + +func (x *CreateFinalityProviderRequest) GetChainId() string { + if x != nil { + return x.ChainId + } + return "" +} + +func (x *CreateFinalityProviderRequest) GetDescription() []byte { + if x != nil { + return x.Description + } + return nil +} + +func (x *CreateFinalityProviderRequest) GetCommission() string { + if x != nil { + return x.Commission + } + return "" +} + +type CreateFinalityProviderResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + FinalityProvider *FinalityProviderInfo `protobuf:"bytes,1,opt,name=finality_provider,json=finalityProvider,proto3" json:"finality_provider,omitempty"` +} + +func (x *CreateFinalityProviderResponse) Reset() { + *x = CreateFinalityProviderResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_finality_providers_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CreateFinalityProviderResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateFinalityProviderResponse) ProtoMessage() {} + +func (x *CreateFinalityProviderResponse) ProtoReflect() protoreflect.Message { + mi := &file_finality_providers_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateFinalityProviderResponse.ProtoReflect.Descriptor instead. +func (*CreateFinalityProviderResponse) Descriptor() ([]byte, []int) { + return file_finality_providers_proto_rawDescGZIP(), []int{3} +} + +func (x *CreateFinalityProviderResponse) GetFinalityProvider() *FinalityProviderInfo { + if x != nil { + return x.FinalityProvider + } + return nil +} + +type RegisterFinalityProviderRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // btc_pk is hex string of the BTC secp256k1 public key of the finality provider encoded in BIP-340 spec + BtcPk string `protobuf:"bytes,1,opt,name=btc_pk,json=btcPk,proto3" json:"btc_pk,omitempty"` + // passphrase is used to encrypt the keys + Passphrase string `protobuf:"bytes,2,opt,name=passphrase,proto3" json:"passphrase,omitempty"` +} + +func (x *RegisterFinalityProviderRequest) Reset() { + *x = RegisterFinalityProviderRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_finality_providers_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RegisterFinalityProviderRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RegisterFinalityProviderRequest) ProtoMessage() {} + +func (x *RegisterFinalityProviderRequest) ProtoReflect() protoreflect.Message { + mi := &file_finality_providers_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RegisterFinalityProviderRequest.ProtoReflect.Descriptor instead. +func (*RegisterFinalityProviderRequest) Descriptor() ([]byte, []int) { + return file_finality_providers_proto_rawDescGZIP(), []int{4} +} + +func (x *RegisterFinalityProviderRequest) GetBtcPk() string { + if x != nil { + return x.BtcPk + } + return "" +} + +func (x *RegisterFinalityProviderRequest) GetPassphrase() string { + if x != nil { + return x.Passphrase + } + return "" +} + +type RegisterFinalityProviderResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // hash of the successful Babylon registration transaction + TxHash string `protobuf:"bytes,1,opt,name=tx_hash,json=txHash,proto3" json:"tx_hash,omitempty"` +} + +func (x *RegisterFinalityProviderResponse) Reset() { + *x = RegisterFinalityProviderResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_finality_providers_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RegisterFinalityProviderResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RegisterFinalityProviderResponse) ProtoMessage() {} + +func (x *RegisterFinalityProviderResponse) ProtoReflect() protoreflect.Message { + mi := &file_finality_providers_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RegisterFinalityProviderResponse.ProtoReflect.Descriptor instead. +func (*RegisterFinalityProviderResponse) Descriptor() ([]byte, []int) { + return file_finality_providers_proto_rawDescGZIP(), []int{5} +} + +func (x *RegisterFinalityProviderResponse) GetTxHash() string { + if x != nil { + return x.TxHash + } + return "" +} + +type AddFinalitySignatureRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // btc_pk is hex string of the BTC secp256k1 public key of the finality provider encoded in BIP-340 spec + BtcPk string `protobuf:"bytes,1,opt,name=btc_pk,json=btcPk,proto3" json:"btc_pk,omitempty"` + // height is the height of the Babylon block + Height uint64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` + // app_hash is the AppHash of the Babylon block + AppHash []byte `protobuf:"bytes,3,opt,name=app_hash,json=appHash,proto3" json:"app_hash,omitempty"` +} + +func (x *AddFinalitySignatureRequest) Reset() { + *x = AddFinalitySignatureRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_finality_providers_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddFinalitySignatureRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddFinalitySignatureRequest) ProtoMessage() {} + +func (x *AddFinalitySignatureRequest) ProtoReflect() protoreflect.Message { + mi := &file_finality_providers_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AddFinalitySignatureRequest.ProtoReflect.Descriptor instead. +func (*AddFinalitySignatureRequest) Descriptor() ([]byte, []int) { + return file_finality_providers_proto_rawDescGZIP(), []int{6} +} + +func (x *AddFinalitySignatureRequest) GetBtcPk() string { + if x != nil { + return x.BtcPk + } + return "" +} + +func (x *AddFinalitySignatureRequest) GetHeight() uint64 { + if x != nil { + return x.Height + } + return 0 +} + +func (x *AddFinalitySignatureRequest) GetAppHash() []byte { + if x != nil { + return x.AppHash + } + return nil +} + +type AddFinalitySignatureResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // hash of the successful Babylon finality signature submission transaction + TxHash string `protobuf:"bytes,1,opt,name=tx_hash,json=txHash,proto3" json:"tx_hash,omitempty"` + // the hex string of the extracted Bitcoin secp256k1 private key + ExtractedSkHex string `protobuf:"bytes,2,opt,name=extracted_sk_hex,json=extractedSkHex,proto3" json:"extracted_sk_hex,omitempty"` + // the hex string of the local Bitcoin secp256k1 private key + LocalSkHex string `protobuf:"bytes,3,opt,name=local_sk_hex,json=localSkHex,proto3" json:"local_sk_hex,omitempty"` +} + +func (x *AddFinalitySignatureResponse) Reset() { + *x = AddFinalitySignatureResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_finality_providers_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddFinalitySignatureResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddFinalitySignatureResponse) ProtoMessage() {} + +func (x *AddFinalitySignatureResponse) ProtoReflect() protoreflect.Message { + mi := &file_finality_providers_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AddFinalitySignatureResponse.ProtoReflect.Descriptor instead. +func (*AddFinalitySignatureResponse) Descriptor() ([]byte, []int) { + return file_finality_providers_proto_rawDescGZIP(), []int{7} +} + +func (x *AddFinalitySignatureResponse) GetTxHash() string { + if x != nil { + return x.TxHash + } + return "" +} + +func (x *AddFinalitySignatureResponse) GetExtractedSkHex() string { + if x != nil { + return x.ExtractedSkHex + } + return "" +} + +func (x *AddFinalitySignatureResponse) GetLocalSkHex() string { + if x != nil { + return x.LocalSkHex + } + return "" +} + +type QueryFinalityProviderRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // btc_pk is hex string of the BTC secp256k1 public key of the finality provider encoded in BIP-340 spec + BtcPk string `protobuf:"bytes,1,opt,name=btc_pk,json=btcPk,proto3" json:"btc_pk,omitempty"` +} + +func (x *QueryFinalityProviderRequest) Reset() { + *x = QueryFinalityProviderRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_finality_providers_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryFinalityProviderRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryFinalityProviderRequest) ProtoMessage() {} + +func (x *QueryFinalityProviderRequest) ProtoReflect() protoreflect.Message { + mi := &file_finality_providers_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use QueryFinalityProviderRequest.ProtoReflect.Descriptor instead. +func (*QueryFinalityProviderRequest) Descriptor() ([]byte, []int) { + return file_finality_providers_proto_rawDescGZIP(), []int{8} +} + +func (x *QueryFinalityProviderRequest) GetBtcPk() string { + if x != nil { + return x.BtcPk + } + return "" +} + +type QueryFinalityProviderResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + FinalityProvider *FinalityProviderInfo `protobuf:"bytes,1,opt,name=finality_provider,json=finalityProvider,proto3" json:"finality_provider,omitempty"` +} + +func (x *QueryFinalityProviderResponse) Reset() { + *x = QueryFinalityProviderResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_finality_providers_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryFinalityProviderResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryFinalityProviderResponse) ProtoMessage() {} + +func (x *QueryFinalityProviderResponse) ProtoReflect() protoreflect.Message { + mi := &file_finality_providers_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use QueryFinalityProviderResponse.ProtoReflect.Descriptor instead. +func (*QueryFinalityProviderResponse) Descriptor() ([]byte, []int) { + return file_finality_providers_proto_rawDescGZIP(), []int{9} +} + +func (x *QueryFinalityProviderResponse) GetFinalityProvider() *FinalityProviderInfo { + if x != nil { + return x.FinalityProvider + } + return nil +} + +type QueryFinalityProviderListRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *QueryFinalityProviderListRequest) Reset() { + *x = QueryFinalityProviderListRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_finality_providers_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryFinalityProviderListRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryFinalityProviderListRequest) ProtoMessage() {} + +func (x *QueryFinalityProviderListRequest) ProtoReflect() protoreflect.Message { + mi := &file_finality_providers_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use QueryFinalityProviderListRequest.ProtoReflect.Descriptor instead. +func (*QueryFinalityProviderListRequest) Descriptor() ([]byte, []int) { + return file_finality_providers_proto_rawDescGZIP(), []int{10} +} + +type QueryFinalityProviderListResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + FinalityProviders []*FinalityProviderInfo `protobuf:"bytes,1,rep,name=finality_providers,json=finalityProviders,proto3" json:"finality_providers,omitempty"` // TODO add pagination in case the list gets large +} + +func (x *QueryFinalityProviderListResponse) Reset() { + *x = QueryFinalityProviderListResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_finality_providers_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryFinalityProviderListResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryFinalityProviderListResponse) ProtoMessage() {} + +func (x *QueryFinalityProviderListResponse) ProtoReflect() protoreflect.Message { + mi := &file_finality_providers_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use QueryFinalityProviderListResponse.ProtoReflect.Descriptor instead. +func (*QueryFinalityProviderListResponse) Descriptor() ([]byte, []int) { + return file_finality_providers_proto_rawDescGZIP(), []int{11} +} + +func (x *QueryFinalityProviderListResponse) GetFinalityProviders() []*FinalityProviderInfo { + if x != nil { + return x.FinalityProviders + } + return nil +} + +type StoreFinalityProvider struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // babylon_pk is the Babylon secp256k1 PK of this finality provider + BabylonPk []byte `protobuf:"bytes,1,opt,name=babylon_pk,json=babylonPk,proto3" json:"babylon_pk,omitempty"` + // btc_pk is the BTC secp256k1 PK of the finality provider encoded in BIP-340 spec + BtcPk []byte `protobuf:"bytes,2,opt,name=btc_pk,json=btcPk,proto3" json:"btc_pk,omitempty"` + // description defines the description terms for the finality provider + Description []byte `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` + // commission defines the commission rate for the finality provider + Commission string `protobuf:"bytes,4,opt,name=commission,proto3" json:"commission,omitempty"` + // pop is the proof of possession of babylon_pk and btc_pk + Pop *ProofOfPossession `protobuf:"bytes,5,opt,name=pop,proto3" json:"pop,omitempty"` + // key_name is the identifier of the keyring + KeyName string `protobuf:"bytes,6,opt,name=key_name,json=keyName,proto3" json:"key_name,omitempty"` + // chain_id is the identifier of the consumer chain that the finality provider connected to + ChainId string `protobuf:"bytes,7,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + // last_voted_height defines the height of the last voted Babylon block + LastVotedHeight uint64 `protobuf:"varint,8,opt,name=last_voted_height,json=lastVotedHeight,proto3" json:"last_voted_height,omitempty"` + // last_processed_height defines the height of the last successfully processed block + // even though the vote is not cast + LastProcessedHeight uint64 `protobuf:"varint,9,opt,name=last_processed_height,json=lastProcessedHeight,proto3" json:"last_processed_height,omitempty"` + // status defines the current finality provider status + Status FinalityProviderStatus `protobuf:"varint,10,opt,name=status,proto3,enum=proto.FinalityProviderStatus" json:"status,omitempty"` +} + +func (x *StoreFinalityProvider) Reset() { + *x = StoreFinalityProvider{} + if protoimpl.UnsafeEnabled { + mi := &file_finality_providers_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *StoreFinalityProvider) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StoreFinalityProvider) ProtoMessage() {} + +func (x *StoreFinalityProvider) ProtoReflect() protoreflect.Message { + mi := &file_finality_providers_proto_msgTypes[12] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StoreFinalityProvider.ProtoReflect.Descriptor instead. +func (*StoreFinalityProvider) Descriptor() ([]byte, []int) { + return file_finality_providers_proto_rawDescGZIP(), []int{12} +} + +func (x *StoreFinalityProvider) GetBabylonPk() []byte { + if x != nil { + return x.BabylonPk + } + return nil +} + +func (x *StoreFinalityProvider) GetBtcPk() []byte { + if x != nil { + return x.BtcPk + } + return nil +} + +func (x *StoreFinalityProvider) GetDescription() []byte { + if x != nil { + return x.Description + } + return nil +} + +func (x *StoreFinalityProvider) GetCommission() string { + if x != nil { + return x.Commission + } + return "" +} + +func (x *StoreFinalityProvider) GetPop() *ProofOfPossession { + if x != nil { + return x.Pop + } + return nil +} + +func (x *StoreFinalityProvider) GetKeyName() string { + if x != nil { + return x.KeyName + } + return "" +} + +func (x *StoreFinalityProvider) GetChainId() string { + if x != nil { + return x.ChainId + } + return "" +} + +func (x *StoreFinalityProvider) GetLastVotedHeight() uint64 { + if x != nil { + return x.LastVotedHeight + } + return 0 +} + +func (x *StoreFinalityProvider) GetLastProcessedHeight() uint64 { + if x != nil { + return x.LastProcessedHeight + } + return 0 +} + +func (x *StoreFinalityProvider) GetStatus() FinalityProviderStatus { + if x != nil { + return x.Status + } + return FinalityProviderStatus_CREATED +} + +// FinalityProviderInfo is the basic information of a finality provider mainly for external usage +type FinalityProviderInfo struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // babylon_pk_hex is the hex string of the Babylon secp256k1 PK of this finality provider + BabylonPkHex string `protobuf:"bytes,1,opt,name=babylon_pk_hex,json=babylonPkHex,proto3" json:"babylon_pk_hex,omitempty"` + // btc_pk_hex is the hex string of the BTC secp256k1 PK of the finality provider encoded in BIP-340 spec + BtcPkHex string `protobuf:"bytes,2,opt,name=btc_pk_hex,json=btcPkHex,proto3" json:"btc_pk_hex,omitempty"` + // description defines the description terms for the finality provider + Description *Description `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` + // commission defines the commission rate for the finality provider + Commission string `protobuf:"bytes,4,opt,name=commission,proto3" json:"commission,omitempty"` + // last_voted_height defines the height of the last voted Babylon block + LastVotedHeight uint64 `protobuf:"varint,5,opt,name=last_voted_height,json=lastVotedHeight,proto3" json:"last_voted_height,omitempty"` + // status defines the current finality provider status + Status string `protobuf:"bytes,6,opt,name=status,proto3" json:"status,omitempty"` +} + +func (x *FinalityProviderInfo) Reset() { + *x = FinalityProviderInfo{} + if protoimpl.UnsafeEnabled { + mi := &file_finality_providers_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FinalityProviderInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FinalityProviderInfo) ProtoMessage() {} + +func (x *FinalityProviderInfo) ProtoReflect() protoreflect.Message { + mi := &file_finality_providers_proto_msgTypes[13] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FinalityProviderInfo.ProtoReflect.Descriptor instead. +func (*FinalityProviderInfo) Descriptor() ([]byte, []int) { + return file_finality_providers_proto_rawDescGZIP(), []int{13} +} + +func (x *FinalityProviderInfo) GetBabylonPkHex() string { + if x != nil { + return x.BabylonPkHex + } + return "" +} + +func (x *FinalityProviderInfo) GetBtcPkHex() string { + if x != nil { + return x.BtcPkHex + } + return "" +} + +func (x *FinalityProviderInfo) GetDescription() *Description { + if x != nil { + return x.Description + } + return nil +} + +func (x *FinalityProviderInfo) GetCommission() string { + if x != nil { + return x.Commission + } + return "" +} + +func (x *FinalityProviderInfo) GetLastVotedHeight() uint64 { + if x != nil { + return x.LastVotedHeight + } + return 0 +} + +func (x *FinalityProviderInfo) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +// Description defines description fields for a finality provider +type Description struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Moniker string `protobuf:"bytes,1,opt,name=moniker,proto3" json:"moniker,omitempty"` + Identity string `protobuf:"bytes,2,opt,name=identity,proto3" json:"identity,omitempty"` + Website string `protobuf:"bytes,3,opt,name=website,proto3" json:"website,omitempty"` + SecurityContact string `protobuf:"bytes,4,opt,name=security_contact,json=securityContact,proto3" json:"security_contact,omitempty"` + Details string `protobuf:"bytes,5,opt,name=details,proto3" json:"details,omitempty"` +} + +func (x *Description) Reset() { + *x = Description{} + if protoimpl.UnsafeEnabled { + mi := &file_finality_providers_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Description) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Description) ProtoMessage() {} + +func (x *Description) ProtoReflect() protoreflect.Message { + mi := &file_finality_providers_proto_msgTypes[14] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Description.ProtoReflect.Descriptor instead. +func (*Description) Descriptor() ([]byte, []int) { + return file_finality_providers_proto_rawDescGZIP(), []int{14} +} + +func (x *Description) GetMoniker() string { + if x != nil { + return x.Moniker + } + return "" +} + +func (x *Description) GetIdentity() string { + if x != nil { + return x.Identity + } + return "" +} + +func (x *Description) GetWebsite() string { + if x != nil { + return x.Website + } + return "" +} + +func (x *Description) GetSecurityContact() string { + if x != nil { + return x.SecurityContact + } + return "" +} + +func (x *Description) GetDetails() string { + if x != nil { + return x.Details + } + return "" +} + +// ProofOfPossession is the proof of possession that a Babylon secp256k1 +// secret key and a Bitcoin secp256k1 secret key are held by the same +// person +type ProofOfPossession struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // babylon_sig is the signature generated via sign(sk_babylon, pk_btc) + BabylonSig []byte `protobuf:"bytes,1,opt,name=babylon_sig,json=babylonSig,proto3" json:"babylon_sig,omitempty"` + // btc_sig is the signature generated via sign(sk_btc, babylon_sig) + // the signature follows encoding in BIP-340 spec + BtcSig []byte `protobuf:"bytes,2,opt,name=btc_sig,json=btcSig,proto3" json:"btc_sig,omitempty"` +} + +func (x *ProofOfPossession) Reset() { + *x = ProofOfPossession{} + if protoimpl.UnsafeEnabled { + mi := &file_finality_providers_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ProofOfPossession) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ProofOfPossession) ProtoMessage() {} + +func (x *ProofOfPossession) ProtoReflect() protoreflect.Message { + mi := &file_finality_providers_proto_msgTypes[15] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ProofOfPossession.ProtoReflect.Descriptor instead. +func (*ProofOfPossession) Descriptor() ([]byte, []int) { + return file_finality_providers_proto_rawDescGZIP(), []int{15} +} + +func (x *ProofOfPossession) GetBabylonSig() []byte { + if x != nil { + return x.BabylonSig + } + return nil +} + +func (x *ProofOfPossession) GetBtcSig() []byte { + if x != nil { + return x.BtcSig + } + return nil +} + +type SchnorrRandPair struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PubRand []byte `protobuf:"bytes,1,opt,name=pub_rand,json=pubRand,proto3" json:"pub_rand,omitempty"` + SecRand []byte `protobuf:"bytes,2,opt,name=sec_rand,json=secRand,proto3" json:"sec_rand,omitempty"` +} + +func (x *SchnorrRandPair) Reset() { + *x = SchnorrRandPair{} + if protoimpl.UnsafeEnabled { + mi := &file_finality_providers_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SchnorrRandPair) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SchnorrRandPair) ProtoMessage() {} + +func (x *SchnorrRandPair) ProtoReflect() protoreflect.Message { + mi := &file_finality_providers_proto_msgTypes[16] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SchnorrRandPair.ProtoReflect.Descriptor instead. +func (*SchnorrRandPair) Descriptor() ([]byte, []int) { + return file_finality_providers_proto_rawDescGZIP(), []int{16} +} + +func (x *SchnorrRandPair) GetPubRand() []byte { + if x != nil { + return x.PubRand + } + return nil +} + +func (x *SchnorrRandPair) GetSecRand() []byte { + if x != nil { + return x.SecRand + } + return nil +} + +var File_finality_providers_proto protoreflect.FileDescriptor + +var file_finality_providers_proto_rawDesc = []byte{ + 0x0a, 0x18, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, + 0x64, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x1a, 0x14, 0x67, 0x6f, 0x67, 0x6f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x67, + 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x24, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, + 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, + 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x73, 0x6d, + 0x6f, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x10, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x49, + 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2b, 0x0a, 0x0f, 0x47, 0x65, + 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, + 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xf5, 0x01, 0x0a, 0x1d, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, + 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, + 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, + 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, + 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, + 0x72, 0x61, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x68, 0x64, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x68, 0x64, 0x50, 0x61, 0x74, 0x68, 0x12, 0x19, 0x0a, + 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x64, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x43, 0x0a, 0x0a, 0x63, 0x6f, + 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x42, 0x23, + 0xc8, 0xde, 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x1b, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, + 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, + 0x44, 0x65, 0x63, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x22, + 0x6a, 0x0a, 0x1e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, + 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x48, 0x0a, 0x11, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x70, 0x72, + 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, + 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x10, 0x66, 0x69, 0x6e, 0x61, 0x6c, + 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x22, 0x58, 0x0a, 0x1f, 0x52, + 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, + 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, + 0x0a, 0x06, 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x62, 0x74, 0x63, 0x50, 0x6b, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, + 0x61, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, 0x73, 0x73, 0x70, + 0x68, 0x72, 0x61, 0x73, 0x65, 0x22, 0x3b, 0x0a, 0x20, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, + 0x72, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, + 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x78, 0x5f, + 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, + 0x73, 0x68, 0x22, 0x67, 0x0a, 0x1b, 0x41, 0x64, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, + 0x79, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x62, 0x74, 0x63, 0x50, 0x6b, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, + 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, + 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x07, 0x61, 0x70, 0x70, 0x48, 0x61, 0x73, 0x68, 0x22, 0x83, 0x01, 0x0a, 0x1c, + 0x41, 0x64, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x53, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, + 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, + 0x78, 0x48, 0x61, 0x73, 0x68, 0x12, 0x28, 0x0a, 0x10, 0x65, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, + 0x65, 0x64, 0x5f, 0x73, 0x6b, 0x5f, 0x68, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0e, 0x65, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, 0x65, 0x64, 0x53, 0x6b, 0x48, 0x65, 0x78, 0x12, + 0x20, 0x0a, 0x0c, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x73, 0x6b, 0x5f, 0x68, 0x65, 0x78, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x53, 0x6b, 0x48, 0x65, + 0x78, 0x22, 0x35, 0x0a, 0x1c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, + 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x62, 0x74, 0x63, 0x50, 0x6b, 0x22, 0x69, 0x0a, 0x1d, 0x51, 0x75, 0x65, 0x72, + 0x79, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, + 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x11, 0x66, 0x69, 0x6e, + 0x61, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6e, + 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66, + 0x6f, 0x52, 0x10, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, + 0x64, 0x65, 0x72, 0x22, 0x22, 0x0a, 0x20, 0x51, 0x75, 0x65, 0x72, 0x79, 0x46, 0x69, 0x6e, 0x61, + 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x6f, 0x0a, 0x21, 0x51, 0x75, 0x65, 0x72, 0x79, + 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, + 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x12, + 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, + 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, + 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x11, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, + 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x22, 0xad, 0x03, 0x0a, 0x15, 0x53, 0x74, 0x6f, + 0x72, 0x65, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, + 0x65, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x61, 0x62, 0x79, 0x6c, 0x6f, 0x6e, 0x5f, 0x70, 0x6b, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x62, 0x61, 0x62, 0x79, 0x6c, 0x6f, 0x6e, 0x50, + 0x6b, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x05, 0x62, 0x74, 0x63, 0x50, 0x6b, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x64, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x43, 0x0a, 0x0a, 0x63, 0x6f, + 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x23, + 0xc8, 0xde, 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x1b, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, + 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, + 0x44, 0x65, 0x63, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, + 0x2a, 0x0a, 0x03, 0x70, 0x6f, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x4f, 0x66, 0x50, 0x6f, 0x73, 0x73, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x70, 0x6f, 0x70, 0x12, 0x19, 0x0a, 0x08, 0x6b, + 0x65, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, + 0x65, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, + 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, + 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x76, 0x6f, 0x74, 0x65, 0x64, 0x5f, + 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6c, 0x61, + 0x73, 0x74, 0x56, 0x6f, 0x74, 0x65, 0x64, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x32, 0x0a, + 0x15, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x5f, + 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x6c, 0x61, + 0x73, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x48, 0x65, 0x69, 0x67, 0x68, + 0x74, 0x12, 0x35, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, + 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x99, 0x02, 0x0a, 0x14, 0x46, 0x69, 0x6e, + 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66, + 0x6f, 0x12, 0x24, 0x0a, 0x0e, 0x62, 0x61, 0x62, 0x79, 0x6c, 0x6f, 0x6e, 0x5f, 0x70, 0x6b, 0x5f, + 0x68, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x62, 0x61, 0x62, 0x79, 0x6c, + 0x6f, 0x6e, 0x50, 0x6b, 0x48, 0x65, 0x78, 0x12, 0x1c, 0x0a, 0x0a, 0x62, 0x74, 0x63, 0x5f, 0x70, + 0x6b, 0x5f, 0x68, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x62, 0x74, 0x63, + 0x50, 0x6b, 0x48, 0x65, 0x78, 0x12, 0x34, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, + 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x43, 0x0a, 0x0a, 0x63, + 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, + 0x23, 0xc8, 0xde, 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x1b, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, + 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x4c, 0x65, 0x67, 0x61, 0x63, + 0x79, 0x44, 0x65, 0x63, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x12, 0x2a, 0x0a, 0x11, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x76, 0x6f, 0x74, 0x65, 0x64, 0x5f, 0x68, + 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6c, 0x61, 0x73, + 0x74, 0x56, 0x6f, 0x74, 0x65, 0x64, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x16, 0x0a, 0x06, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x22, 0xa2, 0x01, 0x0a, 0x0b, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x6f, 0x6e, 0x69, 0x6b, 0x65, 0x72, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x6f, 0x6e, 0x69, 0x6b, 0x65, 0x72, 0x12, 0x1a, + 0x0a, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x77, 0x65, + 0x62, 0x73, 0x69, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x77, 0x65, 0x62, + 0x73, 0x69, 0x74, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, + 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, + 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x12, + 0x18, 0x0a, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x22, 0x4d, 0x0a, 0x11, 0x50, 0x72, 0x6f, + 0x6f, 0x66, 0x4f, 0x66, 0x50, 0x6f, 0x73, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1f, + 0x0a, 0x0b, 0x62, 0x61, 0x62, 0x79, 0x6c, 0x6f, 0x6e, 0x5f, 0x73, 0x69, 0x67, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x62, 0x61, 0x62, 0x79, 0x6c, 0x6f, 0x6e, 0x53, 0x69, 0x67, 0x12, + 0x17, 0x0a, 0x07, 0x62, 0x74, 0x63, 0x5f, 0x73, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x06, 0x62, 0x74, 0x63, 0x53, 0x69, 0x67, 0x22, 0x47, 0x0a, 0x0f, 0x53, 0x63, 0x68, 0x6e, + 0x6f, 0x72, 0x72, 0x52, 0x61, 0x6e, 0x64, 0x50, 0x61, 0x69, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x70, + 0x75, 0x62, 0x5f, 0x72, 0x61, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, + 0x75, 0x62, 0x52, 0x61, 0x6e, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x65, 0x63, 0x5f, 0x72, 0x61, + 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x65, 0x63, 0x52, 0x61, 0x6e, + 0x64, 0x2a, 0xa6, 0x01, 0x0a, 0x16, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, + 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x18, 0x0a, 0x07, + 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, 0x00, 0x1a, 0x0b, 0x8a, 0x9d, 0x20, 0x07, 0x43, + 0x52, 0x45, 0x41, 0x54, 0x45, 0x44, 0x12, 0x1e, 0x0a, 0x0a, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, + 0x45, 0x52, 0x45, 0x44, 0x10, 0x01, 0x1a, 0x0e, 0x8a, 0x9d, 0x20, 0x0a, 0x52, 0x45, 0x47, 0x49, + 0x53, 0x54, 0x45, 0x52, 0x45, 0x44, 0x12, 0x16, 0x0a, 0x06, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, + 0x10, 0x02, 0x1a, 0x0a, 0x8a, 0x9d, 0x20, 0x06, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x12, 0x1a, + 0x0a, 0x08, 0x49, 0x4e, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x10, 0x03, 0x1a, 0x0c, 0x8a, 0x9d, + 0x20, 0x08, 0x49, 0x4e, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x12, 0x18, 0x0a, 0x07, 0x53, 0x4c, + 0x41, 0x53, 0x48, 0x45, 0x44, 0x10, 0x04, 0x1a, 0x0b, 0x8a, 0x9d, 0x20, 0x07, 0x53, 0x4c, 0x41, + 0x53, 0x48, 0x45, 0x44, 0x1a, 0x04, 0x88, 0xa3, 0x1e, 0x00, 0x32, 0xd6, 0x04, 0x0a, 0x11, 0x46, + 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, + 0x12, 0x38, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x15, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, + 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x65, 0x0a, 0x16, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, + 0x69, 0x64, 0x65, 0x72, 0x12, 0x24, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, + 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, + 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x6b, 0x0a, 0x18, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x46, 0x69, 0x6e, + 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x26, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x46, 0x69, + 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, + 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, + 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, + 0x0a, 0x14, 0x41, 0x64, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x53, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, + 0x64, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x41, 0x64, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x53, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x62, 0x0a, 0x15, 0x51, 0x75, 0x65, 0x72, 0x79, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, + 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, + 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x46, 0x69, 0x6e, 0x61, 0x6c, + 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x19, 0x51, 0x75, 0x65, 0x72, 0x79, 0x46, 0x69, 0x6e, 0x61, + 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, + 0x12, 0x27, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x46, 0x69, + 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x4c, 0x69, + 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x50, + 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x42, 0x43, 0x5a, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x62, 0x61, 0x62, 0x79, 0x6c, 0x6f, 0x6e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x2f, 0x66, + 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x2d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, + 0x2f, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x2d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, + 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_finality_providers_proto_rawDescOnce sync.Once + file_finality_providers_proto_rawDescData = file_finality_providers_proto_rawDesc +) + +func file_finality_providers_proto_rawDescGZIP() []byte { + file_finality_providers_proto_rawDescOnce.Do(func() { + file_finality_providers_proto_rawDescData = protoimpl.X.CompressGZIP(file_finality_providers_proto_rawDescData) + }) + return file_finality_providers_proto_rawDescData +} + +var file_finality_providers_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_finality_providers_proto_msgTypes = make([]protoimpl.MessageInfo, 17) +var file_finality_providers_proto_goTypes = []interface{}{ + (FinalityProviderStatus)(0), // 0: proto.FinalityProviderStatus + (*GetInfoRequest)(nil), // 1: proto.GetInfoRequest + (*GetInfoResponse)(nil), // 2: proto.GetInfoResponse + (*CreateFinalityProviderRequest)(nil), // 3: proto.CreateFinalityProviderRequest + (*CreateFinalityProviderResponse)(nil), // 4: proto.CreateFinalityProviderResponse + (*RegisterFinalityProviderRequest)(nil), // 5: proto.RegisterFinalityProviderRequest + (*RegisterFinalityProviderResponse)(nil), // 6: proto.RegisterFinalityProviderResponse + (*AddFinalitySignatureRequest)(nil), // 7: proto.AddFinalitySignatureRequest + (*AddFinalitySignatureResponse)(nil), // 8: proto.AddFinalitySignatureResponse + (*QueryFinalityProviderRequest)(nil), // 9: proto.QueryFinalityProviderRequest + (*QueryFinalityProviderResponse)(nil), // 10: proto.QueryFinalityProviderResponse + (*QueryFinalityProviderListRequest)(nil), // 11: proto.QueryFinalityProviderListRequest + (*QueryFinalityProviderListResponse)(nil), // 12: proto.QueryFinalityProviderListResponse + (*StoreFinalityProvider)(nil), // 13: proto.StoreFinalityProvider + (*FinalityProviderInfo)(nil), // 14: proto.FinalityProviderInfo + (*Description)(nil), // 15: proto.Description + (*ProofOfPossession)(nil), // 16: proto.ProofOfPossession + (*SchnorrRandPair)(nil), // 17: proto.SchnorrRandPair +} +var file_finality_providers_proto_depIdxs = []int32{ + 14, // 0: proto.CreateFinalityProviderResponse.finality_provider:type_name -> proto.FinalityProviderInfo + 14, // 1: proto.QueryFinalityProviderResponse.finality_provider:type_name -> proto.FinalityProviderInfo + 14, // 2: proto.QueryFinalityProviderListResponse.finality_providers:type_name -> proto.FinalityProviderInfo + 16, // 3: proto.StoreFinalityProvider.pop:type_name -> proto.ProofOfPossession + 0, // 4: proto.StoreFinalityProvider.status:type_name -> proto.FinalityProviderStatus + 15, // 5: proto.FinalityProviderInfo.description:type_name -> proto.Description + 1, // 6: proto.FinalityProviders.GetInfo:input_type -> proto.GetInfoRequest + 3, // 7: proto.FinalityProviders.CreateFinalityProvider:input_type -> proto.CreateFinalityProviderRequest + 5, // 8: proto.FinalityProviders.RegisterFinalityProvider:input_type -> proto.RegisterFinalityProviderRequest + 7, // 9: proto.FinalityProviders.AddFinalitySignature:input_type -> proto.AddFinalitySignatureRequest + 9, // 10: proto.FinalityProviders.QueryFinalityProvider:input_type -> proto.QueryFinalityProviderRequest + 11, // 11: proto.FinalityProviders.QueryFinalityProviderList:input_type -> proto.QueryFinalityProviderListRequest + 2, // 12: proto.FinalityProviders.GetInfo:output_type -> proto.GetInfoResponse + 4, // 13: proto.FinalityProviders.CreateFinalityProvider:output_type -> proto.CreateFinalityProviderResponse + 6, // 14: proto.FinalityProviders.RegisterFinalityProvider:output_type -> proto.RegisterFinalityProviderResponse + 8, // 15: proto.FinalityProviders.AddFinalitySignature:output_type -> proto.AddFinalitySignatureResponse + 10, // 16: proto.FinalityProviders.QueryFinalityProvider:output_type -> proto.QueryFinalityProviderResponse + 12, // 17: proto.FinalityProviders.QueryFinalityProviderList:output_type -> proto.QueryFinalityProviderListResponse + 12, // [12:18] is the sub-list for method output_type + 6, // [6:12] is the sub-list for method input_type + 6, // [6:6] is the sub-list for extension type_name + 6, // [6:6] is the sub-list for extension extendee + 0, // [0:6] is the sub-list for field type_name +} + +func init() { file_finality_providers_proto_init() } +func file_finality_providers_proto_init() { + if File_finality_providers_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_finality_providers_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetInfoRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_finality_providers_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetInfoResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_finality_providers_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CreateFinalityProviderRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_finality_providers_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CreateFinalityProviderResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_finality_providers_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RegisterFinalityProviderRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_finality_providers_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RegisterFinalityProviderResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_finality_providers_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddFinalitySignatureRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_finality_providers_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddFinalitySignatureResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_finality_providers_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*QueryFinalityProviderRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_finality_providers_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*QueryFinalityProviderResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_finality_providers_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*QueryFinalityProviderListRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_finality_providers_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*QueryFinalityProviderListResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_finality_providers_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*StoreFinalityProvider); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_finality_providers_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FinalityProviderInfo); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_finality_providers_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Description); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_finality_providers_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ProofOfPossession); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_finality_providers_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SchnorrRandPair); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_finality_providers_proto_rawDesc, + NumEnums: 1, + NumMessages: 17, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_finality_providers_proto_goTypes, + DependencyIndexes: file_finality_providers_proto_depIdxs, + EnumInfos: file_finality_providers_proto_enumTypes, + MessageInfos: file_finality_providers_proto_msgTypes, + }.Build() + File_finality_providers_proto = out.File + file_finality_providers_proto_rawDesc = nil + file_finality_providers_proto_goTypes = nil + file_finality_providers_proto_depIdxs = nil +} diff --git a/finality-provider/proto/finality_providers.proto b/finality-provider/proto/finality_providers.proto new file mode 100644 index 00000000..484e706f --- /dev/null +++ b/finality-provider/proto/finality_providers.proto @@ -0,0 +1,213 @@ +syntax = "proto3"; + +package proto; + +import "gogoproto/gogo.proto"; +import "cosmos/staking/v1beta1/staking.proto"; +import "cosmos_proto/cosmos.proto"; + +option go_package = "github.com/babylonchain/finality-provider/finality-provider/proto"; + +service FinalityProviders { + // GetInfo returns the information of the daemon + rpc GetInfo (GetInfoRequest) returns (GetInfoResponse); + + // CreateFinalityProvider generates and saves a finality provider object + rpc CreateFinalityProvider (CreateFinalityProviderRequest) + returns (CreateFinalityProviderResponse); + + // RegisterFinalityProvider sends a transactions to Babylon to register a BTC + // finality provider + rpc RegisterFinalityProvider (RegisterFinalityProviderRequest) + returns (RegisterFinalityProviderResponse); + + // AddFinalitySignature sends a transactions to Babylon to add a Finality + // signature for a block + rpc AddFinalitySignature(AddFinalitySignatureRequest) + returns (AddFinalitySignatureResponse); + + // QueryFinalityProvider queries the finality provider + rpc QueryFinalityProvider (QueryFinalityProviderRequest) returns (QueryFinalityProviderResponse); + + // QueryFinalityProviderList queries a list of finality providers + rpc QueryFinalityProviderList (QueryFinalityProviderListRequest) + returns (QueryFinalityProviderListResponse); +} + +message GetInfoRequest { +} + +message GetInfoResponse { + string version = 1; +} + +message CreateFinalityProviderRequest { + // key_name is the identifier key in keyring + string key_name = 1; + // passphrase is used to encrypt the keys + string passphrase = 2; + // hd_path is the hd path for private key derivation + string hd_path = 3; + // chain_id is the identifier of the consumer chain that the finality provider connected to + string chain_id = 4; + // description defines the description terms for the finality provider + bytes description = 5; + // commission defines the commission rate for the finality provider + string commission = 6 [ + (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", + (gogoproto.nullable) = false + ]; +} + +message CreateFinalityProviderResponse { + FinalityProviderInfo finality_provider = 1; +} + +message RegisterFinalityProviderRequest { + // btc_pk is hex string of the BTC secp256k1 public key of the finality provider encoded in BIP-340 spec + string btc_pk = 1; + // passphrase is used to encrypt the keys + string passphrase = 2; +} + +message RegisterFinalityProviderResponse { + // hash of the successful Babylon registration transaction + string tx_hash = 1; +} + +message AddFinalitySignatureRequest { + // btc_pk is hex string of the BTC secp256k1 public key of the finality provider encoded in BIP-340 spec + string btc_pk = 1; + // height is the height of the Babylon block + uint64 height = 2; + // app_hash is the AppHash of the Babylon block + bytes app_hash = 3; +} + +message AddFinalitySignatureResponse { + // hash of the successful Babylon finality signature submission transaction + string tx_hash = 1; + // the hex string of the extracted Bitcoin secp256k1 private key + string extracted_sk_hex = 2; + // the hex string of the local Bitcoin secp256k1 private key + string local_sk_hex = 3; +} + +message QueryFinalityProviderRequest { + // btc_pk is hex string of the BTC secp256k1 public key of the finality provider encoded in BIP-340 spec + string btc_pk = 1; +} + +message QueryFinalityProviderResponse { + FinalityProviderInfo finality_provider = 1; +} + +message QueryFinalityProviderListRequest { + // TODO add pagination in case the list gets large +} + +message QueryFinalityProviderListResponse { + repeated FinalityProviderInfo finality_providers = 1; + // TODO add pagination in case the list gets large +} + +message StoreFinalityProvider { + // babylon_pk is the Babylon secp256k1 PK of this finality provider + bytes babylon_pk = 1; + // btc_pk is the BTC secp256k1 PK of the finality provider encoded in BIP-340 spec + bytes btc_pk = 2; + // description defines the description terms for the finality provider + bytes description = 3; + // commission defines the commission rate for the finality provider + string commission = 4 [ + (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", + (gogoproto.nullable) = false + ]; + // pop is the proof of possession of babylon_pk and btc_pk + ProofOfPossession pop = 5; + // key_name is the identifier of the keyring + string key_name = 6; + // chain_id is the identifier of the consumer chain that the finality provider connected to + string chain_id = 7; + // last_voted_height defines the height of the last voted Babylon block + uint64 last_voted_height = 8; + // last_processed_height defines the height of the last successfully processed block + // even though the vote is not cast + uint64 last_processed_height = 9; + // status defines the current finality provider status + FinalityProviderStatus status = 10; +} + +// FinalityProviderInfo is the basic information of a finality provider mainly for external usage +message FinalityProviderInfo { + // babylon_pk_hex is the hex string of the Babylon secp256k1 PK of this finality provider + string babylon_pk_hex = 1; + // btc_pk_hex is the hex string of the BTC secp256k1 PK of the finality provider encoded in BIP-340 spec + string btc_pk_hex = 2; + // description defines the description terms for the finality provider + Description description = 3; + // commission defines the commission rate for the finality provider + string commission = 4 [ + (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", + (gogoproto.nullable) = false + ]; + // last_voted_height defines the height of the last voted Babylon block + uint64 last_voted_height = 5; + // status defines the current finality provider status + string status = 6; +} + +// Description defines description fields for a finality provider +message Description { + string moniker = 1; + string identity = 2; + string website = 3; + string security_contact = 4; + string details = 5; +} + +// ProofOfPossession is the proof of possession that a Babylon secp256k1 +// secret key and a Bitcoin secp256k1 secret key are held by the same +// person +message ProofOfPossession { + // babylon_sig is the signature generated via sign(sk_babylon, pk_btc) + bytes babylon_sig = 1; + // btc_sig is the signature generated via sign(sk_btc, babylon_sig) + // the signature follows encoding in BIP-340 spec + bytes btc_sig = 2; +} + +message SchnorrRandPair { + bytes pub_rand = 1; + bytes sec_rand = 2; +} + +// FinalityProviderStatus is the status of a finality provider +// a FinalityProvider object has 4 states: +// - Created - created and managed by finality provider client, not registered to +// babylon yet +// - Registered - created and registered to Babylon, but not voting yet (No +// delegated stake) +// - Active - created and registered to Babylon with stake to vote +// - Inactive - created and registered to Babylon with no stake to vote. +// Finality Provider was already active. +// Valid State Transactions: +// - Created -> Registered +// - Registered -> Active +// - Active -> Inactive +// - Inactive -> Active +enum FinalityProviderStatus { + option (gogoproto.goproto_enum_prefix) = false; + + // CREATED defines a finality provider that is awaiting registration + CREATED = 0 [(gogoproto.enumvalue_customname) = "CREATED"]; + // REGISTERED defines a finality provider that has been registered + // to Babylon but has no delegated stake + REGISTERED = 1 [(gogoproto.enumvalue_customname) = "REGISTERED"]; + // ACTIVE defines a finality provider that is delegated to vote + ACTIVE = 2 [(gogoproto.enumvalue_customname) = "ACTIVE"]; + // INACTIVE defines a finality provider whose delegations are reduced to zero but not slashed + INACTIVE = 3 [(gogoproto.enumvalue_customname) = "INACTIVE"]; + // SLASHED defines a finality provider that has been slashed + SLASHED = 4 [(gogoproto.enumvalue_customname) = "SLASHED"]; +} diff --git a/finality-provider/proto/finality_providers_grpc.pb.go b/finality-provider/proto/finality_providers_grpc.pb.go new file mode 100644 index 00000000..e8a27819 --- /dev/null +++ b/finality-provider/proto/finality_providers_grpc.pb.go @@ -0,0 +1,310 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.3.0 +// - protoc (unknown) +// source: finality_providers.proto + +package proto + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +const ( + FinalityProviders_GetInfo_FullMethodName = "/proto.FinalityProviders/GetInfo" + FinalityProviders_CreateFinalityProvider_FullMethodName = "/proto.FinalityProviders/CreateFinalityProvider" + FinalityProviders_RegisterFinalityProvider_FullMethodName = "/proto.FinalityProviders/RegisterFinalityProvider" + FinalityProviders_AddFinalitySignature_FullMethodName = "/proto.FinalityProviders/AddFinalitySignature" + FinalityProviders_QueryFinalityProvider_FullMethodName = "/proto.FinalityProviders/QueryFinalityProvider" + FinalityProviders_QueryFinalityProviderList_FullMethodName = "/proto.FinalityProviders/QueryFinalityProviderList" +) + +// FinalityProvidersClient is the client API for FinalityProviders service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type FinalityProvidersClient interface { + // GetInfo returns the information of the daemon + GetInfo(ctx context.Context, in *GetInfoRequest, opts ...grpc.CallOption) (*GetInfoResponse, error) + // CreateFinalityProvider generates and saves a finality provider object + CreateFinalityProvider(ctx context.Context, in *CreateFinalityProviderRequest, opts ...grpc.CallOption) (*CreateFinalityProviderResponse, error) + // RegisterFinalityProvider sends a transactions to Babylon to register a BTC + // finality provider + RegisterFinalityProvider(ctx context.Context, in *RegisterFinalityProviderRequest, opts ...grpc.CallOption) (*RegisterFinalityProviderResponse, error) + // AddFinalitySignature sends a transactions to Babylon to add a Finality + // signature for a block + AddFinalitySignature(ctx context.Context, in *AddFinalitySignatureRequest, opts ...grpc.CallOption) (*AddFinalitySignatureResponse, error) + // QueryFinalityProvider queries the finality provider + QueryFinalityProvider(ctx context.Context, in *QueryFinalityProviderRequest, opts ...grpc.CallOption) (*QueryFinalityProviderResponse, error) + // QueryFinalityProviderList queries a list of finality providers + QueryFinalityProviderList(ctx context.Context, in *QueryFinalityProviderListRequest, opts ...grpc.CallOption) (*QueryFinalityProviderListResponse, error) +} + +type finalityProvidersClient struct { + cc grpc.ClientConnInterface +} + +func NewFinalityProvidersClient(cc grpc.ClientConnInterface) FinalityProvidersClient { + return &finalityProvidersClient{cc} +} + +func (c *finalityProvidersClient) GetInfo(ctx context.Context, in *GetInfoRequest, opts ...grpc.CallOption) (*GetInfoResponse, error) { + out := new(GetInfoResponse) + err := c.cc.Invoke(ctx, FinalityProviders_GetInfo_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *finalityProvidersClient) CreateFinalityProvider(ctx context.Context, in *CreateFinalityProviderRequest, opts ...grpc.CallOption) (*CreateFinalityProviderResponse, error) { + out := new(CreateFinalityProviderResponse) + err := c.cc.Invoke(ctx, FinalityProviders_CreateFinalityProvider_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *finalityProvidersClient) RegisterFinalityProvider(ctx context.Context, in *RegisterFinalityProviderRequest, opts ...grpc.CallOption) (*RegisterFinalityProviderResponse, error) { + out := new(RegisterFinalityProviderResponse) + err := c.cc.Invoke(ctx, FinalityProviders_RegisterFinalityProvider_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *finalityProvidersClient) AddFinalitySignature(ctx context.Context, in *AddFinalitySignatureRequest, opts ...grpc.CallOption) (*AddFinalitySignatureResponse, error) { + out := new(AddFinalitySignatureResponse) + err := c.cc.Invoke(ctx, FinalityProviders_AddFinalitySignature_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *finalityProvidersClient) QueryFinalityProvider(ctx context.Context, in *QueryFinalityProviderRequest, opts ...grpc.CallOption) (*QueryFinalityProviderResponse, error) { + out := new(QueryFinalityProviderResponse) + err := c.cc.Invoke(ctx, FinalityProviders_QueryFinalityProvider_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *finalityProvidersClient) QueryFinalityProviderList(ctx context.Context, in *QueryFinalityProviderListRequest, opts ...grpc.CallOption) (*QueryFinalityProviderListResponse, error) { + out := new(QueryFinalityProviderListResponse) + err := c.cc.Invoke(ctx, FinalityProviders_QueryFinalityProviderList_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// FinalityProvidersServer is the server API for FinalityProviders service. +// All implementations must embed UnimplementedFinalityProvidersServer +// for forward compatibility +type FinalityProvidersServer interface { + // GetInfo returns the information of the daemon + GetInfo(context.Context, *GetInfoRequest) (*GetInfoResponse, error) + // CreateFinalityProvider generates and saves a finality provider object + CreateFinalityProvider(context.Context, *CreateFinalityProviderRequest) (*CreateFinalityProviderResponse, error) + // RegisterFinalityProvider sends a transactions to Babylon to register a BTC + // finality provider + RegisterFinalityProvider(context.Context, *RegisterFinalityProviderRequest) (*RegisterFinalityProviderResponse, error) + // AddFinalitySignature sends a transactions to Babylon to add a Finality + // signature for a block + AddFinalitySignature(context.Context, *AddFinalitySignatureRequest) (*AddFinalitySignatureResponse, error) + // QueryFinalityProvider queries the finality provider + QueryFinalityProvider(context.Context, *QueryFinalityProviderRequest) (*QueryFinalityProviderResponse, error) + // QueryFinalityProviderList queries a list of finality providers + QueryFinalityProviderList(context.Context, *QueryFinalityProviderListRequest) (*QueryFinalityProviderListResponse, error) + mustEmbedUnimplementedFinalityProvidersServer() +} + +// UnimplementedFinalityProvidersServer must be embedded to have forward compatible implementations. +type UnimplementedFinalityProvidersServer struct { +} + +func (UnimplementedFinalityProvidersServer) GetInfo(context.Context, *GetInfoRequest) (*GetInfoResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetInfo not implemented") +} +func (UnimplementedFinalityProvidersServer) CreateFinalityProvider(context.Context, *CreateFinalityProviderRequest) (*CreateFinalityProviderResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CreateFinalityProvider not implemented") +} +func (UnimplementedFinalityProvidersServer) RegisterFinalityProvider(context.Context, *RegisterFinalityProviderRequest) (*RegisterFinalityProviderResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RegisterFinalityProvider not implemented") +} +func (UnimplementedFinalityProvidersServer) AddFinalitySignature(context.Context, *AddFinalitySignatureRequest) (*AddFinalitySignatureResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method AddFinalitySignature not implemented") +} +func (UnimplementedFinalityProvidersServer) QueryFinalityProvider(context.Context, *QueryFinalityProviderRequest) (*QueryFinalityProviderResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method QueryFinalityProvider not implemented") +} +func (UnimplementedFinalityProvidersServer) QueryFinalityProviderList(context.Context, *QueryFinalityProviderListRequest) (*QueryFinalityProviderListResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method QueryFinalityProviderList not implemented") +} +func (UnimplementedFinalityProvidersServer) mustEmbedUnimplementedFinalityProvidersServer() {} + +// UnsafeFinalityProvidersServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to FinalityProvidersServer will +// result in compilation errors. +type UnsafeFinalityProvidersServer interface { + mustEmbedUnimplementedFinalityProvidersServer() +} + +func RegisterFinalityProvidersServer(s grpc.ServiceRegistrar, srv FinalityProvidersServer) { + s.RegisterService(&FinalityProviders_ServiceDesc, srv) +} + +func _FinalityProviders_GetInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetInfoRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(FinalityProvidersServer).GetInfo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: FinalityProviders_GetInfo_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(FinalityProvidersServer).GetInfo(ctx, req.(*GetInfoRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _FinalityProviders_CreateFinalityProvider_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateFinalityProviderRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(FinalityProvidersServer).CreateFinalityProvider(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: FinalityProviders_CreateFinalityProvider_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(FinalityProvidersServer).CreateFinalityProvider(ctx, req.(*CreateFinalityProviderRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _FinalityProviders_RegisterFinalityProvider_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RegisterFinalityProviderRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(FinalityProvidersServer).RegisterFinalityProvider(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: FinalityProviders_RegisterFinalityProvider_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(FinalityProvidersServer).RegisterFinalityProvider(ctx, req.(*RegisterFinalityProviderRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _FinalityProviders_AddFinalitySignature_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AddFinalitySignatureRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(FinalityProvidersServer).AddFinalitySignature(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: FinalityProviders_AddFinalitySignature_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(FinalityProvidersServer).AddFinalitySignature(ctx, req.(*AddFinalitySignatureRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _FinalityProviders_QueryFinalityProvider_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryFinalityProviderRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(FinalityProvidersServer).QueryFinalityProvider(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: FinalityProviders_QueryFinalityProvider_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(FinalityProvidersServer).QueryFinalityProvider(ctx, req.(*QueryFinalityProviderRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _FinalityProviders_QueryFinalityProviderList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryFinalityProviderListRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(FinalityProvidersServer).QueryFinalityProviderList(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: FinalityProviders_QueryFinalityProviderList_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(FinalityProvidersServer).QueryFinalityProviderList(ctx, req.(*QueryFinalityProviderListRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// FinalityProviders_ServiceDesc is the grpc.ServiceDesc for FinalityProviders service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var FinalityProviders_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "proto.FinalityProviders", + HandlerType: (*FinalityProvidersServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetInfo", + Handler: _FinalityProviders_GetInfo_Handler, + }, + { + MethodName: "CreateFinalityProvider", + Handler: _FinalityProviders_CreateFinalityProvider_Handler, + }, + { + MethodName: "RegisterFinalityProvider", + Handler: _FinalityProviders_RegisterFinalityProvider_Handler, + }, + { + MethodName: "AddFinalitySignature", + Handler: _FinalityProviders_AddFinalitySignature_Handler, + }, + { + MethodName: "QueryFinalityProvider", + Handler: _FinalityProviders_QueryFinalityProvider_Handler, + }, + { + MethodName: "QueryFinalityProviderList", + Handler: _FinalityProviders_QueryFinalityProviderList_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "finality_providers.proto", +} diff --git a/finality-provider/proto/scripts/protocgen.sh b/finality-provider/proto/scripts/protocgen.sh new file mode 100755 index 00000000..6132eed1 --- /dev/null +++ b/finality-provider/proto/scripts/protocgen.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +set -eo pipefail + +cd proto +buf mod update +buf generate . +cd .. + +go mod tidy -compat=1.20 diff --git a/finality-provider/service/app.go b/finality-provider/service/app.go new file mode 100644 index 00000000..807e0675 --- /dev/null +++ b/finality-provider/service/app.go @@ -0,0 +1,496 @@ +package service + +import ( + "encoding/hex" + "fmt" + "strings" + "sync" + + sdkmath "cosmossdk.io/math" + bbntypes "github.com/babylonchain/babylon/types" + bstypes "github.com/babylonchain/babylon/x/btcstaking/types" + "github.com/btcsuite/btcd/btcec/v2" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + "go.uber.org/zap" + + "github.com/babylonchain/finality-provider/clientcontroller" + "github.com/babylonchain/finality-provider/eotsmanager" + "github.com/babylonchain/finality-provider/eotsmanager/client" + fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" + "github.com/babylonchain/finality-provider/finality-provider/proto" + fpstore "github.com/babylonchain/finality-provider/finality-provider/store" + fpkr "github.com/babylonchain/finality-provider/keyring" + "github.com/babylonchain/finality-provider/types" + "github.com/babylonchain/finality-provider/util" +) + +type FinalityProviderApp struct { + startOnce sync.Once + stopOnce sync.Once + + wg sync.WaitGroup + quit chan struct{} + + sentWg sync.WaitGroup + sentQuit chan struct{} + + eventWg sync.WaitGroup + eventQuit chan struct{} + + cc clientcontroller.ClientController + kr keyring.Keyring + fps *fpstore.FinalityProviderStore + config *fpcfg.Config + logger *zap.Logger + input *strings.Reader + + fpManager *FinalityProviderManager + eotsManager eotsmanager.EOTSManager + + createFinalityProviderRequestChan chan *createFinalityProviderRequest + registerFinalityProviderRequestChan chan *registerFinalityProviderRequest + finalityProviderRegisteredEventChan chan *finalityProviderRegisteredEvent +} + +func NewFinalityProviderAppFromConfig( + homePath string, + config *fpcfg.Config, + logger *zap.Logger, +) (*FinalityProviderApp, error) { + cc, err := clientcontroller.NewClientController(config.ChainName, config.BabylonConfig, &config.BTCNetParams, logger) + if err != nil { + return nil, fmt.Errorf("failed to create rpc client for the consumer chain %s: %v", config.ChainName, err) + } + + // if the EOTSManagerAddress is empty, run a local EOTS manager; + // otherwise connect a remote one with a gRPC client + em, err := client.NewEOTSManagerGRpcClient(config.EOTSManagerAddress) + if err != nil { + return nil, fmt.Errorf("failed to create EOTS manager client: %w", err) + } + + logger.Info("successfully connected to a remote EOTS manager", zap.String("address", config.EOTSManagerAddress)) + + return NewFinalityProviderApp(homePath, config, cc, em, logger) +} + +func NewFinalityProviderApp( + homePath string, + config *fpcfg.Config, + cc clientcontroller.ClientController, + em eotsmanager.EOTSManager, + logger *zap.Logger, +) (*FinalityProviderApp, error) { + fpStore, err := initStore(homePath, config) + if err != nil { + return nil, fmt.Errorf("failed to load store: %w", err) + } + + input := strings.NewReader("") + kr, err := fpkr.CreateKeyring( + config.BabylonConfig.KeyDirectory, + config.BabylonConfig.ChainID, + config.BabylonConfig.KeyringBackend, + input, + ) + if err != nil { + return nil, fmt.Errorf("failed to create keyring: %w", err) + } + + fpm, err := NewFinalityProviderManager(fpStore, config, cc, em, logger) + if err != nil { + return nil, fmt.Errorf("failed to create finality-provider manager: %w", err) + } + + return &FinalityProviderApp{ + cc: cc, + fps: fpStore, + kr: kr, + config: config, + logger: logger, + input: input, + fpManager: fpm, + eotsManager: em, + quit: make(chan struct{}), + sentQuit: make(chan struct{}), + eventQuit: make(chan struct{}), + createFinalityProviderRequestChan: make(chan *createFinalityProviderRequest), + registerFinalityProviderRequestChan: make(chan *registerFinalityProviderRequest), + finalityProviderRegisteredEventChan: make(chan *finalityProviderRegisteredEvent), + }, nil +} + +func initStore(homePath string, cfg *fpcfg.Config) (*fpstore.FinalityProviderStore, error) { + // Create the directory that will store the data + if err := util.MakeDirectory(fpcfg.DataDir(homePath)); err != nil { + return nil, err + } + + return fpstore.NewFinalityProviderStore(fpcfg.DBPath(homePath), cfg.DatabaseConfig.Name, cfg.DatabaseConfig.Backend) +} + +func (app *FinalityProviderApp) GetConfig() *fpcfg.Config { + return app.config +} + +func (app *FinalityProviderApp) GetFinalityProviderStore() *fpstore.FinalityProviderStore { + return app.fps +} + +func (app *FinalityProviderApp) GetKeyring() keyring.Keyring { + return app.kr +} + +func (app *FinalityProviderApp) GetInput() *strings.Reader { + return app.input +} + +func (app *FinalityProviderApp) ListFinalityProviderInstances() []*FinalityProviderInstance { + return app.fpManager.ListFinalityProviderInstances() +} + +// GetFinalityProviderInstance returns the finality-provider instance with the given Babylon public key +func (app *FinalityProviderApp) GetFinalityProviderInstance(fpPk *bbntypes.BIP340PubKey) (*FinalityProviderInstance, error) { + return app.fpManager.GetFinalityProviderInstance(fpPk) +} + +func (app *FinalityProviderApp) RegisterFinalityProvider(fpPkStr string) (*RegisterFinalityProviderResponse, error) { + fpPk, err := bbntypes.NewBIP340PubKeyFromHex(fpPkStr) + if err != nil { + return nil, err + } + + fp, err := app.fps.GetStoreFinalityProvider(fpPk.MustMarshal()) + if err != nil { + return nil, err + } + + if fp.Status != proto.FinalityProviderStatus_CREATED { + return nil, fmt.Errorf("finality-provider is already registered") + } + + btcSig, err := bbntypes.NewBIP340Signature(fp.Pop.BtcSig) + if err != nil { + return nil, err + } + + pop := &bstypes.ProofOfPossession{ + BabylonSig: fp.Pop.BabylonSig, + BtcSig: btcSig.MustMarshal(), + BtcSigType: bstypes.BTCSigType_BIP340, + } + + commissionRate, err := sdkmath.LegacyNewDecFromStr(fp.Commission) + if err != nil { + return nil, err + } + + request := ®isterFinalityProviderRequest{ + bbnPubKey: fp.GetBabylonPK(), + btcPubKey: fp.MustGetBIP340BTCPK(), + pop: pop, + description: fp.Description, + commission: &commissionRate, + errResponse: make(chan error, 1), + successResponse: make(chan *RegisterFinalityProviderResponse, 1), + } + + app.registerFinalityProviderRequestChan <- request + + select { + case err := <-request.errResponse: + return nil, err + case successResponse := <-request.successResponse: + return successResponse, nil + case <-app.quit: + return nil, fmt.Errorf("finality-provider app is shutting down") + } +} + +// StartHandlingFinalityProvider starts a finality-provider instance with the given Babylon public key +// Note: this should be called right after the finality-provider is registered +func (app *FinalityProviderApp) StartHandlingFinalityProvider(fpPk *bbntypes.BIP340PubKey, passphrase string) error { + return app.fpManager.StartFinalityProvider(fpPk, passphrase) +} + +func (app *FinalityProviderApp) StartHandlingAll() error { + return app.fpManager.StartAll() +} + +// NOTE: this is not safe in production, so only used for testing purpose +func (app *FinalityProviderApp) getFpPrivKey(fpPk []byte) (*btcec.PrivateKey, error) { + record, err := app.eotsManager.KeyRecord(fpPk, "") + if err != nil { + return nil, err + } + + return record.PrivKey, nil +} + +// Start starts only the finality-provider daemon without any finality-provider instances +func (app *FinalityProviderApp) Start() error { + var startErr error + app.startOnce.Do(func() { + app.logger.Info("Starting FinalityProviderApp") + + app.eventWg.Add(1) + go app.eventLoop() + + app.sentWg.Add(1) + go app.registrationLoop() + }) + + return startErr +} + +func (app *FinalityProviderApp) Stop() error { + var stopErr error + app.stopOnce.Do(func() { + app.logger.Info("Stopping FinalityProviderApp") + + // Always stop the submission loop first to not generate additional events and actions + app.logger.Debug("Stopping submission loop") + close(app.quit) + app.wg.Wait() + + app.logger.Debug("Stopping finality providers") + if err := app.fpManager.Stop(); err != nil { + stopErr = err + return + } + + app.logger.Debug("Sent to Babylon loop stopped") + close(app.sentQuit) + app.sentWg.Wait() + + app.logger.Debug("Stopping main eventLoop") + close(app.eventQuit) + app.eventWg.Wait() + + // Closing db as last to avoid anybody to write do db + app.logger.Debug("Stopping data store") + if err := app.fps.Close(); err != nil { + stopErr = err + return + } + + app.logger.Debug("Stopping EOTS manager") + if err := app.eotsManager.Close(); err != nil { + stopErr = err + return + } + + app.logger.Debug("FinalityProviderApp successfully stopped") + + }) + return stopErr +} + +func (app *FinalityProviderApp) CreateFinalityProvider( + keyName, chainID, passPhrase, hdPath string, + description []byte, + commission *sdkmath.LegacyDec, +) (*CreateFinalityProviderResult, error) { + + req := &createFinalityProviderRequest{ + keyName: keyName, + chainID: chainID, + passPhrase: passPhrase, + hdPath: hdPath, + description: description, + commission: commission, + errResponse: make(chan error, 1), + successResponse: make(chan *createFinalityProviderResponse, 1), + } + + app.createFinalityProviderRequestChan <- req + + select { + case err := <-req.errResponse: + return nil, err + case successResponse := <-req.successResponse: + return &CreateFinalityProviderResult{ + StoreFp: successResponse.StoreFp, + }, nil + case <-app.quit: + return nil, fmt.Errorf("finality-provider app is shutting down") + } +} + +func (app *FinalityProviderApp) handleCreateFinalityProviderRequest(req *createFinalityProviderRequest) (*createFinalityProviderResponse, error) { + // 1. check if the chain key exists + kr, err := fpkr.NewChainKeyringControllerWithKeyring(app.kr, req.keyName, app.input) + if err != nil { + return nil, err + } + chainSk, err := kr.GetChainPrivKey(req.passPhrase) + if err != nil { + // the chain key does not exist, should create the chain key first + keyInfo, err := kr.CreateChainKey(req.passPhrase, req.hdPath) + if err != nil { + return nil, fmt.Errorf("failed to create chain key %s: %w", req.keyName, err) + } + chainSk = &secp256k1.PrivKey{Key: keyInfo.PrivateKey.Serialize()} + } + chainPk := &secp256k1.PubKey{Key: chainSk.PubKey().Bytes()} + + // 2. create EOTS key + fpPkBytes, err := app.eotsManager.CreateKey(req.keyName, req.passPhrase, req.hdPath) + if err != nil { + return nil, err + } + fpPk, err := bbntypes.NewBIP340PubKey(fpPkBytes) + if err != nil { + return nil, err + } + fpRecord, err := app.eotsManager.KeyRecord(fpPk.MustMarshal(), req.passPhrase) + if err != nil { + return nil, fmt.Errorf("failed to get finality-provider record: %w", err) + } + + // 3. create proof-of-possession + pop, err := kr.CreatePop(fpRecord.PrivKey, req.passPhrase) + if err != nil { + return nil, fmt.Errorf("failed to create proof-of-possession of the finality-provider: %w", err) + } + + fp := fpstore.NewStoreFinalityProvider(chainPk, fpPk, req.keyName, req.chainID, pop, req.description, req.commission) + + if err := app.fps.SaveFinalityProvider(fp); err != nil { + return nil, fmt.Errorf("failed to save finality-provider: %w", err) + } + + app.logger.Info("successfully created a finality-provider", + zap.String("btc_pk", fpPk.MarshalHex()), + zap.String("chain_pk", chainPk.String()), + zap.String("key_name", req.keyName), + ) + + return &createFinalityProviderResponse{ + StoreFp: fp, + }, nil +} + +func CreateChainKey(keyringDir, chainID, keyName, backend, passphrase, hdPath string) (*types.ChainKeyInfo, error) { + sdkCtx, err := fpkr.CreateClientCtx( + keyringDir, chainID, + ) + if err != nil { + return nil, err + } + + krController, err := fpkr.NewChainKeyringController( + sdkCtx, + keyName, + backend, + ) + if err != nil { + return nil, err + } + + return krController.CreateChainKey(passphrase, hdPath) +} + +// main event loop for the finality-provider app +func (app *FinalityProviderApp) eventLoop() { + defer app.eventWg.Done() + + for { + select { + case req := <-app.createFinalityProviderRequestChan: + res, err := app.handleCreateFinalityProviderRequest(req) + if err != nil { + req.errResponse <- err + continue + } + + req.successResponse <- &createFinalityProviderResponse{StoreFp: res.StoreFp} + + case ev := <-app.finalityProviderRegisteredEventChan: + fpStored, err := app.fps.GetStoreFinalityProvider(ev.btcPubKey.MustMarshal()) + if err != nil { + // we always check if the finality-provider is in the DB before sending the registration request + app.logger.Fatal( + "registered finality-provider not found in DB", + zap.String("pk", ev.btcPubKey.MarshalHex()), + zap.Error(err), + ) + } + + // change the status of the finality-provider to registered + err = app.fps.SetFinalityProviderStatus(fpStored, proto.FinalityProviderStatus_REGISTERED) + if err != nil { + app.logger.Fatal("failed to set finality-provider status to REGISTERED", + zap.String("pk", ev.btcPubKey.MarshalHex()), + zap.Error(err), + ) + } + + // return to the caller + ev.successResponse <- &RegisterFinalityProviderResponse{ + bbnPubKey: fpStored.GetBabylonPK(), + btcPubKey: fpStored.MustGetBIP340BTCPK(), + TxHash: ev.txHash, + } + + case <-app.eventQuit: + app.logger.Debug("exiting main event loop") + return + } + } +} + +func (app *FinalityProviderApp) registrationLoop() { + defer app.sentWg.Done() + for { + select { + case req := <-app.registerFinalityProviderRequestChan: + // we won't do any retries here to not block the loop for more important messages. + // Most probably it fails due so some user error so we just return the error to the user. + // TODO: need to start passing context here to be able to cancel the request in case of app quiting + popBytes, err := req.pop.Marshal() + if err != nil { + req.errResponse <- err + continue + } + + res, err := app.cc.RegisterFinalityProvider( + req.bbnPubKey.Key, + req.btcPubKey.MustToBTCPK(), + popBytes, + req.commission, + req.description, + ) + + if err != nil { + app.logger.Error( + "failed to register finality-provider", + zap.String("pk", req.btcPubKey.MarshalHex()), + zap.Error(err), + ) + req.errResponse <- err + continue + } + + app.logger.Info( + "successfully registered finality-provider on babylon", + zap.String("btc_pk", req.btcPubKey.MarshalHex()), + zap.String("babylon_pk", hex.EncodeToString(req.bbnPubKey.Key)), + zap.String("txHash", res.TxHash), + ) + + app.finalityProviderRegisteredEventChan <- &finalityProviderRegisteredEvent{ + btcPubKey: req.btcPubKey, + bbnPubKey: req.bbnPubKey, + txHash: res.TxHash, + // pass the channel to the event so that we can send the response to the user which requested + // the registration + successResponse: req.successResponse, + } + case <-app.sentQuit: + app.logger.Debug("exiting registration loop") + return + } + } +} diff --git a/finality-provider/service/app_test.go b/finality-provider/service/app_test.go new file mode 100644 index 00000000..74d2ca01 --- /dev/null +++ b/finality-provider/service/app_test.go @@ -0,0 +1,105 @@ +package service_test + +import ( + "math/rand" + "os" + "path/filepath" + "testing" + + bbntypes "github.com/babylonchain/babylon/types" + bstypes "github.com/babylonchain/babylon/x/btcstaking/types" + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/require" + "go.uber.org/zap" + + "github.com/babylonchain/finality-provider/eotsmanager" + "github.com/babylonchain/finality-provider/finality-provider/proto" + "github.com/babylonchain/finality-provider/finality-provider/service" + "github.com/babylonchain/finality-provider/testutil" + "github.com/babylonchain/finality-provider/types" +) + +var ( + passphrase = "testpass" + hdPath = "" +) + +func FuzzRegisterFinalityProvider(f *testing.F) { + testutil.AddRandomSeedsToFuzzer(f, 10) + f.Fuzz(func(t *testing.T, seed int64) { + r := rand.New(rand.NewSource(seed)) + + logger := zap.NewNop() + // create an EOTS manager + eotsHomeDir := filepath.Join(t.TempDir(), "eots-home") + eotsCfg := testutil.GenEOTSConfig(r, t) + em, err := eotsmanager.NewLocalEOTSManager(eotsHomeDir, eotsCfg, logger) + require.NoError(t, err) + defer func() { + err = os.RemoveAll(eotsHomeDir) + require.NoError(t, err) + }() + + // Create mocked babylon client + randomStartingHeight := uint64(r.Int63n(100) + 1) + currentHeight := randomStartingHeight + uint64(r.Int63n(10)+2) + mockClientController := testutil.PrepareMockedClientController(t, r, randomStartingHeight, currentHeight) + mockClientController.EXPECT().QueryLatestFinalizedBlocks(gomock.Any()).Return(nil, nil).AnyTimes() + mockClientController.EXPECT().QueryFinalityProviderVotingPower(gomock.Any(), + gomock.Any()).Return(uint64(0), nil).AnyTimes() + + // Create randomized config + fpHomeDir := filepath.Join(t.TempDir(), "fp-home") + fpCfg := testutil.GenFpConfig(r, t, fpHomeDir) + fpCfg.PollerConfig.AutoChainScanningMode = false + fpCfg.PollerConfig.StaticChainScanningStartHeight = randomStartingHeight + app, err := service.NewFinalityProviderApp(fpHomeDir, fpCfg, mockClientController, em, logger) + require.NoError(t, err) + defer func() { + err = os.RemoveAll(fpHomeDir) + require.NoError(t, err) + }() + + err = app.Start() + require.NoError(t, err) + defer func() { + err = app.Stop() + require.NoError(t, err) + }() + + // create a finality-provider object and save it to db + fp := testutil.GenStoredFinalityProvider(r, t, app, passphrase, hdPath) + btcSig := new(bbntypes.BIP340Signature) + err = btcSig.Unmarshal(fp.Pop.BtcSig) + require.NoError(t, err) + pop := &bstypes.ProofOfPossession{ + BabylonSig: fp.Pop.BabylonSig, + BtcSig: btcSig.MustMarshal(), + BtcSigType: bstypes.BTCSigType_BIP340, + } + popBytes, err := pop.Marshal() + require.NoError(t, err) + + txHash := testutil.GenRandomHexStr(r, 32) + mockClientController.EXPECT(). + RegisterFinalityProvider( + fp.GetBabylonPK().Key, + fp.MustGetBIP340BTCPK().MustToBTCPK(), + popBytes, + testutil.ZeroCommissionRate(), + testutil.EmptyDescription(), + ).Return(&types.TxResponse{TxHash: txHash}, nil).AnyTimes() + + res, err := app.RegisterFinalityProvider(fp.MustGetBIP340BTCPK().MarshalHex()) + require.NoError(t, err) + require.Equal(t, txHash, res.TxHash) + + mockClientController.EXPECT().QueryLastCommittedPublicRand(gomock.Any(), uint64(1)).Return(nil, nil).AnyTimes() + err = app.StartHandlingFinalityProvider(fp.MustGetBIP340BTCPK(), passphrase) + require.NoError(t, err) + + fpAfterReg, err := app.GetFinalityProviderInstance(fp.MustGetBIP340BTCPK()) + require.NoError(t, err) + require.Equal(t, fpAfterReg.GetStoreFinalityProvider().Status, proto.FinalityProviderStatus_REGISTERED) + }) +} diff --git a/finality-provider/service/chain_poller.go b/finality-provider/service/chain_poller.go new file mode 100644 index 00000000..9dcba37b --- /dev/null +++ b/finality-provider/service/chain_poller.go @@ -0,0 +1,331 @@ +package service + +import ( + "fmt" + "sync" + "time" + + "github.com/avast/retry-go/v4" + "go.uber.org/atomic" + "go.uber.org/zap" + + "github.com/babylonchain/finality-provider/clientcontroller" + cfg "github.com/babylonchain/finality-provider/finality-provider/config" + "github.com/babylonchain/finality-provider/types" +) + +var ( + // TODO: Maybe configurable? + RtyAttNum = uint(5) + RtyAtt = retry.Attempts(RtyAttNum) + RtyDel = retry.Delay(time.Millisecond * 400) + RtyErr = retry.LastErrorOnly(true) +) + +const ( + // TODO: Maybe configurable? + maxFailedCycles = 20 +) + +type skipHeightRequest struct { + height uint64 + resp chan *skipHeightResponse +} + +type skipHeightResponse struct { + err error +} + +type ChainPoller struct { + isStarted *atomic.Bool + wg sync.WaitGroup + quit chan struct{} + + cc clientcontroller.ClientController + cfg *cfg.ChainPollerConfig + blockInfoChan chan *types.BlockInfo + skipHeightChan chan *skipHeightRequest + nextHeight uint64 + logger *zap.Logger +} + +func NewChainPoller( + logger *zap.Logger, + cfg *cfg.ChainPollerConfig, + cc clientcontroller.ClientController, +) *ChainPoller { + return &ChainPoller{ + isStarted: atomic.NewBool(false), + logger: logger, + cfg: cfg, + cc: cc, + blockInfoChan: make(chan *types.BlockInfo, cfg.BufferSize), + skipHeightChan: make(chan *skipHeightRequest), + quit: make(chan struct{}), + } +} + +func (cp *ChainPoller) Start(startHeight uint64) error { + if cp.isStarted.Swap(true) { + return fmt.Errorf("the poller is already started") + } + + cp.logger.Info("starting the chain poller") + + err := cp.validateStartHeight(startHeight) + if err != nil { + return fmt.Errorf("invalid starting height %d: %w", startHeight, err) + } + + cp.nextHeight = startHeight + + cp.wg.Add(1) + + go cp.pollChain() + + cp.logger.Info("the chain poller is successfully started") + + return nil +} + +func (cp *ChainPoller) Stop() error { + if !cp.isStarted.Swap(false) { + return fmt.Errorf("the chain poller has already stopped") + } + + cp.logger.Info("stopping the chain poller") + err := cp.cc.Close() + if err != nil { + return err + } + close(cp.quit) + cp.wg.Wait() + + cp.logger.Info("the chain poller is successfully stopped") + + return nil +} + +func (cp *ChainPoller) IsRunning() bool { + return cp.isStarted.Load() +} + +// Return read only channel for incoming blocks +// TODO: Handle the case when there is more than one consumer. Currently with more than +// one consumer blocks most probably will be received out of order to those consumers. +func (cp *ChainPoller) GetBlockInfoChan() <-chan *types.BlockInfo { + return cp.blockInfoChan +} + +func (cp *ChainPoller) latestBlockWithRetry() (*types.BlockInfo, error) { + var ( + latestBlock *types.BlockInfo + err error + ) + + if err := retry.Do(func() error { + latestBlock, err = cp.cc.QueryBestBlock() + if err != nil { + return err + } + return nil + }, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { + cp.logger.Debug( + "failed to query the consumer chain for the latest block", + zap.Uint("attempt", n+1), + zap.Uint("max_attempts", RtyAttNum), + zap.Error(err), + ) + })); err != nil { + return nil, err + } + return latestBlock, nil +} + +func (cp *ChainPoller) blockWithRetry(height uint64) (*types.BlockInfo, error) { + var ( + block *types.BlockInfo + err error + ) + if err := retry.Do(func() error { + block, err = cp.cc.QueryBlock(height) + if err != nil { + return err + } + return nil + }, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { + cp.logger.Debug( + "failed to query the consumer chain for the latest block", + zap.Uint("attempt", n+1), + zap.Uint("max_attempts", RtyAttNum), + zap.Uint64("height", height), + zap.Error(err), + ) + })); err != nil { + return nil, err + } + + return block, nil +} + +func (cp *ChainPoller) validateStartHeight(startHeight uint64) error { + // Infinite retry to get initial latest height + // TODO: Add possible cancellation or timeout for starting node + + if startHeight == 0 { + return fmt.Errorf("start height can't be 0") + } + + var currentBestChainHeight uint64 + for { + lastestBlock, err := cp.latestBlockWithRetry() + if err != nil { + cp.logger.Debug("failed to query babylon for the latest status", zap.Error(err)) + continue + } + + currentBestChainHeight = lastestBlock.Height + break + } + + // Allow the start height to be the next chain height + if startHeight > currentBestChainHeight+1 { + return fmt.Errorf("start height %d is more than the next chain tip height %d", startHeight, currentBestChainHeight+1) + } + + return nil +} + +// waitForActivation waits until BTC staking is activated +func (cp *ChainPoller) waitForActivation() { + // ensure that the startHeight is no lower than the activated height + for { + activatedHeight, err := cp.cc.QueryActivatedHeight() + if err != nil { + cp.logger.Debug("failed to query the consumer chain for the activated height", zap.Error(err)) + } else { + if cp.nextHeight < activatedHeight { + cp.nextHeight = activatedHeight + } + return + } + + select { + case <-time.After(cp.cfg.PollInterval): + + case <-cp.quit: + return + } + } + +} + +func (cp *ChainPoller) pollChain() { + defer cp.wg.Done() + + cp.waitForActivation() + + var failedCycles uint32 + + for { + // TODO: Handlig of request cancellation, as otherwise shutdown will be blocked + // until request is finished + blockToRetrieve := cp.nextHeight + block, err := cp.blockWithRetry(blockToRetrieve) + if err != nil { + failedCycles++ + cp.logger.Debug( + "failed to query the consumer chain for the block", + zap.Uint32("current_failures", failedCycles), + zap.Uint64("block_to_retrieve", blockToRetrieve), + zap.Error(err), + ) + } else { + // no error and we got the header we wanted to get, bump the state and push + // notification about data + cp.nextHeight = blockToRetrieve + 1 + failedCycles = 0 + + cp.logger.Info("the poller retrieved the block from the consumer chain", + zap.Uint64("height", block.Height)) + + // push the data to the channel + // Note: if the consumer is too slow -- the buffer is full + // the channel will block, and we will stop retrieving data from the node + cp.blockInfoChan <- block + } + + if failedCycles > maxFailedCycles { + cp.logger.Fatal("the poller has reached the max failed cycles, exiting") + } + + select { + case <-time.After(cp.cfg.PollInterval): + + case req := <-cp.skipHeightChan: + // no need to skip heights if the target height is not higher + // than the next height to retrieve + targetHeight := req.height + if targetHeight <= cp.nextHeight { + resp := &skipHeightResponse{ + err: fmt.Errorf( + "the target height %d is not higher than the next height %d to retrieve", + targetHeight, cp.nextHeight)} + req.resp <- resp + continue + } + + // drain blocks that can be skipped from blockInfoChan + cp.clearChanBufferUpToHeight(targetHeight) + + // set the next height to the skip height + cp.nextHeight = targetHeight + + cp.logger.Debug("the poller has skipped height(s)", + zap.Uint64("next_height", req.height)) + + req.resp <- &skipHeightResponse{} + + case <-cp.quit: + return + } + } +} + +func (cp *ChainPoller) SkipToHeight(height uint64) error { + if !cp.IsRunning() { + return fmt.Errorf("the chain poller is stopped") + } + + respChan := make(chan *skipHeightResponse, 1) + + // this handles the case when the poller is stopped before the + // skip height request is sent + select { + case <-cp.quit: + return fmt.Errorf("the chain poller is stopped") + case cp.skipHeightChan <- &skipHeightRequest{height: height, resp: respChan}: + } + + // this handles the case when the poller is stopped before + // the skip height request is returned + select { + case <-cp.quit: + return fmt.Errorf("the chain poller is stopped") + case resp := <-respChan: + return resp.err + } +} + +func (cp *ChainPoller) NextHeight() uint64 { + return cp.nextHeight +} + +func (cp *ChainPoller) clearChanBufferUpToHeight(upToHeight uint64) { + for len(cp.blockInfoChan) > 0 { + block := <-cp.blockInfoChan + if block.Height+1 >= upToHeight { + break + } + } +} diff --git a/finality-provider/service/chain_poller_test.go b/finality-provider/service/chain_poller_test.go new file mode 100644 index 00000000..8c5fdc90 --- /dev/null +++ b/finality-provider/service/chain_poller_test.go @@ -0,0 +1,148 @@ +package service_test + +import ( + "math/rand" + "sync" + "testing" + "time" + + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/require" + "go.uber.org/zap" + + fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" + "github.com/babylonchain/finality-provider/finality-provider/service" + "github.com/babylonchain/finality-provider/testutil" + "github.com/babylonchain/finality-provider/testutil/mocks" + "github.com/babylonchain/finality-provider/types" +) + +// FuzzChainPoller_Start tests the poller polling blocks +// in sequence +func FuzzChainPoller_Start(f *testing.F) { + testutil.AddRandomSeedsToFuzzer(f, 10) + f.Fuzz(func(t *testing.T, seed int64) { + r := rand.New(rand.NewSource(seed)) + + currentHeight := uint64(r.Int63n(100) + 1) + startHeight := currentHeight + 1 + endHeight := startHeight + uint64(r.Int63n(10)+1) + + ctl := gomock.NewController(t) + mockClientController := mocks.NewMockClientController(ctl) + mockClientController.EXPECT().Close().Return(nil).AnyTimes() + mockClientController.EXPECT().QueryActivatedHeight().Return(uint64(1), nil).AnyTimes() + + currentBlockRes := &types.BlockInfo{ + Height: currentHeight, + } + mockClientController.EXPECT().QueryBestBlock().Return(currentBlockRes, nil).AnyTimes() + + for i := startHeight; i <= endHeight; i++ { + resBlock := &types.BlockInfo{ + Height: i, + } + mockClientController.EXPECT().QueryBlock(i).Return(resBlock, nil).AnyTimes() + } + + pollerCfg := fpcfg.DefaultChainPollerConfig() + pollerCfg.PollInterval = 10 * time.Millisecond + poller := service.NewChainPoller(zap.NewNop(), &pollerCfg, mockClientController) + err := poller.Start(startHeight) + require.NoError(t, err) + defer func() { + err := poller.Stop() + require.NoError(t, err) + }() + + for i := startHeight; i <= endHeight; i++ { + select { + case info := <-poller.GetBlockInfoChan(): + require.Equal(t, i, info.Height) + case <-time.After(10 * time.Second): + t.Fatalf("Failed to get block info") + } + } + }) +} + +// FuzzChainPoller_SkipHeight tests the functionality of SkipHeight +func FuzzChainPoller_SkipHeight(f *testing.F) { + testutil.AddRandomSeedsToFuzzer(f, 10) + f.Fuzz(func(t *testing.T, seed int64) { + r := rand.New(rand.NewSource(seed)) + + currentHeight := uint64(r.Int63n(100) + 1) + startHeight := currentHeight + 1 + endHeight := startHeight + uint64(r.Int63n(10)+2) + skipHeight := endHeight + uint64(r.Int63n(10)+1) + + ctl := gomock.NewController(t) + mockClientController := mocks.NewMockClientController(ctl) + mockClientController.EXPECT().Close().Return(nil).AnyTimes() + mockClientController.EXPECT().QueryActivatedHeight().Return(uint64(1), nil).AnyTimes() + + currentBlockRes := &types.BlockInfo{ + Height: currentHeight, + } + mockClientController.EXPECT().QueryBestBlock().Return(currentBlockRes, nil).AnyTimes() + + for i := startHeight; i <= skipHeight; i++ { + resBlock := &types.BlockInfo{ + Height: i, + } + mockClientController.EXPECT().QueryBlock(i).Return(resBlock, nil).AnyTimes() + } + + pollerCfg := fpcfg.DefaultChainPollerConfig() + pollerCfg.PollInterval = 1 * time.Second + poller := service.NewChainPoller(zap.NewNop(), &pollerCfg, mockClientController) + // should expect error if the poller is not started + err := poller.SkipToHeight(skipHeight) + require.Error(t, err) + err = poller.Start(startHeight) + require.NoError(t, err) + defer func() { + err := poller.Stop() + require.NoError(t, err) + // should expect error if the poller is stopped + err = poller.SkipToHeight(skipHeight) + require.Error(t, err) + }() + + var wg sync.WaitGroup + wg.Add(1) + go func() { + wg.Done() + // insert a skipToHeight request with height lower than the next + // height to retrieve, expecting an error + err = poller.SkipToHeight(poller.NextHeight() - 1) + require.Error(t, err) + // insert a skipToHeight request with a height higher than the + // next height to retrieve + err = poller.SkipToHeight(skipHeight) + require.NoError(t, err) + }() + + skipped := false + for i := startHeight; i <= endHeight; i++ { + if skipped { + break + } + select { + case info := <-poller.GetBlockInfoChan(): + if info.Height == skipHeight { + skipped = true + } else { + require.Equal(t, i, info.Height) + } + case <-time.After(10 * time.Second): + t.Fatalf("Failed to get block info") + } + } + + wg.Wait() + + require.Equal(t, skipHeight+1, poller.NextHeight()) + }) +} diff --git a/finality-provider/service/client/rpcclient.go b/finality-provider/service/client/rpcclient.go new file mode 100644 index 00000000..13e2677e --- /dev/null +++ b/finality-provider/service/client/rpcclient.go @@ -0,0 +1,122 @@ +package client + +import ( + "context" + "fmt" + + sdkmath "cosmossdk.io/math" + bbntypes "github.com/babylonchain/babylon/types" + "github.com/cosmos/cosmos-sdk/x/staking/types" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + + "github.com/babylonchain/finality-provider/finality-provider/proto" +) + +type FinalityProviderServiceGRpcClient struct { + client proto.FinalityProvidersClient +} + +func NewFinalityProviderServiceGRpcClient(remoteAddr string) (*FinalityProviderServiceGRpcClient, func(), error) { + conn, err := grpc.Dial(remoteAddr, grpc.WithTransportCredentials(insecure.NewCredentials())) + if err != nil { + return nil, nil, fmt.Errorf("failed to build gRPC connection to %s: %w", remoteAddr, err) + } + + cleanUp := func() { + conn.Close() + } + + return &FinalityProviderServiceGRpcClient{ + client: proto.NewFinalityProvidersClient(conn), + }, cleanUp, nil +} + +func (c *FinalityProviderServiceGRpcClient) GetInfo(ctx context.Context) (*proto.GetInfoResponse, error) { + req := &proto.GetInfoRequest{} + res, err := c.client.GetInfo(ctx, req) + if err != nil { + return nil, err + } + + return res, nil +} + +func (c *FinalityProviderServiceGRpcClient) RegisterFinalityProvider( + ctx context.Context, + fpPk *bbntypes.BIP340PubKey, + passphrase string, +) (*proto.RegisterFinalityProviderResponse, error) { + + req := &proto.RegisterFinalityProviderRequest{BtcPk: fpPk.MarshalHex(), Passphrase: passphrase} + res, err := c.client.RegisterFinalityProvider(ctx, req) + if err != nil { + return nil, err + } + + return res, nil +} + +func (c *FinalityProviderServiceGRpcClient) CreateFinalityProvider( + ctx context.Context, + keyName, chainID, passphrase, hdPath string, + description types.Description, + commission *sdkmath.LegacyDec, +) (*proto.CreateFinalityProviderResponse, error) { + + descBytes, err := description.Marshal() + if err != nil { + return nil, err + } + + req := &proto.CreateFinalityProviderRequest{ + KeyName: keyName, + ChainId: chainID, + Passphrase: passphrase, + HdPath: hdPath, + Description: descBytes, + Commission: commission.String(), + } + + res, err := c.client.CreateFinalityProvider(ctx, req) + if err != nil { + return nil, err + } + + return res, nil +} + +func (c *FinalityProviderServiceGRpcClient) AddFinalitySignature(ctx context.Context, fpPk string, height uint64, appHash []byte) (*proto.AddFinalitySignatureResponse, error) { + req := &proto.AddFinalitySignatureRequest{ + BtcPk: fpPk, + Height: height, + AppHash: appHash, + } + + res, err := c.client.AddFinalitySignature(ctx, req) + if err != nil { + return nil, err + } + + return res, nil +} + +func (c *FinalityProviderServiceGRpcClient) QueryFinalityProviderList(ctx context.Context) (*proto.QueryFinalityProviderListResponse, error) { + req := &proto.QueryFinalityProviderListRequest{} + res, err := c.client.QueryFinalityProviderList(ctx, req) + if err != nil { + return nil, err + } + + return res, nil +} + +func (c *FinalityProviderServiceGRpcClient) QueryFinalityProviderInfo(ctx context.Context, fpPk *bbntypes.BIP340PubKey) (*proto.QueryFinalityProviderResponse, error) { + req := &proto.QueryFinalityProviderRequest{BtcPk: fpPk.MarshalHex()} + res, err := c.client.QueryFinalityProvider(ctx, req) + if err != nil { + return nil, err + } + + return res, nil +} diff --git a/service/fastsync.go b/finality-provider/service/fastsync.go similarity index 51% rename from service/fastsync.go rename to finality-provider/service/fastsync.go index d17b958b..b0d16b9a 100644 --- a/service/fastsync.go +++ b/finality-provider/service/fastsync.go @@ -3,14 +3,13 @@ package service import ( "fmt" - "github.com/cosmos/relayer/v2/relayer/provider" - "github.com/sirupsen/logrus" + "go.uber.org/zap" - "github.com/babylonchain/btc-validator/types" + "github.com/babylonchain/finality-provider/types" ) type FastSyncResult struct { - Responses []*provider.RelayerTxResponse + Responses []*types.TxResponse SyncedHeight uint64 LastProcessedHeight uint64 } @@ -18,11 +17,11 @@ type FastSyncResult struct { // FastSync attempts to send a batch of finality signatures // from the maximum of the last voted height and the last finalized height // to the current height -func (v *ValidatorInstance) FastSync(startHeight, endHeight uint64) (*FastSyncResult, error) { - if v.inSync.Swap(true) { - return nil, fmt.Errorf("the validator has already been in fast sync") +func (fp *FinalityProviderInstance) FastSync(startHeight, endHeight uint64) (*FastSyncResult, error) { + if fp.inSync.Swap(true) { + return nil, fmt.Errorf("the finality-provider has already been in fast sync") } - defer v.inSync.Store(false) + defer fp.inSync.Store(false) if startHeight > endHeight { return nil, fmt.Errorf("the start height %v should not be higher than the end height %v", @@ -30,11 +29,11 @@ func (v *ValidatorInstance) FastSync(startHeight, endHeight uint64) (*FastSyncRe } var syncedHeight uint64 - responses := make([]*provider.RelayerTxResponse, 0) + responses := make([]*types.TxResponse, 0) // we may need several rounds to catch-up as we need to limit // the catch-up distance for each round to avoid memory overflow for startHeight <= endHeight { - blocks, err := v.cc.QueryBlocks(startHeight, endHeight, v.cfg.FastSyncLimit) + blocks, err := fp.cc.QueryBlocks(startHeight, endHeight, fp.cfg.FastSyncLimit) if err != nil { return nil, err } @@ -50,19 +49,27 @@ func (v *ValidatorInstance) FastSync(startHeight, endHeight uint64) (*FastSyncRe // have gaps during sync catchUpBlocks := make([]*types.BlockInfo, 0, len(blocks)) for _, b := range blocks { - should, err := v.shouldSubmitFinalitySignature(b) + // check whether the block has been processed before + if fp.hasProcessed(b) { + continue + } + // check whether the finality provider has voting power + hasVp, err := fp.hasVotingPower(b) if err != nil { - // stop catch-up when critical errors occur return nil, err } - if !should { - // two cases could lead to here: - // 1. insufficient committed randomness - // 2. no voting power - // thus we should continue here in case the two conditions - // will not happen in the rest of the blocks + if !hasVp { continue } + // check whether the randomness has been committed + hasRand, err := fp.hasRandomness(b) + if err != nil { + return nil, err + } + if !hasRand { + break + } + // all good, add the block for catching up catchUpBlocks = append(catchUpBlocks, b) } @@ -72,25 +79,27 @@ func (v *ValidatorInstance) FastSync(startHeight, endHeight uint64) (*FastSyncRe syncedHeight = catchUpBlocks[len(catchUpBlocks)-1].Height - res, err := v.SubmitBatchFinalitySignatures(catchUpBlocks) + res, err := fp.SubmitBatchFinalitySignatures(catchUpBlocks) if err != nil { return nil, err } responses = append(responses, res) - v.logger.WithFields(logrus.Fields{ - "btc_pk_hex": v.GetBtcPkHex(), - "start_height": catchUpBlocks[0].Height, - "synced_height": syncedHeight, - }).Debug("the validator is catching up by sending finality signatures in a batch") + fp.logger.Debug( + "the finality-provider is catching up by sending finality signatures in a batch", + zap.String("pk", fp.GetBtcPkHex()), + zap.Uint64("start_height", catchUpBlocks[0].Height), + zap.Uint64("synced_height", syncedHeight), + ) } - v.MustSetLastProcessedHeight(endHeight) + // update the processed height + fp.MustSetLastProcessedHeight(syncedHeight) return &FastSyncResult{ Responses: responses, SyncedHeight: syncedHeight, - LastProcessedHeight: endHeight, + LastProcessedHeight: fp.GetLastProcessedHeight(), }, nil } diff --git a/finality-provider/service/fastsync_test.go b/finality-provider/service/fastsync_test.go new file mode 100644 index 00000000..bd4940ee --- /dev/null +++ b/finality-provider/service/fastsync_test.go @@ -0,0 +1,98 @@ +package service_test + +import ( + "math/rand" + "testing" + + "github.com/btcsuite/btcd/btcec/v2" + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/require" + + "github.com/babylonchain/finality-provider/testutil" + "github.com/babylonchain/finality-provider/types" +) + +// FuzzFastSync_SufficientRandomness tests a case where we have sufficient +// randomness and voting power when the finality provider enters fast-sync +// it is expected that the finality provider could catch up to the current +// height through fast-sync +func FuzzFastSync_SufficientRandomness(f *testing.F) { + testutil.AddRandomSeedsToFuzzer(f, 10) + f.Fuzz(func(t *testing.T, seed int64) { + r := rand.New(rand.NewSource(seed)) + + randomStartingHeight := uint64(r.Int63n(100) + 1) + finalizedHeight := randomStartingHeight + uint64(r.Int63n(10)+2) + currentHeight := finalizedHeight + uint64(r.Int63n(10)+1) + mockClientController := testutil.PrepareMockedClientController(t, r, randomStartingHeight, currentHeight) + mockClientController.EXPECT().QueryLatestFinalizedBlocks(uint64(1)).Return(nil, nil).AnyTimes() + _, fpIns, cleanUp := startFinalityProviderAppWithRegisteredFp(t, r, mockClientController, randomStartingHeight) + defer cleanUp() + + mockClientController.EXPECT().QueryFinalityProviderVotingPower(fpIns.MustGetBtcPk(), gomock.Any()). + Return(uint64(1), nil).AnyTimes() + // the last committed height is higher than the current height + // to make sure the randomness is sufficient + lastCommittedHeight := randomStartingHeight + testutil.TestPubRandNum + lastCommittedPubRandMap := make(map[uint64]*btcec.FieldVal) + lastCommittedPubRandMap[lastCommittedHeight] = testutil.GenPublicRand(r, t).ToFieldVal() + mockClientController.EXPECT().QueryLastCommittedPublicRand(gomock.Any(), uint64(1)).Return(lastCommittedPubRandMap, nil).AnyTimes() + + catchUpBlocks := testutil.GenBlocks(r, finalizedHeight+1, currentHeight) + expectedTxHash := testutil.GenRandomHexStr(r, 32) + finalizedBlock := &types.BlockInfo{Height: finalizedHeight, Hash: testutil.GenRandomByteArray(r, 32)} + mockClientController.EXPECT().QueryLatestFinalizedBlocks(uint64(1)).Return([]*types.BlockInfo{finalizedBlock}, nil).AnyTimes() + mockClientController.EXPECT().QueryBlocks(finalizedHeight+1, currentHeight, uint64(10)). + Return(catchUpBlocks, nil) + mockClientController.EXPECT().SubmitBatchFinalitySigs(fpIns.MustGetBtcPk(), catchUpBlocks, gomock.Any()). + Return(&types.TxResponse{TxHash: expectedTxHash}, nil).AnyTimes() + result, err := fpIns.FastSync(finalizedHeight+1, currentHeight) + require.NoError(t, err) + require.NotNil(t, result) + require.Equal(t, expectedTxHash, result.Responses[0].TxHash) + require.Equal(t, currentHeight, fpIns.GetLastVotedHeight()) + require.Equal(t, currentHeight, fpIns.GetLastProcessedHeight()) + }) +} + +// FuzzFastSync_SufficientRandomness tests a case where we have insufficient +// randomness but with voting power when the finality provider enters fast-sync +// it is expected that the finality provider could catch up to the last +// committed height +func FuzzFastSync_NoRandomness(f *testing.F) { + testutil.AddRandomSeedsToFuzzer(f, 10) + f.Fuzz(func(t *testing.T, seed int64) { + r := rand.New(rand.NewSource(seed)) + + randomStartingHeight := uint64(r.Int63n(100) + 1) + finalizedHeight := randomStartingHeight + uint64(r.Int63n(10)+2) + currentHeight := finalizedHeight + uint64(r.Int63n(10)+1) + mockClientController := testutil.PrepareMockedClientController(t, r, randomStartingHeight, currentHeight) + mockClientController.EXPECT().QueryLatestFinalizedBlocks(uint64(1)).Return(nil, nil).AnyTimes() + _, fpIns, cleanUp := startFinalityProviderAppWithRegisteredFp(t, r, mockClientController, randomStartingHeight) + defer cleanUp() + + mockClientController.EXPECT().QueryFinalityProviderVotingPower(fpIns.MustGetBtcPk(), gomock.Any()). + Return(uint64(1), nil).AnyTimes() + // the last committed height is set in [finalizedHeight+1, currentHeight] + lastCommittedHeight := uint64(rand.Intn(int(currentHeight)-int(finalizedHeight))) + finalizedHeight + 1 + lastCommittedPubRandMap := make(map[uint64]*btcec.FieldVal) + lastCommittedPubRandMap[lastCommittedHeight] = testutil.GenPublicRand(r, t).ToFieldVal() + mockClientController.EXPECT().QueryLastCommittedPublicRand(gomock.Any(), uint64(1)).Return(lastCommittedPubRandMap, nil).AnyTimes() + + catchUpBlocks := testutil.GenBlocks(r, finalizedHeight+1, currentHeight) + expectedTxHash := testutil.GenRandomHexStr(r, 32) + finalizedBlock := &types.BlockInfo{Height: finalizedHeight, Hash: testutil.GenRandomByteArray(r, 32)} + mockClientController.EXPECT().QueryLatestFinalizedBlocks(uint64(1)).Return([]*types.BlockInfo{finalizedBlock}, nil).AnyTimes() + mockClientController.EXPECT().QueryBlocks(finalizedHeight+1, currentHeight, uint64(10)). + Return(catchUpBlocks, nil) + mockClientController.EXPECT().SubmitBatchFinalitySigs(fpIns.MustGetBtcPk(), catchUpBlocks[:lastCommittedHeight-finalizedHeight], gomock.Any()). + Return(&types.TxResponse{TxHash: expectedTxHash}, nil).AnyTimes() + result, err := fpIns.FastSync(finalizedHeight+1, currentHeight) + require.NoError(t, err) + require.NotNil(t, result) + require.Equal(t, expectedTxHash, result.Responses[0].TxHash) + require.Equal(t, lastCommittedHeight, fpIns.GetLastVotedHeight()) + require.Equal(t, lastCommittedHeight, fpIns.GetLastProcessedHeight()) + }) +} diff --git a/finality-provider/service/fp_instance.go b/finality-provider/service/fp_instance.go new file mode 100644 index 00000000..4864c08a --- /dev/null +++ b/finality-provider/service/fp_instance.go @@ -0,0 +1,1006 @@ +package service + +import ( + "errors" + "fmt" + "strings" + "sync" + "time" + + "github.com/avast/retry-go/v4" + bbntypes "github.com/babylonchain/babylon/types" + bstypes "github.com/babylonchain/babylon/x/btcstaking/types" + ftypes "github.com/babylonchain/babylon/x/finality/types" + "github.com/btcsuite/btcd/btcec/v2" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + "github.com/gogo/protobuf/jsonpb" + "go.uber.org/atomic" + "go.uber.org/zap" + + "github.com/babylonchain/finality-provider/clientcontroller" + "github.com/babylonchain/finality-provider/eotsmanager" + fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" + "github.com/babylonchain/finality-provider/finality-provider/proto" + fpstore "github.com/babylonchain/finality-provider/finality-provider/store" + "github.com/babylonchain/finality-provider/types" +) + +type FinalityProviderInstance struct { + bbnPk *secp256k1.PubKey + btcPk *bbntypes.BIP340PubKey + + state *fpState + cfg *fpcfg.Config + + logger *zap.Logger + em eotsmanager.EOTSManager + cc clientcontroller.ClientController + poller *ChainPoller + + // passphrase is used to unlock private keys + passphrase string + + laggingTargetChan chan *types.BlockInfo + criticalErrChan chan<- *CriticalError + + isStarted *atomic.Bool + inSync *atomic.Bool + isLagging *atomic.Bool + + wg sync.WaitGroup + quit chan struct{} +} + +// NewFinalityProviderInstance returns a FinalityProviderInstance instance with the given Babylon public key +// the finality-provider should be registered before +func NewFinalityProviderInstance( + fpPk *bbntypes.BIP340PubKey, + cfg *fpcfg.Config, + s *fpstore.FinalityProviderStore, + cc clientcontroller.ClientController, + em eotsmanager.EOTSManager, + passphrase string, + errChan chan<- *CriticalError, + logger *zap.Logger, +) (*FinalityProviderInstance, error) { + sfp, err := s.GetStoreFinalityProvider(fpPk.MustMarshal()) + if err != nil { + return nil, fmt.Errorf("failed to retrive the finality-provider %s from DB: %w", sfp.GetBabylonPkHexString(), err) + } + + // ensure the finality-provider has been registered + if sfp.Status < proto.FinalityProviderStatus_REGISTERED { + return nil, fmt.Errorf("the finality-provider %s has not been registered", sfp.KeyName) + } + + return &FinalityProviderInstance{ + btcPk: sfp.MustGetBIP340BTCPK(), + bbnPk: sfp.GetBabylonPK(), + state: &fpState{ + fp: sfp, + s: s, + }, + cfg: cfg, + logger: logger, + isStarted: atomic.NewBool(false), + inSync: atomic.NewBool(false), + isLagging: atomic.NewBool(false), + criticalErrChan: errChan, + passphrase: passphrase, + em: em, + cc: cc, + }, nil +} + +func (fp *FinalityProviderInstance) Start() error { + if fp.isStarted.Swap(true) { + return fmt.Errorf("the finality-provider instance %s is already started", fp.GetBtcPkHex()) + } + + fp.logger.Info("Starting finality-provider instance", zap.String("pk", fp.GetBtcPkHex())) + + startHeight, err := fp.bootstrap() + if err != nil { + return fmt.Errorf("failed to bootstrap the finality-provider %s: %w", fp.GetBtcPkHex(), err) + } + + fp.logger.Info("the finality-provider %s has been bootstrapped", + zap.String("pk", fp.GetBtcPkHex()), zap.Uint64("height", startHeight)) + + poller := NewChainPoller(fp.logger, fp.cfg.PollerConfig, fp.cc) + + if err := poller.Start(startHeight + 1); err != nil { + return fmt.Errorf("failed to start the poller: %w", err) + } + + fp.poller = poller + + fp.laggingTargetChan = make(chan *types.BlockInfo, 1) + + fp.quit = make(chan struct{}) + + fp.wg.Add(1) + go fp.finalitySigSubmissionLoop() + fp.wg.Add(1) + go fp.randomnessCommitmentLoop() + fp.wg.Add(1) + go fp.checkLaggingLoop() + + return nil +} + +func (fp *FinalityProviderInstance) bootstrap() (uint64, error) { + latestBlock, err := fp.getLatestBlockWithRetry() + if err != nil { + return 0, err + } + + if fp.checkLagging(latestBlock) { + _, err := fp.tryFastSync(latestBlock) + if err != nil && !clientcontroller.IsExpected(err) { + return 0, err + } + } + + startHeight, err := fp.getPollerStartingHeight() + if err != nil { + return 0, err + } + + return startHeight, nil +} + +func (fp *FinalityProviderInstance) Stop() error { + if !fp.isStarted.Swap(false) { + return fmt.Errorf("the finality-provider %s has already stopped", fp.GetBtcPkHex()) + } + + if err := fp.poller.Stop(); err != nil { + return fmt.Errorf("failed to stop the poller: %w", err) + } + + fp.logger.Info("stopping finality-provider instance", zap.String("pk", fp.GetBtcPkHex())) + + close(fp.quit) + fp.wg.Wait() + + fp.logger.Info("the finality-provider instance %s is successfully stopped", zap.String("pk", fp.GetBtcPkHex())) + + return nil +} + +func (fp *FinalityProviderInstance) IsRunning() bool { + return fp.isStarted.Load() +} + +func (fp *FinalityProviderInstance) finalitySigSubmissionLoop() { + defer fp.wg.Done() + + for { + select { + case b := <-fp.poller.GetBlockInfoChan(): + fp.logger.Debug( + "the finality-provider received a new block, start processing", + zap.String("pk", fp.GetBtcPkHex()), + zap.Uint64("height", b.Height), + ) + + // check whether the block has been processed before + if fp.hasProcessed(b) { + continue + } + // check whether the finality provider has voting power + hasVp, err := fp.hasVotingPower(b) + if err != nil { + fp.reportCriticalErr(err) + continue + } + if !hasVp { + // the finality provider does not have voting power + // and it will never will at this block + fp.MustSetLastProcessedHeight(b.Height) + continue + } + // check whether the randomness has been committed + // we should stall here until we have randomness committed at this + // height, otherwise, we might miss blocks + if err := fp.retryCheckRandomnessUntilBlockFinalized(b); err != nil { + fp.reportCriticalErr(err) + break + } + + // use the copy of the block to avoid the impact to other receivers + nextBlock := *b + res, err := fp.retrySubmitFinalitySignatureUntilBlockFinalized(&nextBlock) + if err != nil { + fp.reportCriticalErr(err) + continue + } + if res == nil { + // this can happen when a finality signature is not needed + // either if the block is already submitted or the signature + // is already submitted + continue + } + fp.logger.Info( + "successfully submitted a finality signature to the consumer chain", + zap.String("pk", fp.GetBtcPkHex()), + zap.Uint64("height", b.Height), + zap.String("tx_hash", res.TxHash), + ) + + case targetBlock := <-fp.laggingTargetChan: + res, err := fp.tryFastSync(targetBlock) + fp.isLagging.Store(false) + if err != nil { + if errors.Is(err, bstypes.ErrFpAlreadySlashed) { + fp.reportCriticalErr(err) + continue + } + fp.logger.Debug( + "failed to sync up, will try again later", + zap.String("pk", fp.GetBtcPkHex()), + zap.Error(err), + ) + continue + } + // response might be nil if sync is not needed + if res != nil { + fp.logger.Info( + "fast sync is finished", + zap.String("pk", fp.GetBtcPkHex()), + zap.Uint64("synced_height", res.SyncedHeight), + zap.Uint64("last_processed_height", res.LastProcessedHeight), + ) + + // inform the poller to skip to the next block of the last + // processed one + err := fp.poller.SkipToHeight(fp.GetLastProcessedHeight() + 1) + if err != nil { + fp.logger.Debug( + "failed to skip heights from the poller", + zap.Error(err), + ) + } + } + case <-fp.quit: + fp.logger.Info("the finality signature submission loop is closing") + return + } + } +} + +func (fp *FinalityProviderInstance) randomnessCommitmentLoop() { + defer fp.wg.Done() + + commitRandTicker := time.NewTicker(fp.cfg.RandomnessCommitInterval) + defer commitRandTicker.Stop() + + for { + select { + case <-commitRandTicker.C: + tipBlock, err := fp.getLatestBlockWithRetry() + if err != nil { + fp.reportCriticalErr(err) + continue + } + txRes, err := fp.retryCommitPubRandUntilBlockFinalized(tipBlock) + if err != nil { + fp.reportCriticalErr(err) + continue + } + // txRes could be nil if no need to commit more randomness + if txRes != nil { + fp.logger.Info( + "successfully committed public randomness to the consumer chain", + zap.String("pk", fp.GetBtcPkHex()), + zap.String("tx_hash", txRes.TxHash), + ) + } + + case <-fp.quit: + fp.logger.Info("the randomness commitment loop is closing") + return + } + } +} + +func (fp *FinalityProviderInstance) checkLaggingLoop() { + defer fp.wg.Done() + + if fp.cfg.FastSyncInterval == 0 { + fp.logger.Info("the fast sync is disabled") + return + } + + fastSyncTicker := time.NewTicker(fp.cfg.FastSyncInterval) + defer fastSyncTicker.Stop() + + for { + select { + case <-fastSyncTicker.C: + if fp.isLagging.Load() { + // we are in fast sync mode, skip do not do checks + continue + } + + latestBlock, err := fp.getLatestBlockWithRetry() + if err != nil { + fp.logger.Debug( + "failed to get the latest block of the consumer chain", + zap.String("pk", fp.GetBtcPkHex()), + zap.Error(err), + ) + continue + } + + if fp.checkLagging(latestBlock) { + fp.isLagging.Store(true) + fp.laggingTargetChan <- latestBlock + } + case <-fp.quit: + fp.logger.Debug("the fast sync loop is closing") + return + } + } +} + +func (fp *FinalityProviderInstance) tryFastSync(targetBlock *types.BlockInfo) (*FastSyncResult, error) { + if fp.inSync.Load() { + return nil, fmt.Errorf("the finality-provider %s is already in sync", fp.GetBtcPkHex()) + } + + // get the last finalized height + lastFinalizedBlocks, err := fp.cc.QueryLatestFinalizedBlocks(1) + if err != nil { + return nil, err + } + if lastFinalizedBlocks == nil { + fp.logger.Debug( + "no finalized blocks yet, no need to catch up", + zap.String("pk", fp.GetBtcPkHex()), + zap.Uint64("height", targetBlock.Height), + ) + return nil, nil + } + + lastFinalizedHeight := lastFinalizedBlocks[0].Height + lastProcessedHeight := fp.GetLastProcessedHeight() + + // get the startHeight from the maximum of the lastVotedHeight and + // the lastFinalizedHeight plus 1 + var startHeight uint64 + if lastFinalizedHeight < lastProcessedHeight { + startHeight = lastProcessedHeight + 1 + } else { + startHeight = lastFinalizedHeight + 1 + } + + if startHeight > targetBlock.Height { + return nil, fmt.Errorf("the start height %v should not be higher than the current block %v", startHeight, targetBlock.Height) + } + + fp.logger.Debug("the finality-provider is entering fast sync") + + return fp.FastSync(startHeight, targetBlock.Height) +} + +func (fp *FinalityProviderInstance) hasProcessed(b *types.BlockInfo) bool { + if b.Height <= fp.GetLastProcessedHeight() { + fp.logger.Debug( + "the block has been processed before, skip processing", + zap.String("pk", fp.GetBtcPkHex()), + zap.Uint64("block_height", b.Height), + zap.Uint64("last_processed_height", fp.GetLastProcessedHeight()), + ) + return true + } + + return false +} + +func (fp *FinalityProviderInstance) hasVotingPower(b *types.BlockInfo) (bool, error) { + power, err := fp.GetVotingPowerWithRetry(b.Height) + if err != nil { + return false, err + } + if power == 0 { + fp.logger.Debug( + "the finality-provider does not have voting power", + zap.String("pk", fp.GetBtcPkHex()), + zap.Uint64("block_height", b.Height), + ) + + return false, nil + } + + return true, nil +} + +func (fp *FinalityProviderInstance) hasRandomness(b *types.BlockInfo) (bool, error) { + lastCommittedHeight, err := fp.GetLastCommittedHeight() + if err != nil { + return false, err + } + if b.Height > lastCommittedHeight { + fp.logger.Debug( + "the finality provider has not committed public randomness for the height", + zap.String("pk", fp.GetBtcPkHex()), + zap.Uint64("block_height", b.Height), + zap.Uint64("last_committed_height", lastCommittedHeight), + ) + return false, nil + } + + return true, nil +} + +func (fp *FinalityProviderInstance) reportCriticalErr(err error) { + fp.criticalErrChan <- &CriticalError{ + err: err, + fpBtcPk: fp.GetBtcPkBIP340(), + } +} + +// checkLagging returns true if the lasted voted height is behind by a configured gap +func (fp *FinalityProviderInstance) checkLagging(currentBlock *types.BlockInfo) bool { + return currentBlock.Height >= fp.GetLastProcessedHeight()+fp.cfg.FastSyncGap +} + +// retryQueryingRandomnessUntilBlockFinalized periodically checks whether +// the randomness has been committed to the target block until the block is +// finalized +// error will be returned if maximum retries have been reached or the query to +// the consumer chain fails +func (fp *FinalityProviderInstance) retryCheckRandomnessUntilBlockFinalized(targetBlock *types.BlockInfo) error { + var failedCycles uint32 + + // we break the for loop if the block is finalized or the randomness is successfully committed + // error will be returned if maximum retries have been reached or the query to the consumer chain fails + for { + fp.logger.Debug( + "checking randomness", + zap.String("pk", fp.GetBtcPkHex()), + zap.Uint64("target_block_height", targetBlock.Height), + ) + hasRand, err := fp.hasRandomness(targetBlock) + if err != nil { + fp.logger.Debug( + "failed to check last committed randomness", + zap.String("pk", fp.GetBtcPkHex()), + zap.Uint32("current_failures", failedCycles), + zap.Uint64("target_block_height", targetBlock.Height), + zap.Error(err), + ) + + failedCycles += 1 + if failedCycles > uint32(fp.cfg.MaxSubmissionRetries) { + return fmt.Errorf("reached max failed cycles with err: %w", err) + } + } else if hasRand { + // the randomness has been successfully committed + return nil + } + select { + case <-time.After(fp.cfg.SubmissionRetryInterval): + // periodically query the index block to be later checked whether it is Finalized + finalized, err := fp.checkBlockFinalization(targetBlock.Height) + if err != nil { + return fmt.Errorf("failed to query block finalization at height %v: %w", targetBlock.Height, err) + } + if finalized { + fp.logger.Debug( + "the block is already finalized, skip checking randomness", + zap.String("pk", fp.GetBtcPkHex()), + zap.Uint64("target_height", targetBlock.Height), + ) + // TODO: returning nil here is to safely break the loop + // the error still exists + return nil + } + + case <-fp.quit: + fp.logger.Debug("the finality-provider instance is closing", zap.String("pk", fp.GetBtcPkHex())) + return nil + } + } +} + +// retrySubmitFinalitySignatureUntilBlockFinalized periodically tries to submit finality signature until success or the block is finalized +// error will be returned if maximum retries have been reached or the query to the consumer chain fails +func (fp *FinalityProviderInstance) retrySubmitFinalitySignatureUntilBlockFinalized(targetBlock *types.BlockInfo) (*types.TxResponse, error) { + var failedCycles uint32 + + // we break the for loop if the block is finalized or the signature is successfully submitted + // error will be returned if maximum retries have been reached or the query to the consumer chain fails + for { + // error will be returned if max retries have been reached + res, err := fp.SubmitFinalitySignature(targetBlock) + if err != nil { + + fp.logger.Debug( + "failed to submit finality signature to the consumer chain", + zap.String("pk", fp.GetBtcPkHex()), + zap.Uint32("current_failures", failedCycles), + zap.Uint64("target_block_height", targetBlock.Height), + zap.Error(err), + ) + + if clientcontroller.IsUnrecoverable(err) { + return nil, err + } + + if clientcontroller.IsExpected(err) { + return nil, nil + } + + failedCycles += 1 + if failedCycles > uint32(fp.cfg.MaxSubmissionRetries) { + return nil, fmt.Errorf("reached max failed cycles with err: %w", err) + } + } else { + // the signature has been successfully submitted + return res, nil + } + select { + case <-time.After(fp.cfg.SubmissionRetryInterval): + // periodically query the index block to be later checked whether it is Finalized + finalized, err := fp.checkBlockFinalization(targetBlock.Height) + if err != nil { + return nil, fmt.Errorf("failed to query block finalization at height %v: %w", targetBlock.Height, err) + } + if finalized { + fp.logger.Debug( + "the block is already finalized, skip submission", + zap.String("pk", fp.GetBtcPkHex()), + zap.Uint64("target_height", targetBlock.Height), + ) + // TODO: returning nil here is to safely break the loop + // the error still exists + return nil, nil + } + + case <-fp.quit: + fp.logger.Debug("the finality-provider instance is closing", zap.String("pk", fp.GetBtcPkHex())) + return nil, nil + } + } +} + +func (fp *FinalityProviderInstance) checkBlockFinalization(height uint64) (bool, error) { + b, err := fp.cc.QueryBlock(height) + if err != nil { + return false, err + } + + return b.Finalized, nil +} + +// retryCommitPubRandUntilBlockFinalized periodically tries to commit public rand until success or the block is finalized +// error will be returned if maximum retries have been reached or the query to the consumer chain fails +func (fp *FinalityProviderInstance) retryCommitPubRandUntilBlockFinalized(targetBlock *types.BlockInfo) (*types.TxResponse, error) { + var failedCycles uint32 + + // we break the for loop if the block is finalized or the public rand is successfully committed + // error will be returned if maximum retries have been reached or the query to the consumer chain fails + for { + // error will be returned if max retries have been reached + res, err := fp.CommitPubRand(targetBlock) + if err != nil { + if clientcontroller.IsUnrecoverable(err) { + return nil, err + } + fp.logger.Debug( + "failed to commit public randomness to the consumer chain", + zap.String("pk", fp.GetBtcPkHex()), + zap.Uint32("current_failures", failedCycles), + zap.Uint64("target_block_height", targetBlock.Height), + zap.Error(err), + ) + + failedCycles += 1 + if failedCycles > uint32(fp.cfg.MaxSubmissionRetries) { + return nil, fmt.Errorf("reached max failed cycles with err: %w", err) + } + } else { + // the public randomness has been successfully submitted + return res, nil + } + select { + case <-time.After(fp.cfg.SubmissionRetryInterval): + // periodically query the index block to be later checked whether it is Finalized + finalized, err := fp.checkBlockFinalization(targetBlock.Height) + if err != nil { + return nil, fmt.Errorf("failed to query block finalization at height %v: %w", targetBlock.Height, err) + } + if finalized { + fp.logger.Debug( + "the block is already finalized, skip submission", + zap.String("pk", fp.GetBtcPkHex()), + zap.Uint64("target_height", targetBlock.Height), + ) + // TODO: returning nil here is to safely break the loop + // the error still exists + return nil, nil + } + + case <-fp.quit: + fp.logger.Debug("the finality-provider instance is closing", zap.String("pk", fp.GetBtcPkHex())) + return nil, nil + } + } +} + +// CommitPubRand generates a list of Schnorr rand pairs, +// commits the public randomness for the managed finality providers, +// and save the randomness pair to DB +func (fp *FinalityProviderInstance) CommitPubRand(tipBlock *types.BlockInfo) (*types.TxResponse, error) { + lastCommittedHeight, err := fp.GetLastCommittedHeight() + if err != nil { + return nil, err + } + + var startHeight uint64 + if lastCommittedHeight == uint64(0) { + // the finality-provider has never submitted public rand before + startHeight = tipBlock.Height + 1 + // should not use subtraction because they are in the type of uint64 + } else if lastCommittedHeight < fp.cfg.MinRandHeightGap+tipBlock.Height { + // we are running out of the randomness + startHeight = lastCommittedHeight + 1 + } else { + fp.logger.Debug( + "the finality-provider has sufficient public randomness, skip committing more", + zap.String("pk", fp.GetBtcPkHex()), + zap.Uint64("block_height", tipBlock.Height), + zap.Uint64("last_committed_height", lastCommittedHeight), + ) + return nil, nil + } + + // generate a list of Schnorr randomness pairs + // NOTE: currently, calling this will create and save a list of randomness + // in case of failure, randomness that has been created will be overwritten + // for safety reason as the same randomness must not be used twice + // TODO: should consider an implementation that deterministically create + // randomness without saving it + pubRandList, err := fp.createPubRandList(startHeight) + if err != nil { + return nil, fmt.Errorf("failed to generate randomness: %w", err) + } + + // get the message hash for signing + msg := &ftypes.MsgCommitPubRandList{ + FpBtcPk: fp.btcPk, + StartHeight: startHeight, + PubRandList: pubRandList, + } + hash, err := msg.HashToSign() + if err != nil { + return nil, fmt.Errorf("failed to sign the commit public randomness message: %w", err) + } + + // sign the message hash using the finality-provider's BTC private key + schnorrSig, err := fp.em.SignSchnorrSig(fp.btcPk.MustMarshal(), hash, fp.passphrase) + if err != nil { + return nil, fmt.Errorf("failed to sign the Schnorr signature: %w", err) + } + + pubRandByteList := make([]*btcec.FieldVal, 0, len(pubRandList)) + for _, r := range pubRandList { + pubRandByteList = append(pubRandByteList, r.ToFieldVal()) + } + res, err := fp.cc.CommitPubRandList(fp.MustGetBtcPk(), startHeight, pubRandByteList, schnorrSig) + if err != nil { + // TODO Add retry. check issue: https://github.com/babylonchain/finality-provider/issues/34 + return nil, fmt.Errorf("failed to commit public randomness to the consumer chain: %w", err) + } + + return res, nil +} + +func (fp *FinalityProviderInstance) createPubRandList(startHeight uint64) ([]bbntypes.SchnorrPubRand, error) { + pubRandList, err := fp.em.CreateRandomnessPairList( + fp.btcPk.MustMarshal(), + fp.GetChainID(), + startHeight, + uint32(fp.cfg.NumPubRand), + fp.passphrase, + ) + if err != nil { + return nil, err + } + + schnorrPubRandList := make([]bbntypes.SchnorrPubRand, 0, len(pubRandList)) + for _, pr := range pubRandList { + schnorrPubRandList = append(schnorrPubRandList, *bbntypes.NewSchnorrPubRandFromFieldVal(pr)) + } + + return schnorrPubRandList, nil +} + +// SubmitFinalitySignature builds and sends a finality signature over the given block to the consumer chain +func (fp *FinalityProviderInstance) SubmitFinalitySignature(b *types.BlockInfo) (*types.TxResponse, error) { + eotsSig, err := fp.signEotsSig(b) + if err != nil { + return nil, err + } + + // send finality signature to the consumer chain + res, err := fp.cc.SubmitFinalitySig(fp.MustGetBtcPk(), b.Height, b.Hash, eotsSig.ToModNScalar()) + if err != nil { + return nil, fmt.Errorf("failed to send finality signature to the consumer chain: %w", err) + } + + // update DB + fp.MustUpdateStateAfterFinalitySigSubmission(b.Height) + + return res, nil +} + +// SubmitBatchFinalitySignatures builds and sends a finality signature over the given block to the consumer chain +// NOTE: the input blocks should be in the ascending order of height +func (fp *FinalityProviderInstance) SubmitBatchFinalitySignatures(blocks []*types.BlockInfo) (*types.TxResponse, error) { + if len(blocks) == 0 { + return nil, fmt.Errorf("should not submit batch finality signature with zero block") + } + + sigs := make([]*btcec.ModNScalar, 0, len(blocks)) + for _, b := range blocks { + eotsSig, err := fp.signEotsSig(b) + if err != nil { + return nil, err + } + sigs = append(sigs, eotsSig.ToModNScalar()) + } + + // send finality signature to the consumer chain + res, err := fp.cc.SubmitBatchFinalitySigs(fp.MustGetBtcPk(), blocks, sigs) + if err != nil { + return nil, fmt.Errorf("failed to send a batch of finality signatures to the consumer chain: %w", err) + } + + // update DB + highBlock := blocks[len(blocks)-1] + fp.MustUpdateStateAfterFinalitySigSubmission(highBlock.Height) + + return res, nil +} + +func (fp *FinalityProviderInstance) signEotsSig(b *types.BlockInfo) (*bbntypes.SchnorrEOTSSig, error) { + // build proper finality signature request + msg := &ftypes.MsgAddFinalitySig{ + FpBtcPk: fp.btcPk, + BlockHeight: b.Height, + BlockAppHash: b.Hash, + } + msgToSign := msg.MsgToSign() + sig, err := fp.em.SignEOTS(fp.btcPk.MustMarshal(), fp.GetChainID(), msgToSign, b.Height, fp.passphrase) + if err != nil { + return nil, fmt.Errorf("failed to sign EOTS: %w", err) + } + + return bbntypes.NewSchnorrEOTSSigFromModNScalar(sig), nil +} + +// TestSubmitFinalitySignatureAndExtractPrivKey is exposed for presentation/testing purpose to allow manual sending finality signature +// this API is the same as SubmitFinalitySignature except that we don't constraint the voting height and update status +// Note: this should not be used in the submission loop +func (fp *FinalityProviderInstance) TestSubmitFinalitySignatureAndExtractPrivKey(b *types.BlockInfo) (*types.TxResponse, *btcec.PrivateKey, error) { + // check last committed height + lastCommittedHeight, err := fp.GetLastCommittedHeight() + if err != nil { + return nil, nil, err + } + if lastCommittedHeight < b.Height { + return nil, nil, fmt.Errorf("the finality-provider's last committed height %v is lower than the current block height %v", + lastCommittedHeight, b.Height) + } + + eotsSig, err := fp.signEotsSig(b) + if err != nil { + return nil, nil, err + } + + // send finality signature to the consumer chain + res, err := fp.cc.SubmitFinalitySig(fp.MustGetBtcPk(), b.Height, b.Hash, eotsSig.ToModNScalar()) + if err != nil { + return nil, nil, fmt.Errorf("failed to send finality signature to the consumer chain: %w", err) + } + + // try to extract the private key + var privKey *btcec.PrivateKey + for _, ev := range res.Events { + if strings.Contains(ev.EventType, "EventSlashedFinalityProvider") { + evidenceStr := ev.Attributes["evidence"] + fp.logger.Debug("found slashing evidence") + var evidence ftypes.Evidence + if err := jsonpb.UnmarshalString(evidenceStr, &evidence); err != nil { + return nil, nil, fmt.Errorf("failed to decode evidence bytes to evidence: %s", err.Error()) + } + privKey, err = evidence.ExtractBTCSK() + if err != nil { + return nil, nil, fmt.Errorf("failed to extract private key: %s", err.Error()) + } + break + } + } + + return res, privKey, nil +} + +func (fp *FinalityProviderInstance) getPollerStartingHeight() (uint64, error) { + if !fp.cfg.PollerConfig.AutoChainScanningMode { + return fp.cfg.PollerConfig.StaticChainScanningStartHeight, nil + } + + // Set initial block to the maximum of + // - last processed height + // - the latest Babylon finalised height + // The above is to ensure that: + // + // (1) Any finality-provider that is eligible to vote for a block, + // doesn't miss submitting a vote for it. + // (2) The finality providers do not submit signatures for any already + // finalised blocks. + initialBlockToGet := fp.GetLastProcessedHeight() + latestFinalisedBlock, err := fp.latestFinalizedBlocksWithRetry(1) + if err != nil { + return 0, err + } + if len(latestFinalisedBlock) != 0 { + if latestFinalisedBlock[0].Height > initialBlockToGet { + initialBlockToGet = latestFinalisedBlock[0].Height + } + } + + // ensure that initialBlockToGet is at least 1 + if initialBlockToGet == 0 { + initialBlockToGet = 1 + } + return initialBlockToGet, nil +} + +func (fp *FinalityProviderInstance) GetLastCommittedHeight() (uint64, error) { + pubRandMap, err := fp.lastCommittedPublicRandWithRetry(1) + if err != nil { + return 0, err + } + + // no committed randomness yet + if len(pubRandMap) == 0 { + return 0, nil + } + + if len(pubRandMap) > 1 { + return 0, fmt.Errorf("got more than one last committed public randomness") + } + heights := make([]uint64, 0, 1) + for k := range pubRandMap { + heights = append(heights, k) + } + + return heights[0], nil +} + +func (fp *FinalityProviderInstance) lastCommittedPublicRandWithRetry(count uint64) (map[uint64]*btcec.FieldVal, error) { + var response map[uint64]*btcec.FieldVal + if err := retry.Do(func() error { + pubRandMap, err := fp.cc.QueryLastCommittedPublicRand(fp.MustGetBtcPk(), count) + if err != nil { + return err + } + response = pubRandMap + return nil + }, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { + fp.logger.Debug( + "failed to query babylon for the last committed public randomness", + zap.Uint("attempt", n+1), + zap.Uint("max_attempts", RtyAttNum), + zap.Error(err), + ) + })); err != nil { + return nil, err + } + return response, nil +} + +func (fp *FinalityProviderInstance) latestFinalizedBlocksWithRetry(count uint64) ([]*types.BlockInfo, error) { + var response []*types.BlockInfo + if err := retry.Do(func() error { + latestFinalisedBlock, err := fp.cc.QueryLatestFinalizedBlocks(count) + if err != nil { + return err + } + response = latestFinalisedBlock + return nil + }, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { + fp.logger.Debug( + "failed to query babylon for the latest finalised blocks", + zap.Uint("attempt", n+1), + zap.Uint("max_attempts", RtyAttNum), + zap.Error(err), + ) + })); err != nil { + return nil, err + } + return response, nil +} + +func (fp *FinalityProviderInstance) getLatestBlockWithRetry() (*types.BlockInfo, error) { + var ( + latestBlock *types.BlockInfo + err error + ) + + if err := retry.Do(func() error { + latestBlock, err = fp.cc.QueryBestBlock() + if err != nil { + return err + } + return nil + }, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { + fp.logger.Debug( + "failed to query the consumer chain for the latest block", + zap.Uint("attempt", n+1), + zap.Uint("max_attempts", RtyAttNum), + zap.Error(err), + ) + })); err != nil { + return nil, err + } + + return latestBlock, nil +} + +func (fp *FinalityProviderInstance) GetVotingPowerWithRetry(height uint64) (uint64, error) { + var ( + power uint64 + err error + ) + + if err := retry.Do(func() error { + power, err = fp.cc.QueryFinalityProviderVotingPower(fp.MustGetBtcPk(), height) + if err != nil { + return err + } + return nil + }, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { + fp.logger.Debug( + "failed to query the voting power", + zap.Uint("attempt", n+1), + zap.Uint("max_attempts", RtyAttNum), + zap.Error(err), + ) + })); err != nil { + return 0, err + } + + return power, nil +} + +func (fp *FinalityProviderInstance) GetFinalityProviderSlashedWithRetry() (bool, error) { + var ( + slashed bool + err error + ) + + if err := retry.Do(func() error { + slashed, err = fp.cc.QueryFinalityProviderSlashed(fp.MustGetBtcPk()) + if err != nil { + return err + } + return nil + }, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { + fp.logger.Debug( + "failed to query the finality-provider", + zap.Uint("attempt", n+1), + zap.Uint("max_attempts", RtyAttNum), + zap.Error(err), + ) + })); err != nil { + return false, err + } + + return slashed, nil +} diff --git a/finality-provider/service/fp_instance_test.go b/finality-provider/service/fp_instance_test.go new file mode 100644 index 00000000..c58ad91d --- /dev/null +++ b/finality-provider/service/fp_instance_test.go @@ -0,0 +1,126 @@ +package service_test + +import ( + "math/rand" + "os" + "path/filepath" + "testing" + + "github.com/btcsuite/btcd/btcec/v2" + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/require" + "go.uber.org/zap" + + "github.com/babylonchain/finality-provider/clientcontroller" + "github.com/babylonchain/finality-provider/eotsmanager" + "github.com/babylonchain/finality-provider/finality-provider/proto" + "github.com/babylonchain/finality-provider/finality-provider/service" + "github.com/babylonchain/finality-provider/testutil" + "github.com/babylonchain/finality-provider/types" +) + +func FuzzCommitPubRandList(f *testing.F) { + testutil.AddRandomSeedsToFuzzer(f, 10) + f.Fuzz(func(t *testing.T, seed int64) { + r := rand.New(rand.NewSource(seed)) + + randomStartingHeight := uint64(r.Int63n(100) + 1) + currentHeight := randomStartingHeight + uint64(r.Int63n(10)+2) + startingBlock := &types.BlockInfo{Height: randomStartingHeight, Hash: testutil.GenRandomByteArray(r, 32)} + mockClientController := testutil.PrepareMockedClientController(t, r, randomStartingHeight, currentHeight) + mockClientController.EXPECT().QueryFinalityProviderVotingPower(gomock.Any(), gomock.Any()). + Return(uint64(0), nil).AnyTimes() + _, fpIns, cleanUp := startFinalityProviderAppWithRegisteredFp(t, r, mockClientController, randomStartingHeight) + defer cleanUp() + + expectedTxHash := testutil.GenRandomHexStr(r, 32) + mockClientController.EXPECT(). + CommitPubRandList(fpIns.MustGetBtcPk(), startingBlock.Height+1, gomock.Any(), gomock.Any()). + Return(&types.TxResponse{TxHash: expectedTxHash}, nil).AnyTimes() + mockClientController.EXPECT().QueryLastCommittedPublicRand(gomock.Any(), uint64(1)).Return(nil, nil).AnyTimes() + res, err := fpIns.CommitPubRand(startingBlock) + require.NoError(t, err) + require.Equal(t, expectedTxHash, res.TxHash) + }) +} + +func FuzzSubmitFinalitySig(f *testing.F) { + testutil.AddRandomSeedsToFuzzer(f, 10) + f.Fuzz(func(t *testing.T, seed int64) { + r := rand.New(rand.NewSource(seed)) + + randomStartingHeight := uint64(r.Int63n(100) + 1) + currentHeight := randomStartingHeight + uint64(r.Int63n(10)+1) + startingBlock := &types.BlockInfo{Height: randomStartingHeight, Hash: testutil.GenRandomByteArray(r, 32)} + mockClientController := testutil.PrepareMockedClientController(t, r, randomStartingHeight, currentHeight) + mockClientController.EXPECT().QueryLatestFinalizedBlocks(gomock.Any()).Return(nil, nil).AnyTimes() + _, fpIns, cleanUp := startFinalityProviderAppWithRegisteredFp(t, r, mockClientController, randomStartingHeight) + defer cleanUp() + + mockClientController.EXPECT().QueryFinalityProviderVotingPower(fpIns.MustGetBtcPk(), gomock.Any()). + Return(uint64(1), nil).AnyTimes() + lastCommittedHeight := randomStartingHeight + 25 + lastCommittedPubRandMap := make(map[uint64]*btcec.FieldVal) + lastCommittedPubRandMap[lastCommittedHeight] = testutil.GenPublicRand(r, t).ToFieldVal() + mockClientController.EXPECT().QueryLastCommittedPublicRand(gomock.Any(), uint64(1)).Return(lastCommittedPubRandMap, nil).AnyTimes() + mockClientController.EXPECT().QueryFinalityProviderVotingPower(fpIns.MustGetBtcPk(), gomock.Any()). + Return(uint64(1), nil).AnyTimes() + + // submit finality sig + nextBlock := &types.BlockInfo{ + Height: startingBlock.Height + 1, + Hash: testutil.GenRandomByteArray(r, 32), + } + expectedTxHash := testutil.GenRandomHexStr(r, 32) + mockClientController.EXPECT(). + SubmitFinalitySig(fpIns.MustGetBtcPk(), nextBlock.Height, nextBlock.Hash, gomock.Any()). + Return(&types.TxResponse{TxHash: expectedTxHash}, nil).AnyTimes() + providerRes, err := fpIns.SubmitFinalitySignature(nextBlock) + require.NoError(t, err) + require.Equal(t, expectedTxHash, providerRes.TxHash) + + // check the last_voted_height + require.Equal(t, nextBlock.Height, fpIns.GetLastVotedHeight()) + require.Equal(t, nextBlock.Height, fpIns.GetLastProcessedHeight()) + }) +} + +func startFinalityProviderAppWithRegisteredFp(t *testing.T, r *rand.Rand, cc clientcontroller.ClientController, startingHeight uint64) (*service.FinalityProviderApp, *service.FinalityProviderInstance, func()) { + logger := zap.NewNop() + // create an EOTS manager + eotsHomeDir := filepath.Join(t.TempDir(), "eots-home") + eotsCfg := testutil.GenEOTSConfig(r, t) + em, err := eotsmanager.NewLocalEOTSManager(eotsHomeDir, eotsCfg, logger) + require.NoError(t, err) + + // create finality-provider app with randomized config + fpHomeDir := filepath.Join(t.TempDir(), "fp-home") + fpCfg := testutil.GenFpConfig(r, t, fpHomeDir) + fpCfg.NumPubRand = testutil.TestPubRandNum + fpCfg.PollerConfig.AutoChainScanningMode = false + fpCfg.PollerConfig.StaticChainScanningStartHeight = startingHeight + app, err := service.NewFinalityProviderApp(fpHomeDir, fpCfg, cc, em, logger) + require.NoError(t, err) + err = app.Start() + require.NoError(t, err) + err = app.StartHandlingAll() + require.NoError(t, err) + + // create registered finality-provider + fp := testutil.GenStoredFinalityProvider(r, t, app, passphrase, hdPath) + err = app.GetFinalityProviderStore().SetFinalityProviderStatus(fp, proto.FinalityProviderStatus_REGISTERED) + require.NoError(t, err) + fpIns, err := service.NewFinalityProviderInstance(fp.MustGetBIP340BTCPK(), fpCfg, app.GetFinalityProviderStore(), cc, em, passphrase, make(chan *service.CriticalError), logger) + require.NoError(t, err) + + cleanUp := func() { + err = app.Stop() + require.NoError(t, err) + err = os.RemoveAll(eotsHomeDir) + require.NoError(t, err) + err = os.RemoveAll(fpHomeDir) + require.NoError(t, err) + } + + return app, fpIns, cleanUp +} diff --git a/finality-provider/service/fp_manager.go b/finality-provider/service/fp_manager.go new file mode 100644 index 00000000..921747e4 --- /dev/null +++ b/finality-provider/service/fp_manager.go @@ -0,0 +1,372 @@ +package service + +import ( + "errors" + "fmt" + "sync" + "time" + + "github.com/avast/retry-go/v4" + bbntypes "github.com/babylonchain/babylon/types" + btcstakingtypes "github.com/babylonchain/babylon/x/btcstaking/types" + "go.uber.org/atomic" + "go.uber.org/zap" + + "github.com/babylonchain/finality-provider/clientcontroller" + "github.com/babylonchain/finality-provider/eotsmanager" + fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" + "github.com/babylonchain/finality-provider/finality-provider/proto" + fpstore "github.com/babylonchain/finality-provider/finality-provider/store" + "github.com/babylonchain/finality-provider/types" +) + +const instanceTerminatingMsg = "terminating the finality-provider instance due to critical error" + +type CriticalError struct { + err error + fpBtcPk *bbntypes.BIP340PubKey +} + +func (ce *CriticalError) Error() string { + return fmt.Sprintf("critical err on finality-provider %s: %s", ce.fpBtcPk.MarshalHex(), ce.err.Error()) +} + +type FinalityProviderManager struct { + isStarted *atomic.Bool + + mu sync.Mutex + wg sync.WaitGroup + + // running finality-provider instances map keyed by the hex string of the BTC public key + fpis map[string]*FinalityProviderInstance + + // needed for initiating finality-provider instances + fps *fpstore.FinalityProviderStore + config *fpcfg.Config + cc clientcontroller.ClientController + em eotsmanager.EOTSManager + logger *zap.Logger + + criticalErrChan chan *CriticalError + + quit chan struct{} +} + +func NewFinalityProviderManager(fps *fpstore.FinalityProviderStore, + config *fpcfg.Config, + cc clientcontroller.ClientController, + em eotsmanager.EOTSManager, + logger *zap.Logger, +) (*FinalityProviderManager, error) { + return &FinalityProviderManager{ + fpis: make(map[string]*FinalityProviderInstance), + criticalErrChan: make(chan *CriticalError), + isStarted: atomic.NewBool(false), + fps: fps, + config: config, + cc: cc, + em: em, + logger: logger, + quit: make(chan struct{}), + }, nil +} + +// monitorCriticalErr takes actions when it receives critical errors from a finality-provider instance +// if the finality-provider is slashed, it will be terminated and the program keeps running in case +// new finality providers join +// otherwise, the program will panic +func (fpm *FinalityProviderManager) monitorCriticalErr() { + defer fpm.wg.Done() + + var criticalErr *CriticalError + for { + select { + case criticalErr = <-fpm.criticalErrChan: + fpi, err := fpm.GetFinalityProviderInstance(criticalErr.fpBtcPk) + if err != nil { + fpm.logger.Debug("the finality-provider instance is already shutdown", + zap.String("pk", criticalErr.fpBtcPk.MarshalHex())) + continue + } + if errors.Is(criticalErr.err, btcstakingtypes.ErrFpAlreadySlashed) { + fpm.setFinalityProviderSlashed(fpi) + fpm.logger.Debug("the finality-provider has been slashed", + zap.String("pk", criticalErr.fpBtcPk.MarshalHex())) + continue + } + fpm.logger.Fatal(instanceTerminatingMsg, + zap.String("pk", criticalErr.fpBtcPk.MarshalHex()), zap.Error(criticalErr.err)) + case <-fpm.quit: + return + } + } +} + +// monitorStatusUpdate periodically check the status of each managed finality providers and update +// it accordingly. We update the status by querying the latest voting power and the slashed_height. +// In particular, we perform the following status transitions (REGISTERED, ACTIVE, INACTIVE, SLASHED): +// 1. if power == 0 and slashed_height == 0, if status == ACTIVE, change to INACTIVE, otherwise remain the same +// 2. if power == 0 and slashed_height > 0, set status to SLASHED and stop and remove the finality-provider instance +// 3. if power > 0 (slashed_height must > 0), set status to ACTIVE +// NOTE: once error occurs, we log and continue as the status update is not critical to the entire program +func (fpm *FinalityProviderManager) monitorStatusUpdate() { + defer fpm.wg.Done() + + if fpm.config.StatusUpdateInterval == 0 { + fpm.logger.Info("the status update is disabled") + return + } + + statusUpdateTicker := time.NewTicker(fpm.config.StatusUpdateInterval) + defer statusUpdateTicker.Stop() + + for { + select { + case <-statusUpdateTicker.C: + latestBlock, err := fpm.getLatestBlockWithRetry() + if err != nil { + fpm.logger.Debug("failed to get the latest block", zap.Error(err)) + continue + } + fpis := fpm.ListFinalityProviderInstances() + for _, fpi := range fpis { + oldStatus := fpi.GetStatus() + power, err := fpi.GetVotingPowerWithRetry(latestBlock.Height) + if err != nil { + fpm.logger.Debug( + "failed to get the voting power", + zap.String("fp_btc_pk", fpi.GetBtcPkHex()), + zap.Uint64("height", latestBlock.Height), + zap.Error(err), + ) + continue + } + // power > 0 (slashed_height must > 0), set status to ACTIVE + if power > 0 { + if oldStatus != proto.FinalityProviderStatus_ACTIVE { + fpi.MustSetStatus(proto.FinalityProviderStatus_ACTIVE) + fpm.logger.Debug( + "the finality-provider status is changed to ACTIVE", + zap.String("fp_btc_pk", fpi.GetBtcPkHex()), + zap.String("old_status", oldStatus.String()), + zap.Uint64("power", power), + ) + } + continue + } + slashed, err := fpi.GetFinalityProviderSlashedWithRetry() + if err != nil { + fpm.logger.Debug( + "failed to get the slashed height", + zap.String("fp_btc_pk", fpi.GetBtcPkHex()), + zap.Error(err), + ) + continue + } + // power == 0 and slashed == true, set status to SLASHED and stop and remove the finality-provider instance + if slashed { + fpm.setFinalityProviderSlashed(fpi) + fpm.logger.Debug( + "the finality-provider is slashed", + zap.String("fp_btc_pk", fpi.GetBtcPkHex()), + zap.String("old_status", oldStatus.String()), + ) + continue + } + // power == 0 and slashed_height == 0, change to INACTIVE if the current status is ACTIVE + if oldStatus == proto.FinalityProviderStatus_ACTIVE { + fpi.MustSetStatus(proto.FinalityProviderStatus_INACTIVE) + fpm.logger.Debug( + "the finality-provider status is changed to INACTIVE", + zap.String("fp_btc_pk", fpi.GetBtcPkHex()), + zap.String("old_status", oldStatus.String()), + ) + } + } + case <-fpm.quit: + return + } + } +} + +func (fpm *FinalityProviderManager) setFinalityProviderSlashed(fpi *FinalityProviderInstance) { + fpi.MustSetStatus(proto.FinalityProviderStatus_SLASHED) + if err := fpm.removeFinalityProviderInstance(fpi.GetBtcPkBIP340()); err != nil { + panic(fmt.Errorf("failed to terminate a slashed finality-provider %s: %w", fpi.GetBtcPkHex(), err)) + } +} + +func (fpm *FinalityProviderManager) StartFinalityProvider(fpPk *bbntypes.BIP340PubKey, passphrase string) error { + if !fpm.isStarted.Load() { + fpm.isStarted.Store(true) + + fpm.wg.Add(1) + go fpm.monitorCriticalErr() + + fpm.wg.Add(1) + go fpm.monitorStatusUpdate() + } + + if fpm.numOfRunningFinalityProviders() >= int(fpm.config.MaxNumFinalityProviders) { + return fmt.Errorf("reaching maximum number of running finality providers %v", fpm.config.MaxNumFinalityProviders) + } + + if err := fpm.addFinalityProviderInstance(fpPk, passphrase); err != nil { + return err + } + + return nil +} + +func (fpm *FinalityProviderManager) StartAll() error { + if !fpm.isStarted.Load() { + fpm.isStarted.Store(true) + + fpm.wg.Add(1) + go fpm.monitorCriticalErr() + + fpm.wg.Add(1) + go fpm.monitorStatusUpdate() + } + + registeredFps, err := fpm.fps.ListRegisteredFinalityProviders() + if err != nil { + return err + } + + for _, fp := range registeredFps { + // TODO: passphrase is not available for starting all the finality providers + if err := fpm.StartFinalityProvider(fp.MustGetBIP340BTCPK(), ""); err != nil { + return err + } + } + + return nil +} + +func (fpm *FinalityProviderManager) Stop() error { + if !fpm.isStarted.Swap(false) { + return fmt.Errorf("the finality-provider manager has already stopped") + } + + var stopErr error + + for _, fpi := range fpm.fpis { + if !fpi.IsRunning() { + continue + } + if err := fpi.Stop(); err != nil { + stopErr = err + break + } + } + + close(fpm.quit) + fpm.wg.Wait() + + return stopErr +} + +func (fpm *FinalityProviderManager) ListFinalityProviderInstances() []*FinalityProviderInstance { + fpm.mu.Lock() + defer fpm.mu.Unlock() + + fpisList := make([]*FinalityProviderInstance, 0, len(fpm.fpis)) + for _, fpi := range fpm.fpis { + fpisList = append(fpisList, fpi) + } + + return fpisList +} + +func (fpm *FinalityProviderManager) GetFinalityProviderInstance(fpPk *bbntypes.BIP340PubKey) (*FinalityProviderInstance, error) { + fpm.mu.Lock() + defer fpm.mu.Unlock() + + keyHex := fpPk.MarshalHex() + v, exists := fpm.fpis[keyHex] + if !exists { + return nil, fmt.Errorf("cannot find the finality-provider instance with PK: %s", keyHex) + } + + return v, nil +} + +func (fpm *FinalityProviderManager) removeFinalityProviderInstance(fpPk *bbntypes.BIP340PubKey) error { + fpm.mu.Lock() + defer fpm.mu.Unlock() + + keyHex := fpPk.MarshalHex() + fpi, exists := fpm.fpis[keyHex] + if !exists { + return fmt.Errorf("cannot find the finality-provider instance with PK: %s", keyHex) + } + if fpi.IsRunning() { + if err := fpi.Stop(); err != nil { + return fmt.Errorf("failed to stop the finality-provider instance %s", keyHex) + } + } + + delete(fpm.fpis, keyHex) + return nil +} + +func (fpm *FinalityProviderManager) numOfRunningFinalityProviders() int { + fpm.mu.Lock() + defer fpm.mu.Unlock() + + return len(fpm.fpis) +} + +// addFinalityProviderInstance creates a finality-provider instance, starts it and adds it into the finality-provider manager +func (fpm *FinalityProviderManager) addFinalityProviderInstance( + pk *bbntypes.BIP340PubKey, + passphrase string, +) error { + fpm.mu.Lock() + defer fpm.mu.Unlock() + + pkHex := pk.MarshalHex() + if _, exists := fpm.fpis[pkHex]; exists { + return fmt.Errorf("finality-provider instance already exists") + } + + fpIns, err := NewFinalityProviderInstance(pk, fpm.config, fpm.fps, fpm.cc, fpm.em, passphrase, fpm.criticalErrChan, fpm.logger) + if err != nil { + return fmt.Errorf("failed to create finality-provider %s instance: %w", pkHex, err) + } + + if err := fpIns.Start(); err != nil { + return fmt.Errorf("failed to start finality-provider %s instance: %w", pkHex, err) + } + + fpm.fpis[pkHex] = fpIns + + return nil +} + +func (fpm *FinalityProviderManager) getLatestBlockWithRetry() (*types.BlockInfo, error) { + var ( + latestBlock *types.BlockInfo + err error + ) + + if err := retry.Do(func() error { + latestBlock, err = fpm.cc.QueryBestBlock() + if err != nil { + return err + } + return nil + }, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { + fpm.logger.Debug( + "failed to query the consumer chain for the latest block", + zap.Uint("attempt", n+1), + zap.Uint("max_attempts", RtyAttNum), + zap.Error(err), + ) + })); err != nil { + return nil, err + } + + return latestBlock, nil +} diff --git a/finality-provider/service/fp_manager_test.go b/finality-provider/service/fp_manager_test.go new file mode 100644 index 00000000..511068bb --- /dev/null +++ b/finality-provider/service/fp_manager_test.go @@ -0,0 +1,162 @@ +package service_test + +import ( + "math/rand" + "os" + "path/filepath" + "strings" + "testing" + "time" + + fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" + "github.com/babylonchain/finality-provider/util" + + "go.uber.org/zap" + + "github.com/babylonchain/finality-provider/keyring" + + "github.com/babylonchain/babylon/testutil/datagen" + bbntypes "github.com/babylonchain/babylon/types" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/require" + + fpstore "github.com/babylonchain/finality-provider/finality-provider/store" + + "github.com/babylonchain/finality-provider/clientcontroller" + "github.com/babylonchain/finality-provider/eotsmanager" + "github.com/babylonchain/finality-provider/finality-provider/proto" + "github.com/babylonchain/finality-provider/finality-provider/service" + "github.com/babylonchain/finality-provider/testutil" + "github.com/babylonchain/finality-provider/testutil/mocks" + "github.com/babylonchain/finality-provider/types" +) + +var ( + eventuallyWaitTimeOut = 1 * time.Second + eventuallyPollTime = 10 * time.Millisecond +) + +func FuzzStatusUpdate(f *testing.F) { + testutil.AddRandomSeedsToFuzzer(f, 10) + f.Fuzz(func(t *testing.T, seed int64) { + r := rand.New(rand.NewSource(seed)) + + ctl := gomock.NewController(t) + mockClientController := mocks.NewMockClientController(ctl) + vm, fpPk, cleanUp := newFinalityProviderManagerWithRegisteredFp(t, r, mockClientController) + defer cleanUp() + + // setup mocks + currentHeight := uint64(r.Int63n(100) + 1) + currentBlockRes := &types.BlockInfo{ + Height: currentHeight, + Hash: datagen.GenRandomByteArray(r, 32), + } + mockClientController.EXPECT().QueryBestBlock().Return(currentBlockRes, nil).AnyTimes() + mockClientController.EXPECT().Close().Return(nil).AnyTimes() + mockClientController.EXPECT().QueryLatestFinalizedBlocks(gomock.Any()).Return(nil, nil).AnyTimes() + mockClientController.EXPECT().QueryBestBlock().Return(currentBlockRes, nil).AnyTimes() + mockClientController.EXPECT().QueryActivatedHeight().Return(uint64(1), nil).AnyTimes() + mockClientController.EXPECT().QueryBlock(gomock.Any()).Return(currentBlockRes, nil).AnyTimes() + mockClientController.EXPECT().QueryLastCommittedPublicRand(gomock.Any(), uint64(1)).Return(nil, nil).AnyTimes() + + votingPower := uint64(r.Intn(2)) + mockClientController.EXPECT().QueryFinalityProviderVotingPower(gomock.Any(), currentHeight).Return(votingPower, nil).AnyTimes() + mockClientController.EXPECT().SubmitFinalitySig(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(&types.TxResponse{TxHash: ""}, nil).AnyTimes() + var slashedHeight uint64 + if votingPower == 0 { + mockClientController.EXPECT().QueryFinalityProviderSlashed(gomock.Any()).Return(true, nil).AnyTimes() + } + + err := vm.StartFinalityProvider(fpPk, passphrase) + require.NoError(t, err) + fpIns := vm.ListFinalityProviderInstances()[0] + // stop the finality-provider as we are testing static functionalities + err = fpIns.Stop() + require.NoError(t, err) + + if votingPower > 0 { + waitForStatus(t, fpIns, proto.FinalityProviderStatus_ACTIVE) + } else { + if slashedHeight == 0 && fpIns.GetStatus() == proto.FinalityProviderStatus_ACTIVE { + waitForStatus(t, fpIns, proto.FinalityProviderStatus_INACTIVE) + } else if slashedHeight > 0 { + waitForStatus(t, fpIns, proto.FinalityProviderStatus_SLASHED) + } + } + }) +} + +func waitForStatus(t *testing.T, fpIns *service.FinalityProviderInstance, s proto.FinalityProviderStatus) { + require.Eventually(t, + func() bool { + return fpIns.GetStatus() == s + }, eventuallyWaitTimeOut, eventuallyPollTime) +} + +func newFinalityProviderManagerWithRegisteredFp(t *testing.T, r *rand.Rand, cc clientcontroller.ClientController) (*service.FinalityProviderManager, *bbntypes.BIP340PubKey, func()) { + logger := zap.NewNop() + // create an EOTS manager + eotsHomeDir := filepath.Join(t.TempDir(), "eots-home") + eotsCfg := testutil.GenEOTSConfig(r, t) + em, err := eotsmanager.NewLocalEOTSManager(eotsHomeDir, eotsCfg, logger) + require.NoError(t, err) + + // create finality-provider app with randomized config + fpHomeDir := filepath.Join(t.TempDir(), "fp-home") + fpCfg := testutil.GenFpConfig(r, t, fpHomeDir) + fpCfg.StatusUpdateInterval = 10 * time.Millisecond + input := strings.NewReader("") + kr, err := keyring.CreateKeyring( + fpCfg.BabylonConfig.KeyDirectory, + fpCfg.BabylonConfig.ChainID, + fpCfg.BabylonConfig.KeyringBackend, + input, + ) + require.NoError(t, err) + err = util.MakeDirectory(fpcfg.DataDir(fpHomeDir)) + require.NoError(t, err) + fpStore, err := fpstore.NewFinalityProviderStore( + fpcfg.DBPath(fpHomeDir), + fpCfg.DatabaseConfig.Name, + fpCfg.DatabaseConfig.Backend, + ) + require.NoError(t, err) + + vm, err := service.NewFinalityProviderManager(fpStore, fpCfg, cc, em, logger) + require.NoError(t, err) + + // create registered finality-provider + keyName := datagen.GenRandomHexStr(r, 10) + chainID := datagen.GenRandomHexStr(r, 10) + kc, err := keyring.NewChainKeyringControllerWithKeyring(kr, keyName, input) + require.NoError(t, err) + btcPkBytes, err := em.CreateKey(keyName, passphrase, hdPath) + require.NoError(t, err) + btcPk, err := bbntypes.NewBIP340PubKey(btcPkBytes) + require.NoError(t, err) + keyInfo, err := kc.CreateChainKey(passphrase, hdPath) + require.NoError(t, err) + bbnPk := &secp256k1.PubKey{Key: keyInfo.PublicKey.SerializeCompressed()} + fpRecord, err := em.KeyRecord(btcPk.MustMarshal(), passphrase) + require.NoError(t, err) + pop, err := kc.CreatePop(fpRecord.PrivKey, passphrase) + require.NoError(t, err) + + storedFp := fpstore.NewStoreFinalityProvider(bbnPk, btcPk, keyName, chainID, pop, testutil.EmptyDescription(), testutil.ZeroCommissionRate()) + storedFp.Status = proto.FinalityProviderStatus_REGISTERED + err = fpStore.SaveFinalityProvider(storedFp) + require.NoError(t, err) + + cleanUp := func() { + err = vm.Stop() + require.NoError(t, err) + err = os.RemoveAll(eotsHomeDir) + require.NoError(t, err) + err = os.RemoveAll(fpHomeDir) + require.NoError(t, err) + } + + return vm, btcPk, cleanUp +} diff --git a/finality-provider/service/rpcserver.go b/finality-provider/service/rpcserver.go new file mode 100644 index 00000000..a2948746 --- /dev/null +++ b/finality-provider/service/rpcserver.go @@ -0,0 +1,220 @@ +package service + +import ( + "context" + "encoding/hex" + "fmt" + "sync" + "sync/atomic" + + "cosmossdk.io/math" + bbntypes "github.com/babylonchain/babylon/types" + "google.golang.org/grpc" + + "github.com/babylonchain/finality-provider/finality-provider/proto" + "github.com/babylonchain/finality-provider/types" + "github.com/babylonchain/finality-provider/version" +) + +// rpcServer is the main RPC server for the Finality Provider daemon that handles +// gRPC incoming requests. +type rpcServer struct { + started int32 + shutdown int32 + + proto.UnimplementedFinalityProvidersServer + + app *FinalityProviderApp + + quit chan struct{} + wg sync.WaitGroup +} + +// newRPCServer creates a new RPC sever from the set of input dependencies. +func newRPCServer( + fpa *FinalityProviderApp, +) *rpcServer { + + return &rpcServer{ + quit: make(chan struct{}), + app: fpa, + } +} + +// Start signals that the RPC server starts accepting requests. +func (r *rpcServer) Start() error { + if atomic.AddInt32(&r.started, 1) != 1 { + return nil + } + + return nil +} + +// Stop signals that the RPC server should attempt a graceful shutdown and +// cancel any outstanding requests. +func (r *rpcServer) Stop() error { + if atomic.AddInt32(&r.shutdown, 1) != 1 { + return nil + } + + close(r.quit) + + r.wg.Wait() + + return nil +} + +// RegisterWithGrpcServer registers the rpcServer with the passed root gRPC +// server. +func (r *rpcServer) RegisterWithGrpcServer(grpcServer *grpc.Server) error { + // Register the main RPC server. + proto.RegisterFinalityProvidersServer(grpcServer, r) + return nil +} + +// GetInfo returns general information relating to the active daemon +func (r *rpcServer) GetInfo(context.Context, *proto.GetInfoRequest) (*proto.GetInfoResponse, error) { + + return &proto.GetInfoResponse{ + Version: version.Version(), + }, nil +} + +// CreateFinalityProvider generates a finality-provider object and saves it in the database +func (r *rpcServer) CreateFinalityProvider(ctx context.Context, req *proto.CreateFinalityProviderRequest) ( + *proto.CreateFinalityProviderResponse, error) { + + commissionRate, err := math.LegacyNewDecFromStr(req.Commission) + if err != nil { + return nil, err + } + + result, err := r.app.CreateFinalityProvider( + req.KeyName, + req.ChainId, + req.Passphrase, + req.HdPath, + req.Description, + &commissionRate, + ) + + if err != nil { + return nil, err + } + + fpInfo, err := proto.NewFinalityProviderInfo(result.StoreFp) + if err != nil { + return nil, err + } + return &proto.CreateFinalityProviderResponse{ + FinalityProvider: fpInfo, + }, nil + +} + +// RegisterFinalityProvider sends a transactions to Babylon to register a BTC finality-provider +func (r *rpcServer) RegisterFinalityProvider(ctx context.Context, req *proto.RegisterFinalityProviderRequest) ( + *proto.RegisterFinalityProviderResponse, error) { + + txRes, err := r.app.RegisterFinalityProvider(req.BtcPk) + if err != nil { + return nil, fmt.Errorf("failed to register the finality-provider to Babylon: %w", err) + } + + // the finality-provider instance should be started right after registration + if err := r.app.StartHandlingFinalityProvider(txRes.btcPubKey, req.Passphrase); err != nil { + return nil, fmt.Errorf("failed to start the registered finality-provider %s: %w", hex.EncodeToString(txRes.bbnPubKey.Key), err) + } + + return &proto.RegisterFinalityProviderResponse{TxHash: txRes.TxHash}, nil +} + +// AddFinalitySignature adds a manually constructed finality signature to Babylon +// NOTE: this is only used for presentation/testing purposes +func (r *rpcServer) AddFinalitySignature(ctx context.Context, req *proto.AddFinalitySignatureRequest) ( + *proto.AddFinalitySignatureResponse, error) { + + fpPk, err := bbntypes.NewBIP340PubKeyFromHex(req.BtcPk) + if err != nil { + return nil, err + } + + fpi, err := r.app.GetFinalityProviderInstance(fpPk) + if err != nil { + return nil, err + } + + b := &types.BlockInfo{ + Height: req.Height, + Hash: req.AppHash, + } + + txRes, privKey, err := fpi.TestSubmitFinalitySignatureAndExtractPrivKey(b) + if err != nil { + return nil, err + } + + res := &proto.AddFinalitySignatureResponse{TxHash: txRes.TxHash} + + // if privKey is not empty, then this BTC finality-provider + // has voted for a fork and will be slashed + if privKey != nil { + localPrivKey, err := r.app.getFpPrivKey(fpPk.MustMarshal()) + res.ExtractedSkHex = privKey.Key.String() + if err != nil { + return nil, err + } + localSkHex := localPrivKey.Key.String() + localSkNegateHex := localPrivKey.Key.Negate().String() + if res.ExtractedSkHex == localSkHex { + res.LocalSkHex = localSkHex + } else if res.ExtractedSkHex == localSkNegateHex { + res.LocalSkHex = localSkNegateHex + } else { + return nil, fmt.Errorf("the finality-provider's BTC private key is extracted but does not match the local key,"+ + "extrated: %s, local: %s, local-negated: %s", + res.ExtractedSkHex, localSkHex, localSkNegateHex) + } + } + + return res, nil +} + +// QueryFinalityProvider queries the information of the finality-provider +func (r *rpcServer) QueryFinalityProvider(ctx context.Context, req *proto.QueryFinalityProviderRequest) ( + *proto.QueryFinalityProviderResponse, error) { + + fpPk, err := bbntypes.NewBIP340PubKeyFromHex(req.BtcPk) + if err != nil { + return nil, err + } + fp, err := r.app.GetFinalityProviderInstance(fpPk) + if err != nil { + return nil, err + } + + fpInfo, err := proto.NewFinalityProviderInfo(fp.GetStoreFinalityProvider()) + if err != nil { + return nil, err + } + + return &proto.QueryFinalityProviderResponse{FinalityProvider: fpInfo}, nil +} + +// QueryFinalityProviderList queries the information of a list of finality providers +func (r *rpcServer) QueryFinalityProviderList(ctx context.Context, req *proto.QueryFinalityProviderListRequest) ( + *proto.QueryFinalityProviderListResponse, error) { + + fps := r.app.ListFinalityProviderInstances() + + fpsInfo := make([]*proto.FinalityProviderInfo, len(fps)) + for i, fp := range fps { + fpInfo, err := proto.NewFinalityProviderInfo(fp.GetStoreFinalityProvider()) + if err != nil { + return nil, err + } + fpsInfo[i] = fpInfo + } + + return &proto.QueryFinalityProviderListResponse{FinalityProviders: fpsInfo}, nil +} diff --git a/finality-provider/service/server.go b/finality-provider/service/server.go new file mode 100644 index 00000000..5b4dbf58 --- /dev/null +++ b/finality-provider/service/server.go @@ -0,0 +1,108 @@ +package service + +import ( + "fmt" + "net" + "sync" + "sync/atomic" + + "github.com/lightningnetwork/lnd/signal" + "go.uber.org/zap" + "google.golang.org/grpc" + + fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" +) + +// Server is the main daemon construct for the Finality Provider server. It handles +// spinning up the RPC sever, the database, and any other components that the +// Taproot Asset server needs to function. +type Server struct { + started int32 + + cfg *fpcfg.Config + logger *zap.Logger + + rpcServer *rpcServer + interceptor signal.Interceptor + + quit chan struct{} +} + +// NewFinalityproviderServer creates a new server with the given config. +func NewFinalityProviderServer(cfg *fpcfg.Config, l *zap.Logger, fpa *FinalityProviderApp, sig signal.Interceptor) *Server { + return &Server{ + cfg: cfg, + logger: l, + rpcServer: newRPCServer(fpa), + interceptor: sig, + quit: make(chan struct{}, 1), + } +} + +// RunUntilShutdown runs the main EOTS manager server loop until a signal is +// received to shut down the process. +func (s *Server) RunUntilShutdown() error { + if atomic.AddInt32(&s.started, 1) != 1 { + return nil + } + + defer func() { + s.logger.Info("Shutdown complete") + }() + + listenAddr := s.cfg.RpcListener + // we create listeners from the RPCListeners defined + // in the config. + lis, err := net.Listen("tcp", listenAddr) + if err != nil { + return fmt.Errorf("failed to listen on %s: %w", listenAddr, err) + } + defer lis.Close() + + grpcServer := grpc.NewServer() + defer grpcServer.Stop() + + if err := s.rpcServer.RegisterWithGrpcServer(grpcServer); err != nil { + return fmt.Errorf("failed to register gRPC server: %w", err) + } + + // All the necessary components have been registered, so we can + // actually start listening for requests. + if err := s.startGrpcListen(grpcServer, []net.Listener{lis}); err != nil { + return fmt.Errorf("failed to start gRPC listener: %v", err) + } + + s.logger.Info("Finality Provider Daemon is fully active!") + + // Wait for shutdown signal from either a graceful server stop or from + // the interrupt handler. + <-s.interceptor.ShutdownChannel() + + return nil +} + +// startGrpcListen starts the GRPC server on the passed listeners. +func (s *Server) startGrpcListen(grpcServer *grpc.Server, listeners []net.Listener) error { + + // Use a WaitGroup so we can be sure the instructions on how to input the + // password is the last thing to be printed to the console. + var wg sync.WaitGroup + + for _, lis := range listeners { + wg.Add(1) + go func(lis net.Listener) { + s.logger.Info("RPC server listening", zap.String("address", lis.Addr().String())) + + // Close the ready chan to indicate we are listening. + defer lis.Close() + + wg.Done() + _ = grpcServer.Serve(lis) + }(lis) + } + + // Wait for gRPC servers to be up running. + wg.Wait() + + return nil +} diff --git a/finality-provider/service/types.go b/finality-provider/service/types.go new file mode 100644 index 00000000..b2aa907b --- /dev/null +++ b/finality-provider/service/types.go @@ -0,0 +1,178 @@ +package service + +import ( + "sync" + + sdkmath "cosmossdk.io/math" + bbntypes "github.com/babylonchain/babylon/types" + btcstakingtypes "github.com/babylonchain/babylon/x/btcstaking/types" + "github.com/btcsuite/btcd/btcec/v2" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + "go.uber.org/zap" + + "github.com/babylonchain/finality-provider/finality-provider/proto" + fpstore "github.com/babylonchain/finality-provider/finality-provider/store" +) + +type createFinalityProviderResponse struct { + StoreFp *proto.StoreFinalityProvider +} +type createFinalityProviderRequest struct { + keyName string + passPhrase string + hdPath string + chainID string + description []byte + commission *sdkmath.LegacyDec + errResponse chan error + successResponse chan *createFinalityProviderResponse +} + +type registerFinalityProviderRequest struct { + bbnPubKey *secp256k1.PubKey + btcPubKey *bbntypes.BIP340PubKey + // TODO we should have our own representation of PoP + pop *btcstakingtypes.ProofOfPossession + description []byte + commission *sdkmath.LegacyDec + errResponse chan error + successResponse chan *RegisterFinalityProviderResponse +} + +type finalityProviderRegisteredEvent struct { + bbnPubKey *secp256k1.PubKey + btcPubKey *bbntypes.BIP340PubKey + txHash string + successResponse chan *RegisterFinalityProviderResponse +} + +type RegisterFinalityProviderResponse struct { + bbnPubKey *secp256k1.PubKey + btcPubKey *bbntypes.BIP340PubKey + TxHash string +} + +type CreateFinalityProviderResult struct { + StoreFp *proto.StoreFinalityProvider +} + +type fpState struct { + mu sync.Mutex + fp *proto.StoreFinalityProvider + s *fpstore.FinalityProviderStore +} + +func (fps *fpState) getStoreFinalityProvider() *proto.StoreFinalityProvider { + fps.mu.Lock() + defer fps.mu.Unlock() + return fps.fp +} + +func (fps *fpState) setStatus(s proto.FinalityProviderStatus) error { + fps.mu.Lock() + fps.fp.Status = s + fps.mu.Unlock() + return fps.s.UpdateFinalityProvider(fps.fp) +} + +func (fps *fpState) setLastProcessedHeight(height uint64) error { + fps.mu.Lock() + fps.fp.LastProcessedHeight = height + fps.mu.Unlock() + return fps.s.UpdateFinalityProvider(fps.fp) +} + +func (fps *fpState) setLastProcessedAndVotedHeight(height uint64) error { + fps.mu.Lock() + fps.fp.LastVotedHeight = height + fps.fp.LastProcessedHeight = height + fps.mu.Unlock() + return fps.s.UpdateFinalityProvider(fps.fp) +} + +func (fp *FinalityProviderInstance) GetStoreFinalityProvider() *proto.StoreFinalityProvider { + return fp.state.getStoreFinalityProvider() +} + +func (fp *FinalityProviderInstance) GetBabylonPk() *secp256k1.PubKey { + return fp.state.getStoreFinalityProvider().GetBabylonPK() +} + +func (fp *FinalityProviderInstance) GetBabylonPkHex() string { + return fp.state.getStoreFinalityProvider().GetBabylonPkHexString() +} + +func (fp *FinalityProviderInstance) GetBtcPkBIP340() *bbntypes.BIP340PubKey { + return fp.state.getStoreFinalityProvider().MustGetBIP340BTCPK() +} + +func (fp *FinalityProviderInstance) MustGetBtcPk() *btcec.PublicKey { + return fp.state.getStoreFinalityProvider().MustGetBTCPK() +} + +func (fp *FinalityProviderInstance) GetBtcPkHex() string { + return fp.GetBtcPkBIP340().MarshalHex() +} + +func (fp *FinalityProviderInstance) GetStatus() proto.FinalityProviderStatus { + return fp.state.getStoreFinalityProvider().Status +} + +func (fp *FinalityProviderInstance) GetLastVotedHeight() uint64 { + return fp.state.getStoreFinalityProvider().LastVotedHeight +} + +func (fp *FinalityProviderInstance) GetLastProcessedHeight() uint64 { + return fp.state.getStoreFinalityProvider().LastProcessedHeight +} + +func (fp *FinalityProviderInstance) GetChainID() []byte { + return []byte(fp.state.getStoreFinalityProvider().ChainId) +} + +func (fp *FinalityProviderInstance) SetStatus(s proto.FinalityProviderStatus) error { + return fp.state.setStatus(s) +} + +func (fp *FinalityProviderInstance) MustSetStatus(s proto.FinalityProviderStatus) { + if err := fp.SetStatus(s); err != nil { + fp.logger.Fatal("failed to set finality-provider status", + zap.String("pk", fp.GetBtcPkHex()), zap.String("status", s.String())) + } +} + +func (fp *FinalityProviderInstance) SetLastProcessedHeight(height uint64) error { + return fp.state.setLastProcessedHeight(height) +} + +func (fp *FinalityProviderInstance) MustSetLastProcessedHeight(height uint64) { + if err := fp.SetLastProcessedHeight(height); err != nil { + fp.logger.Fatal("failed to set last processed height", + zap.String("pk", fp.GetBtcPkHex()), zap.Uint64("last_processed_height", height)) + } +} + +func (fp *FinalityProviderInstance) updateStateAfterFinalitySigSubmission(height uint64) error { + return fp.state.setLastProcessedAndVotedHeight(height) +} + +func (fp *FinalityProviderInstance) MustUpdateStateAfterFinalitySigSubmission(height uint64) { + if err := fp.updateStateAfterFinalitySigSubmission(height); err != nil { + fp.logger.Fatal("failed to update state after finality signature submitted", + zap.String("pk", fp.GetBtcPkHex()), zap.Uint64("height", height)) + } +} + +func (fp *FinalityProviderInstance) getEOTSPrivKey() (*btcec.PrivateKey, error) { + record, err := fp.em.KeyRecord(fp.btcPk.MustMarshal(), fp.passphrase) + if err != nil { + return nil, err + } + + return record.PrivKey, nil +} + +// only used for testing purposes +func (fp *FinalityProviderInstance) BtcPrivKey() (*btcec.PrivateKey, error) { + return fp.getEOTSPrivKey() +} diff --git a/finality-provider/store/fpstore.go b/finality-provider/store/fpstore.go new file mode 100644 index 00000000..feaa6088 --- /dev/null +++ b/finality-provider/store/fpstore.go @@ -0,0 +1,210 @@ +package store + +import ( + "fmt" + "math" + + sdkmath "cosmossdk.io/math" + "github.com/babylonchain/babylon/types" + bstypes "github.com/babylonchain/babylon/x/btcstaking/types" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + gproto "google.golang.org/protobuf/proto" + + "github.com/babylonchain/finality-provider/finality-provider/proto" + "github.com/babylonchain/finality-provider/store" +) + +const ( + fpPrefix = "finality-provider" +) + +func NewStoreFinalityProvider(babylonPk *secp256k1.PubKey, btcPk *types.BIP340PubKey, keyName, chainID string, pop *bstypes.ProofOfPossession, des []byte, com *sdkmath.LegacyDec) *proto.StoreFinalityProvider { + return &proto.StoreFinalityProvider{ + KeyName: keyName, + BabylonPk: babylonPk.Bytes(), + BtcPk: btcPk.MustMarshal(), + Pop: &proto.ProofOfPossession{ + BabylonSig: pop.BabylonSig, + BtcSig: pop.BtcSig, + }, + ChainId: chainID, + Status: proto.FinalityProviderStatus_CREATED, + Description: des, + Commission: com.String(), + } +} + +type FinalityProviderStore struct { + s store.Store +} + +func NewFinalityProviderStore(dbPath string, dbName string, dbBackend string) (*FinalityProviderStore, error) { + s, err := openStore(dbPath, dbName, dbBackend) + if err != nil { + return nil, err + } + + return &FinalityProviderStore{s: s}, nil +} + +func getFinalityProviderKey(pk []byte) []byte { + return append([]byte(fpPrefix), pk...) +} + +func (vs *FinalityProviderStore) getFinalityProviderListKey() []byte { + return []byte(fpPrefix) +} + +func (vs *FinalityProviderStore) SaveFinalityProvider(fp *proto.StoreFinalityProvider) error { + k := getFinalityProviderKey(fp.BtcPk) + v, err := gproto.Marshal(fp) + if err != nil { + return fmt.Errorf("failed to marshal the created finality-provider object: %w", err) + } + + if err := vs.s.Put(k, v); err != nil { + return fmt.Errorf("failed to save the created finality-provider object: %w", err) + } + + return nil +} + +func (vs *FinalityProviderStore) UpdateFinalityProvider(fp *proto.StoreFinalityProvider) error { + k := getFinalityProviderKey(fp.BtcPk) + exists, err := vs.s.Exists(k) + if err != nil { + return err + } + if !exists { + return fmt.Errorf("the finality-provider does not exist") + } + + v, err := gproto.Marshal(fp) + if err != nil { + return err + } + + if err := vs.s.Put(k, v); err != nil { + return err + } + + return nil +} + +func (vs *FinalityProviderStore) SetFinalityProviderStatus(fp *proto.StoreFinalityProvider, status proto.FinalityProviderStatus) error { + fp.Status = status + return vs.UpdateFinalityProvider(fp) +} + +func (vs *FinalityProviderStore) GetStoreFinalityProvider(pk []byte) (*proto.StoreFinalityProvider, error) { + k := getFinalityProviderKey(pk) + fpBytes, err := vs.s.Get(k) + if err != nil { + return nil, err + } + + fp := new(proto.StoreFinalityProvider) + err = gproto.Unmarshal(fpBytes, fp) + if err != nil { + panic(fmt.Errorf("unable to unmarshal finality-provider object: %w", err)) + } + + return fp, nil +} + +func (vs *FinalityProviderStore) ListFinalityProviders() ([]*proto.StoreFinalityProvider, error) { + k := vs.getFinalityProviderListKey() + fpsBytes, err := vs.s.List(k) + if err != nil { + return nil, err + } + + fpsList := make([]*proto.StoreFinalityProvider, len(fpsBytes)) + for i := 0; i < len(fpsBytes); i++ { + fp := new(proto.StoreFinalityProvider) + err := gproto.Unmarshal(fpsBytes[i].Value, fp) + if err != nil { + panic(fmt.Errorf("failed to unmarshal finality-provider from the database: %w", err)) + } + fpsList[i] = fp + } + + return fpsList, nil +} + +// ListRegisteredFinalityProviders returns a list of finality providers whose status is more than CREATED +// but less than SLASHED +func (vs *FinalityProviderStore) ListRegisteredFinalityProviders() ([]*proto.StoreFinalityProvider, error) { + k := vs.getFinalityProviderListKey() + fpsBytes, err := vs.s.List(k) + if err != nil { + return nil, err + } + + fpsList := make([]*proto.StoreFinalityProvider, 0) + for i := 0; i < len(fpsBytes); i++ { + fp := new(proto.StoreFinalityProvider) + err := gproto.Unmarshal(fpsBytes[i].Value, fp) + if err != nil { + panic(fmt.Errorf("failed to unmarshal finality-provider from the database: %w", err)) + } + if fp.Status > proto.FinalityProviderStatus_CREATED && fp.Status < proto.FinalityProviderStatus_SLASHED { + fpsList = append(fpsList, fp) + } + } + + return fpsList, nil +} + +func (vs *FinalityProviderStore) GetEarliestActiveFinalityProviderVotedHeight() (uint64, error) { + registeredFps, err := vs.ListRegisteredFinalityProviders() + if err != nil { + return 0, err + } + + if len(registeredFps) == 0 { + return 0, nil + } + + earliestHeight := uint64(math.MaxUint64) + activeFpsCnt := 0 + for _, fp := range registeredFps { + // Note there might be a delay between the finality-provider being active on Babylon + // and this program capturing that. However, given that we only care + // about the `LastVotedHeight` of the finality-provider, other parts of the program + // ensure that when this value is set, the finality-provider is stored as ACTIVE. + // TODO: Another option would be to query here for the + // active status of each finality-provider although this might prove inefficient. + if fp.Status != proto.FinalityProviderStatus_ACTIVE { + continue + } + activeFpsCnt += 1 + if earliestHeight > fp.LastVotedHeight { + earliestHeight = fp.LastVotedHeight + } + } + // If there are no active finality providers, return 0 + if activeFpsCnt == 0 { + return 0, nil + } + return earliestHeight, nil +} + +func (vs *FinalityProviderStore) Close() error { + if err := vs.s.Close(); err != nil { + return err + } + + return nil +} + +// openStore returns a Store instance with the given db type, path and name +// currently, we only support bbolt +func openStore(dbPath string, dbName string, dbBackend string) (store.Store, error) { + switch dbBackend { + case "bbolt": + return store.NewBboltStore(dbPath, dbName) + default: + return nil, fmt.Errorf("unsupported database type") + } +} diff --git a/finality-provider/store/fpstore_test.go b/finality-provider/store/fpstore_test.go new file mode 100644 index 00000000..a8c39a2b --- /dev/null +++ b/finality-provider/store/fpstore_test.go @@ -0,0 +1,45 @@ +package store_test + +import ( + "math/rand" + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/require" + + fpstore "github.com/babylonchain/finality-provider/finality-provider/store" + "github.com/babylonchain/finality-provider/testutil" +) + +// FuzzFinalityProvidersStore tests save and list finality providers properly +func FuzzFinalityProvidersStore(f *testing.F) { + testutil.AddRandomSeedsToFuzzer(f, 10) + f.Fuzz(func(t *testing.T, seed int64) { + r := rand.New(rand.NewSource(seed)) + + dbPath := filepath.Join(t.TempDir(), "db") + dbcfg := testutil.GenDBConfig(r, t) + vs, err := fpstore.NewFinalityProviderStore(dbPath, dbcfg.Name, dbcfg.Backend) + require.NoError(t, err) + + defer func() { + err := os.RemoveAll(dbPath) + require.NoError(t, err) + }() + + fp := testutil.GenRandomFinalityProvider(r, t) + err = vs.SaveFinalityProvider(fp) + require.NoError(t, err) + + fpList, err := vs.ListFinalityProviders() + require.NoError(t, err) + require.Equal(t, fp.BtcPk, fpList[0].BtcPk) + + actualFp, err := vs.GetStoreFinalityProvider(fp.BtcPk) + require.NoError(t, err) + require.Equal(t, fp.BabylonPk, actualFp.BabylonPk) + require.Equal(t, fp.BtcPk, actualFp.BtcPk) + require.Equal(t, fp.KeyName, actualFp.KeyName) + }) +} diff --git a/go.mod b/go.mod index afddf9d5..ff2e9477 100644 --- a/go.mod +++ b/go.mod @@ -1,310 +1,247 @@ -module github.com/babylonchain/btc-validator +module github.com/babylonchain/finality-provider -go 1.20 +go 1.21 + +toolchain go1.21.4 require ( - cosmossdk.io/math v1.0.1 - github.com/avast/retry-go/v4 v4.3.3 - github.com/babylonchain/babylon v0.7.1 - github.com/btcsuite/btcd v0.23.5-0.20230228185050-38331963bddd + cosmossdk.io/errors v1.0.1 + cosmossdk.io/math v1.2.0 + github.com/avast/retry-go/v4 v4.5.1 + github.com/babylonchain/babylon v0.8.0 + github.com/babylonchain/rpc-client v0.8.0 + github.com/btcsuite/btcd v0.24.0 github.com/btcsuite/btcd/btcec/v2 v2.3.2 - github.com/btcsuite/btcd/btcutil v1.1.3 - github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 - github.com/cometbft/cometbft v0.37.2 - github.com/cosmos/cosmos-proto v1.0.0-beta.2 - github.com/cosmos/cosmos-sdk v0.47.3 + github.com/btcsuite/btcd/btcutil v1.1.5 + github.com/cosmos/cosmos-proto v1.0.0-beta.3 + github.com/cosmos/cosmos-sdk v0.50.4-0.20240126152601-c4a2fe2b8987 github.com/cosmos/go-bip39 v1.0.0 - github.com/cosmos/gogoproto v1.4.10 - github.com/cosmos/relayer/v2 v2.4.1 + github.com/cosmos/gogoproto v1.4.11 + github.com/cosmos/relayer/v2 v2.4.3-0.20231227002143-820caf5ab483 + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 github.com/gogo/protobuf v1.3.3 github.com/golang/mock v1.6.0 github.com/jessevdk/go-flags v1.5.0 github.com/jsternberg/zap-logfmt v1.3.0 - github.com/juju/fslock v0.0.0-20160525022230-4d5c94c67b4b github.com/lightningnetwork/lnd v0.16.4-beta.rc1 - github.com/sirupsen/logrus v1.9.3 github.com/stretchr/testify v1.8.4 github.com/urfave/cli v1.22.14 - go.etcd.io/bbolt v1.3.7 + go.etcd.io/bbolt v1.3.8 go.uber.org/atomic v1.10.0 - go.uber.org/zap v1.24.0 - golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 - golang.org/x/sync v0.1.0 - google.golang.org/grpc v1.56.1 - google.golang.org/protobuf v1.31.0 + go.uber.org/zap v1.26.0 + google.golang.org/grpc v1.60.1 + google.golang.org/protobuf v1.32.0 ) require ( - cloud.google.com/go v0.110.0 // indirect - cloud.google.com/go/compute v1.19.1 // indirect + cloud.google.com/go v0.110.10 // indirect + cloud.google.com/go/compute v1.23.3 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect - cloud.google.com/go/iam v0.13.0 // indirect - cloud.google.com/go/storage v1.29.0 // indirect - cosmossdk.io/api v0.3.1 // indirect - cosmossdk.io/core v0.5.1 // indirect - cosmossdk.io/depinject v1.0.0-alpha.3 // indirect - cosmossdk.io/errors v1.0.0-beta.7 // indirect - cosmossdk.io/log v1.1.0 // indirect - cosmossdk.io/tools/rosetta v0.2.1 // indirect + cloud.google.com/go/iam v1.1.5 // indirect + cloud.google.com/go/storage v1.35.1 // indirect + cosmossdk.io/api v0.7.2 // indirect + cosmossdk.io/client/v2 v2.0.0-beta.1 // indirect + cosmossdk.io/collections v0.4.0 // indirect + cosmossdk.io/core v0.11.0 // indirect + cosmossdk.io/depinject v1.0.0-alpha.4 // indirect + cosmossdk.io/log v1.3.0 // indirect + cosmossdk.io/store v1.0.2 // indirect + cosmossdk.io/x/circuit v0.1.0 // indirect + cosmossdk.io/x/evidence v0.1.0 // indirect + cosmossdk.io/x/feegrant v0.1.0 // indirect + cosmossdk.io/x/nft v0.1.0 // indirect + cosmossdk.io/x/tx v0.13.0 // indirect + cosmossdk.io/x/upgrade v0.1.0 // indirect filippo.io/edwards25519 v1.0.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/keyring v1.2.1 // indirect - github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect - github.com/CosmWasm/wasmd v0.40.0 // indirect - github.com/CosmWasm/wasmvm v1.2.3 // indirect - github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect + github.com/CosmWasm/wasmd v0.50.0 // indirect + github.com/CosmWasm/wasmvm v1.5.2 // indirect + github.com/DataDog/datadog-go v3.2.0+incompatible // indirect + github.com/DataDog/zstd v1.5.5 // indirect github.com/aead/siphash v1.0.1 // indirect - github.com/andybalholm/brotli v1.0.3 // indirect - github.com/armon/go-metrics v0.4.1 // indirect - github.com/aws/aws-sdk-go v1.44.203 // indirect + github.com/aws/aws-sdk-go v1.44.312 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect + github.com/bits-and-blooms/bitset v1.8.0 // indirect github.com/boljen/go-bitmap v0.0.0-20151001105940-23cd2fb0ce7d // indirect - github.com/btcsuite/btcd/btcutil/psbt v1.1.8 // indirect + github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect - github.com/btcsuite/btcwallet v0.16.10-0.20230621165747-9c21f464ce13 // indirect - github.com/btcsuite/btcwallet/wallet/txauthor v1.3.2 // indirect - github.com/btcsuite/btcwallet/wallet/txrules v1.2.0 // indirect - github.com/btcsuite/btcwallet/wallet/txsizes v1.2.3 // indirect - github.com/btcsuite/btcwallet/walletdb v1.4.0 // indirect - github.com/btcsuite/btcwallet/wtxmgr v1.5.0 // indirect - github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd // indirect - github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 // indirect - github.com/btcsuite/winsvc v1.0.0 // indirect github.com/cenkalti/backoff/v4 v4.2.0 // indirect github.com/cespare/xxhash v1.1.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/chzyer/readline v1.5.1 // indirect github.com/cockroachdb/apd/v2 v2.0.2 // indirect - github.com/coinbase/rosetta-sdk-go/types v1.0.0 // indirect - github.com/cometbft/cometbft-db v0.8.0 // indirect - github.com/confio/ics23/go v0.9.0 // indirect - github.com/coreos/go-semver v0.3.0 // indirect + github.com/cockroachdb/errors v1.11.1 // indirect + github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect + github.com/cockroachdb/pebble v0.0.0-20231102162011-844f0582c2eb // indirect + github.com/cockroachdb/redact v1.1.5 // indirect + github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect + github.com/cometbft/cometbft v0.38.5 // indirect + github.com/cometbft/cometbft-db v0.9.1 // indirect + github.com/consensys/bavard v0.1.13 // indirect + github.com/consensys/gnark-crypto v0.12.1 // indirect github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect - github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/cosmos/btcutil v1.0.5 // indirect + github.com/cosmos/cosmos-db v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect - github.com/cosmos/iavl v0.20.0 // indirect - github.com/cosmos/ibc-go/v7 v7.2.0 // indirect + github.com/cosmos/iavl v1.0.0 // indirect + github.com/cosmos/ibc-go/modules/capability v1.0.0 // indirect + github.com/cosmos/ibc-go/v8 v8.0.0 // indirect github.com/cosmos/ics23/go v0.10.0 // indirect - github.com/cosmos/ledger-cosmos-go v0.12.2 // indirect - github.com/cosmos/rosetta-sdk-go v0.10.0 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect - github.com/creachadair/taskgroup v0.4.2 // indirect + github.com/cosmos/ledger-cosmos-go v0.13.3 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect + github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect github.com/danieljoos/wincred v1.1.2 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/decred/dcrd/crypto/blake256 v1.0.1 // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect - github.com/decred/dcrd/lru v1.0.0 // indirect github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect github.com/dgraph-io/badger/v2 v2.2007.4 // indirect github.com/dgraph-io/ristretto v0.1.1 // indirect github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect - github.com/docker/distribution v2.8.2+incompatible // indirect - github.com/dsnet/compress v0.0.1 // indirect + github.com/distribution/reference v0.5.0 // indirect + github.com/docker/docker v23.0.8+incompatible // indirect github.com/dustin/go-humanize v1.0.1 // indirect - github.com/dvsekhvalnov/jose2go v1.5.0 // indirect - github.com/ethereum/go-ethereum v1.11.3 // indirect - github.com/felixge/httpsnoop v1.0.2 // indirect - github.com/fergusstrange/embedded-postgres v1.10.0 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/go-errors/errors v1.0.1 // indirect + github.com/dvsekhvalnov/jose2go v1.6.0 // indirect + github.com/emicklei/dot v1.6.0 // indirect + github.com/ethereum/c-kzg-4844 v0.4.0 // indirect + github.com/ethereum/go-ethereum v1.13.5 // indirect + github.com/fatih/color v1.15.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/getsentry/sentry-go v0.25.0 // indirect github.com/go-kit/kit v0.12.0 // indirect github.com/go-kit/log v0.2.1 // indirect github.com/go-logfmt/logfmt v0.6.0 // indirect - github.com/go-logr/logr v1.2.3 // indirect - github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-stack/stack v1.8.1 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gogo/googleapis v1.4.1 // indirect - github.com/golang-jwt/jwt/v4 v4.4.2 // indirect - github.com/golang/glog v1.1.0 // indirect + github.com/golang/glog v1.2.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/golang/snappy v0.0.4 // indirect + github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/btree v1.1.2 // indirect - github.com/google/go-cmp v0.5.9 // indirect + github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/orderedcode v0.0.1 // indirect - github.com/google/s2a-go v0.1.3 // indirect - github.com/google/uuid v1.3.0 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect - github.com/googleapis/gax-go/v2 v2.8.0 // indirect - github.com/gorilla/handlers v1.5.1 // indirect - github.com/gorilla/mux v1.8.0 // indirect + github.com/google/s2a-go v0.1.7 // indirect + github.com/google/uuid v1.4.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect + github.com/googleapis/gax-go/v2 v2.12.0 // indirect + github.com/gorilla/handlers v1.5.2 // indirect + github.com/gorilla/mux v1.8.1 // indirect github.com/gorilla/websocket v1.5.0 // indirect - github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect - github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect + github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.5.0 // indirect github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect github.com/gtank/merlin v0.1.1 // indirect - github.com/gtank/ristretto255 v0.1.2 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-getter v1.7.1 // indirect + github.com/hashicorp/go-getter v1.7.2 // indirect + github.com/hashicorp/go-hclog v1.5.0 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect + github.com/hashicorp/go-metrics v0.5.1 // indirect + github.com/hashicorp/go-plugin v1.5.2 // indirect github.com/hashicorp/go-safetemp v1.0.0 // indirect - github.com/hashicorp/go-uuid v1.0.2 // indirect github.com/hashicorp/go-version v1.6.0 // indirect - github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect + github.com/hashicorp/golang-lru v1.0.2 // indirect github.com/hashicorp/hcl v1.0.0 // indirect + github.com/hashicorp/yamux v0.1.1 // indirect github.com/hdevalence/ed25519consensus v0.1.0 // indirect - github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e // indirect - github.com/holiman/uint256 v1.2.0 // indirect + github.com/holiman/uint256 v1.2.3 // indirect github.com/huandu/skiplist v1.2.0 // indirect + github.com/iancoleman/strcase v0.3.0 // indirect github.com/improbable-eng/grpc-web v0.15.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/jackc/chunkreader/v2 v2.0.1 // indirect - github.com/jackc/pgconn v1.10.0 // indirect - github.com/jackc/pgio v1.0.0 // indirect - github.com/jackc/pgpassfile v1.0.0 // indirect - github.com/jackc/pgproto3/v2 v2.1.1 // indirect - github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect - github.com/jackc/pgtype v1.8.1 // indirect - github.com/jackc/pgx/v4 v4.13.0 // indirect github.com/jinzhu/copier v0.3.5 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect - github.com/jonboulle/clockwork v0.2.2 // indirect - github.com/jrick/logrotate v1.0.0 // indirect - github.com/json-iterator/go v1.1.12 // indirect - github.com/juju/clock v1.0.3 // indirect - github.com/juju/errors v1.0.0 // indirect - github.com/juju/loggo v1.0.0 // indirect - github.com/juju/testing v1.0.2 // indirect - github.com/juju/utils/v3 v3.0.2 // indirect - github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect + github.com/juju/fslock v0.0.0-20160525022230-4d5c94c67b4b // indirect github.com/kkdai/bstream v1.0.0 // indirect - github.com/klauspost/compress v1.16.3 // indirect - github.com/klauspost/pgzip v1.2.5 // indirect + github.com/klauspost/compress v1.17.4 // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/kr/text v0.2.0 // indirect github.com/lib/pq v1.10.7 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect - github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf // indirect - github.com/lightninglabs/neutrino v0.15.0 // indirect - github.com/lightninglabs/neutrino/cache v1.1.1 // indirect - github.com/lightningnetwork/lightning-onion v1.2.1-0.20221202012345-ca23184850a1 // indirect - github.com/lightningnetwork/lnd/clock v1.1.0 // indirect - github.com/lightningnetwork/lnd/healthcheck v1.2.2 // indirect - github.com/lightningnetwork/lnd/kvdb v1.4.1 // indirect - github.com/lightningnetwork/lnd/queue v1.1.0 // indirect - github.com/lightningnetwork/lnd/ticker v1.1.0 // indirect - github.com/lightningnetwork/lnd/tlv v1.1.0 // indirect - github.com/lightningnetwork/lnd/tor v1.1.0 // indirect - github.com/linxGnu/grocksdb v1.7.16 // indirect - github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796 // indirect + github.com/linxGnu/grocksdb v1.8.6 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/manifoldco/promptui v0.9.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.18 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect - github.com/mholt/archiver/v3 v3.5.0 // indirect - github.com/miekg/dns v1.1.43 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect github.com/minio/highwayhash v1.0.2 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/mtibben/percent v0.2.1 // indirect - github.com/nwaples/rardecode v1.1.2 // indirect + github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a // indirect + github.com/oklog/run v1.1.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/pelletier/go-toml/v2 v2.0.8 // indirect - github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect - github.com/pierrec/lz4/v4 v4.1.8 // indirect + github.com/pelletier/go-toml/v2 v2.1.0 // indirect + github.com/petermattis/goid v0.0.0-20230904192822-1876fd5063bc // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_golang v1.15.0 // indirect - github.com/prometheus/client_model v0.3.0 // indirect - github.com/prometheus/common v0.42.0 // indirect - github.com/prometheus/procfs v0.9.0 // indirect - github.com/rakyll/statik v0.1.7 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/client_golang v1.17.0 // indirect + github.com/prometheus/client_model v0.5.0 // indirect + github.com/prometheus/common v0.45.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect - github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect - github.com/rogpeppe/fastuuid v1.2.0 // indirect + github.com/rogpeppe/go-internal v1.11.0 // indirect github.com/rs/cors v1.8.3 // indirect - github.com/rs/zerolog v1.29.1 // indirect + github.com/rs/zerolog v1.31.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sasha-s/go-deadlock v0.3.1 // indirect - github.com/soheilhy/cmux v0.1.5 // indirect - github.com/spf13/afero v1.9.5 // indirect - github.com/spf13/cast v1.5.1 // indirect - github.com/spf13/cobra v1.7.0 // indirect - github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.11.0 // indirect + github.com/spf13/cast v1.6.0 // indirect + github.com/spf13/cobra v1.8.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/spf13/viper v1.16.0 // indirect - github.com/stretchr/objx v0.5.0 // indirect - github.com/subosito/gotenv v1.4.2 // indirect - github.com/supranational/blst v0.3.8 // indirect + github.com/spf13/viper v1.18.2 // indirect + github.com/strangelove-ventures/cometbft v0.37.3-0.20231004194858-c01e8d5bcac3 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + github.com/supranational/blst v0.3.11 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect github.com/tendermint/go-amino v0.16.0 // indirect - github.com/tidwall/btree v1.6.0 // indirect - github.com/tklauser/go-sysconf v0.3.10 // indirect - github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 // indirect + github.com/tidwall/btree v1.7.0 // indirect github.com/tyler-smith/go-bip39 v1.1.0 // indirect github.com/ulikunitz/xz v0.5.11 // indirect - github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect - github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect - github.com/zondax/hid v0.9.1 // indirect - github.com/zondax/ledger-go v0.14.1 // indirect - go.etcd.io/etcd/api/v3 v3.5.9 // indirect - go.etcd.io/etcd/client/pkg/v3 v3.5.9 // indirect - go.etcd.io/etcd/client/v2 v2.305.7 // indirect - go.etcd.io/etcd/client/v3 v3.5.9 // indirect - go.etcd.io/etcd/pkg/v3 v3.5.7 // indirect - go.etcd.io/etcd/raft/v3 v3.5.7 // indirect - go.etcd.io/etcd/server/v3 v3.5.7 // indirect + github.com/zondax/hid v0.9.2 // indirect + github.com/zondax/ledger-go v0.14.3 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.36.3 // indirect - go.opentelemetry.io/otel v1.11.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.1 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.0.1 // indirect - go.opentelemetry.io/otel/sdk v1.0.1 // indirect - go.opentelemetry.io/otel/trace v1.11.0 // indirect - go.opentelemetry.io/proto/otlp v0.9.0 // indirect - go.uber.org/multierr v1.8.0 // indirect - golang.org/x/crypto v0.9.0 // indirect - golang.org/x/mod v0.8.0 // indirect - golang.org/x/net v0.10.0 // indirect - golang.org/x/oauth2 v0.8.0 // indirect - golang.org/x/sys v0.8.0 // indirect - golang.org/x/term v0.8.0 // indirect - golang.org/x/text v0.9.0 // indirect - golang.org/x/time v0.1.0 // indirect - golang.org/x/tools v0.6.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/crypto v0.18.0 // indirect + golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect + golang.org/x/mod v0.14.0 // indirect + golang.org/x/net v0.20.0 // indirect + golang.org/x/oauth2 v0.15.0 // indirect + golang.org/x/sync v0.5.0 // indirect + golang.org/x/sys v0.16.0 // indirect + golang.org/x/term v0.16.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect - google.golang.org/api v0.122.0 // indirect - google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect - gopkg.in/errgo.v1 v1.0.1 // indirect + google.golang.org/api v0.153.0 // indirect + google.golang.org/appengine v1.6.8 // indirect + google.golang.org/genproto v0.0.0-20231211222908-989df2bf70f3 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20231120223509-83a465c0220f // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect - gopkg.in/macaroon-bakery.v2 v2.0.1 // indirect - gopkg.in/macaroon.v2 v2.0.0 // indirect - gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - lukechampine.com/uint128 v1.2.0 // indirect - modernc.org/cc/v3 v3.40.0 // indirect - modernc.org/ccgo/v3 v3.16.13 // indirect - modernc.org/libc v1.22.2 // indirect - modernc.org/mathutil v1.5.0 // indirect - modernc.org/memory v1.4.0 // indirect - modernc.org/opt v0.1.3 // indirect - modernc.org/sqlite v1.20.3 // indirect - modernc.org/strutil v1.1.3 // indirect - modernc.org/token v1.0.1 // indirect + gotest.tools/v3 v3.5.1 // indirect nhooyr.io/websocket v1.8.6 // indirect - pgregory.net/rapid v0.5.5 // indirect - sigs.k8s.io/yaml v1.3.0 // indirect + pgregory.net/rapid v1.1.0 // indirect + rsc.io/tmplfunc v0.0.3 // indirect + sigs.k8s.io/yaml v1.4.0 // indirect ) replace ( - github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20230914082434-aece8a12b91c - github.com/cosmos/ibc-go/v7 => github.com/babylonchain/ibc-go/v7 v7.0.0-20230726130104-6d9787ab5b61 + // use cosmos fork of keyring + github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0 github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 ) diff --git a/go.sum b/go.sum index 6e657cdf..ffc99b3b 100644 --- a/go.sum +++ b/go.sum @@ -3,7 +3,6 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= @@ -16,7 +15,6 @@ cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOY cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= @@ -32,8 +30,8 @@ cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w9 cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU= cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA= -cloud.google.com/go v0.110.0 h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys= -cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= +cloud.google.com/go v0.110.10 h1:LXy9GEO+timppncPIAZoOj3l58LIU9k+kn48AN7IO3Y= +cloud.google.com/go v0.110.10/go.mod h1:v1OoFqYxiBkUrruItNM3eT4lLByNjxmJSV/xDKJNnic= cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI= @@ -70,8 +68,8 @@ cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= -cloud.google.com/go/compute v1.19.1 h1:am86mquDUgjGNWxiGn+5PGLbmgiWXlE/yNWpIpNvuXY= -cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE= +cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= +cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= @@ -111,13 +109,12 @@ cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y97 cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc= cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc= -cloud.google.com/go/iam v0.13.0 h1:+CmB+K0J/33d0zSQ9SlFWUeCCEn5XJA0ZMZ3pHE9u8k= -cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0= +cloud.google.com/go/iam v1.1.5 h1:1jTsCu4bcsNsE4iiqNT5SHwrDRCfRmIaaaVFhRveTJI= +cloud.google.com/go/iam v1.1.5/go.mod h1:rB6P/Ic3mykPbFio+vo7403drjlgvoWfYpJhMXEbzv8= cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic= cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI= cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8= cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08= -cloud.google.com/go/longrunning v0.4.1 h1:v+yFJOfKC3yZdY6ZUI933pIYdhyhV8S3NpWrXWmg7jM= cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4= cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w= cloud.google.com/go/memcache v1.4.0/go.mod h1:rTOfiGZtJX1AaFUrOgsMHX5kAzaTQ8azHiuDoTPzNsE= @@ -171,12 +168,11 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo 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= -cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= -cloud.google.com/go/storage v1.29.0 h1:6weCgzRvMg7lzuUurI4697AqIRPU1SvzHhynwpW31jI= -cloud.google.com/go/storage v1.29.0/go.mod h1:4puEjyTKnku6gfKoTfNOU/W+a9JyuVNxjpS5GBrB8h4= +cloud.google.com/go/storage v1.35.1 h1:B59ahL//eDfx2IIKFBeT5Atm9wnNmj3+8xG/W4WB//w= +cloud.google.com/go/storage v1.35.1/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8= cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw= cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g= cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU= @@ -188,92 +184,102 @@ cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xX cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= -cosmossdk.io/api v0.3.1 h1:NNiOclKRR0AOlO4KIqeaG6PS6kswOMhHD0ir0SscNXE= -cosmossdk.io/api v0.3.1/go.mod h1:DfHfMkiNA2Uhy8fj0JJlOCYOBp4eWUUJ1te5zBGNyIw= -cosmossdk.io/core v0.5.1 h1:vQVtFrIYOQJDV3f7rw4pjjVqc1id4+mE0L9hHP66pyI= -cosmossdk.io/core v0.5.1/go.mod h1:KZtwHCLjcFuo0nmDc24Xy6CRNEL9Vl/MeimQ2aC7NLE= -cosmossdk.io/depinject v1.0.0-alpha.3 h1:6evFIgj//Y3w09bqOUOzEpFj5tsxBqdc5CfkO7z+zfw= -cosmossdk.io/depinject v1.0.0-alpha.3/go.mod h1:eRbcdQ7MRpIPEM5YUJh8k97nxHpYbc3sMUnEtt8HPWU= -cosmossdk.io/errors v1.0.0-beta.7 h1:gypHW76pTQGVnHKo6QBkb4yFOJjC+sUGRc5Al3Odj1w= -cosmossdk.io/errors v1.0.0-beta.7/go.mod h1:mz6FQMJRku4bY7aqS/Gwfcmr/ue91roMEKAmDUDpBfE= -cosmossdk.io/log v1.1.0 h1:v0ogPHYeTzPcBTcPR1A3j1hkei4pZama8kz8LKlCMv0= -cosmossdk.io/log v1.1.0/go.mod h1:6zjroETlcDs+mm62gd8Ig7mZ+N+fVOZS91V17H+M4N4= -cosmossdk.io/math v1.0.1 h1:Qx3ifyOPaMLNH/89WeZFH268yCvU4xEcnPLu3sJqPPg= -cosmossdk.io/math v1.0.1/go.mod h1:Ygz4wBHrgc7g0N+8+MrnTfS9LLn9aaTGa9hKopuym5k= -cosmossdk.io/tools/rosetta v0.2.1 h1:ddOMatOH+pbxWbrGJKRAawdBkPYLfKXutK9IETnjYxw= -cosmossdk.io/tools/rosetta v0.2.1/go.mod h1:Pqdc1FdvkNV3LcNIkYWt2RQY6IP1ge6YWZk8MhhO9Hw= +cosmossdk.io/api v0.7.2 h1:BO3i5fvKMKvfaUiMkCznxViuBEfyWA/k6w2eAF6q1C4= +cosmossdk.io/api v0.7.2/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= +cosmossdk.io/client/v2 v2.0.0-beta.1 h1:XkHh1lhrLYIT9zKl7cIOXUXg2hdhtjTPBUfqERNA1/Q= +cosmossdk.io/client/v2 v2.0.0-beta.1/go.mod h1:JEUSu9moNZQ4kU3ir1DKD5eU4bllmAexrGWjmb9k8qU= +cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= +cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= +cosmossdk.io/core v0.11.0 h1:vtIafqUi+1ZNAE/oxLOQQ7Oek2n4S48SWLG8h/+wdbo= +cosmossdk.io/core v0.11.0/go.mod h1:LaTtayWBSoacF5xNzoF8tmLhehqlA9z1SWiPuNC6X1w= +cosmossdk.io/depinject v1.0.0-alpha.4 h1:PLNp8ZYAMPTUKyG9IK2hsbciDWqna2z1Wsl98okJopc= +cosmossdk.io/depinject v1.0.0-alpha.4/go.mod h1:HeDk7IkR5ckZ3lMGs/o91AVUc7E596vMaOmslGFM3yU= +cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= +cosmossdk.io/errors v1.0.1/go.mod h1:MeelVSZThMi4bEakzhhhE/CKqVv3nOJDA25bIqRDu/U= +cosmossdk.io/log v1.3.0 h1:L0Z0XstClo2kOU4h3V1iDoE5Ji64sg5HLOogzGg67Oo= +cosmossdk.io/log v1.3.0/go.mod h1:HIDyvWLqZe2ovlWabsDN4aPMpY/nUEquAhgfTf2ZzB8= +cosmossdk.io/math v1.2.0 h1:8gudhTkkD3NxOP2YyyJIYYmt6dQ55ZfJkDOaxXpy7Ig= +cosmossdk.io/math v1.2.0/go.mod h1:l2Gnda87F0su8a/7FEKJfFdJrM0JZRXQaohlgJeyQh0= +cosmossdk.io/store v1.0.2 h1:lSg5BTvJBHUDwswNNyeh4K/CbqiHER73VU4nDNb8uk0= +cosmossdk.io/store v1.0.2/go.mod h1:EFtENTqVTuWwitGW1VwaBct+yDagk7oG/axBMPH+FXs= +cosmossdk.io/x/circuit v0.1.0 h1:IAej8aRYeuOMritczqTlljbUVHq1E85CpBqaCTwYgXs= +cosmossdk.io/x/circuit v0.1.0/go.mod h1:YDzblVE8+E+urPYQq5kq5foRY/IzhXovSYXb4nwd39w= +cosmossdk.io/x/evidence v0.1.0 h1:J6OEyDl1rbykksdGynzPKG5R/zm6TacwW2fbLTW4nCk= +cosmossdk.io/x/evidence v0.1.0/go.mod h1:hTaiiXsoiJ3InMz1uptgF0BnGqROllAN8mwisOMMsfw= +cosmossdk.io/x/feegrant v0.1.0 h1:c7s3oAq/8/UO0EiN1H5BIjwVntujVTkYs35YPvvrdQk= +cosmossdk.io/x/feegrant v0.1.0/go.mod h1:4r+FsViJRpcZif/yhTn+E0E6OFfg4n0Lx+6cCtnZElU= +cosmossdk.io/x/nft v0.1.0 h1:VhcsFiEK33ODN27kxKLa0r/CeFd8laBfbDBwYqCyYCM= +cosmossdk.io/x/nft v0.1.0/go.mod h1:ec4j4QAO4mJZ+45jeYRnW7awLHby1JZANqe1hNZ4S3g= +cosmossdk.io/x/tx v0.13.0 h1:8lzyOh3zONPpZv2uTcUmsv0WTXy6T1/aCVDCqShmpzU= +cosmossdk.io/x/tx v0.13.0/go.mod h1:CpNQtmoqbXa33/DVxWQNx5Dcnbkv2xGUhL7tYQ5wUsY= +cosmossdk.io/x/upgrade v0.1.0 h1:z1ZZG4UL9ICTNbJDYZ6jOnF9GdEK9wyoEFi4BUScHXE= +cosmossdk.io/x/upgrade v0.1.0/go.mod h1:/6jjNGbiPCNtmA1N+rBtP601sr0g4ZXuj3yC6ClPCGY= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek= filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= -github.com/99designs/keyring v1.2.1 h1:tYLp1ULvO7i3fI5vE21ReQuj99QFSs7lGm0xWyJo87o= -github.com/99designs/keyring v1.2.1/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= -github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= -github.com/CosmWasm/wasmd v0.40.0 h1:3Vvq1m8dPQdvZR+QJc86VIx6QoWAEVnuHxqBPshJvyo= -github.com/CosmWasm/wasmd v0.40.0/go.mod h1:SuxskRBB7+bpwXGhUXaEfdpjg5WKpdxBy7Tm36VRMUU= -github.com/CosmWasm/wasmvm v1.2.3 h1:OKYlobwmVGbl0eSn0mXoAAjE5hIuXnQCLPjbNd91sVY= -github.com/CosmWasm/wasmvm v1.2.3/go.mod h1:vW/E3h8j9xBQs9bCoijDuawKo9kCtxOaS8N8J7KFtkc= +github.com/ChainSafe/go-schnorrkel v1.0.0 h1:3aDA67lAykLaG1y3AOjs88dMxC88PgUuHRrLeDnvGIM= +github.com/ChainSafe/go-schnorrkel v1.0.0/go.mod h1:dpzHYVxLZcp8pjlV+O+UR8K0Hp/z7vcchBSbMBEhCw4= +github.com/CosmWasm/wasmd v0.50.0 h1:NVaGqCSTRfb9UTDHJwT6nQIWcb6VjlQl88iI+u1+qjE= +github.com/CosmWasm/wasmd v0.50.0/go.mod h1:UjmShW4l9YxaMytwJZ7IB7MWzHiynSZP3DdWrG0FRtk= +github.com/CosmWasm/wasmvm v1.5.2 h1:+pKB1Mz9GZVt1vadxB+EDdD1FOz3dMNjIKq/58/lrag= +github.com/CosmWasm/wasmvm v1.5.2/go.mod h1:Q0bSEtlktzh7W2hhEaifrFp1Erx11ckQZmjq8FLCyys= +github.com/DataDog/datadog-go v3.2.0+incompatible h1:qSG2N4FghB1He/r2mFrWKCaL7dXCilEuNEeAn20fdD4= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= +github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= +github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= -github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= -github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= -github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= -github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= -github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o= +github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= +github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= +github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40= +github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/adlio/schema v1.3.3 h1:oBJn8I02PyTB466pZO1UZEn1TV5XLlifBSyMrmHl/1I= -github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY= -github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA= +github.com/adlio/schema v1.3.3/go.mod h1:1EsRssiv9/Ce2CMzq5DoL7RiMshhuigQxrR4DMV9fHg= github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= -github.com/alecthomas/participle/v2 v2.0.0-alpha7 h1:cK4vjj0VSgb3lN1nuKA5F7dw+1s1pWBe5bx7nNCnN+c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 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/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= -github.com/andybalholm/brotli v1.0.3 h1:fpcw+r1N1h0Poc1F/pHbW40cUm/lMEQslZtCkBQ0UnM= -github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= -github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= -github.com/avast/retry-go/v4 v4.3.3 h1:G56Bp6mU0b5HE1SkaoVjscZjlQb0oy4mezwY/cGH19w= -github.com/avast/retry-go/v4 v4.3.3/go.mod h1:rg6XFaiuFYII0Xu3RDbZQkxCofFwruZKW8oEF1jpWiU= +github.com/avast/retry-go/v4 v4.5.1 h1:AxIx0HGi4VZ3I02jr78j5lZ3M6x1E0Ivxa6b0pUUh7o= +github.com/avast/retry-go/v4 v4.5.1/go.mod h1:/sipNsvNB3RRuT5iNcb6h73nw3IBmXJ/H3XrCQYSOpc= github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= -github.com/aws/aws-sdk-go v1.44.203 h1:pcsP805b9acL3wUqa4JR2vg1k2wnItkDYNvfmcy6F+U= -github.com/aws/aws-sdk-go v1.44.203/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go v1.44.312 h1:llrElfzeqG/YOLFFKjg1xNpZCFJ2xraIi3PqSuP+95k= +github.com/aws/aws-sdk-go v1.44.312/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= -github.com/babylonchain/babylon-private v0.0.0-20230914082434-aece8a12b91c h1:n4XLSd0DZapEdoiekdwlDvhjknaSG/7AOLhg8eW53Wg= -github.com/babylonchain/babylon-private v0.0.0-20230914082434-aece8a12b91c/go.mod h1:zQsbXiE3LBanEB0kZ8LfiVoP7TMzfVlPrSP3cyEHako= -github.com/babylonchain/ibc-go/v7 v7.0.0-20230726130104-6d9787ab5b61 h1:0NPV8yfawKAYrw96b2ZR70QHIAwB1QcKWyf2BWcRvmU= -github.com/babylonchain/ibc-go/v7 v7.0.0-20230726130104-6d9787ab5b61/go.mod h1:OOcjKIRku/j1Xs1RgKK0yvKRrJ5iFuZYMetR1n3yMlc= -github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= +github.com/babylonchain/babylon v0.8.0 h1:QC04LPCFBD0MZyiM3cAjVBlr3CXEZPdhORWPBlO2gaQ= +github.com/babylonchain/babylon v0.8.0/go.mod h1:jR1b+5mA7BkRrXfd/PMHwk7W/RpoeQtunvjal+tKeHY= +github.com/babylonchain/rpc-client v0.8.0 h1:H7VN7dTR1Z6uffRrziFRD9FTj+1Jf3u9gL2RLm3z9Jo= +github.com/babylonchain/rpc-client v0.8.0/go.mod h1:+7IiKHmIAmfM888hPpfAVmGs85yZRxfbJym4swmgKG8= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= 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= @@ -283,62 +289,39 @@ github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 h1:41iFGWnSlI2gVpmOtVTJZNodLdLQLn/KsJqFvXwnd/s= github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bits-and-blooms/bitset v1.8.0 h1:FD+XqgOZDUxxZ8hzoBFuV9+cGWY9CslN6d5MS5JVb4c= +github.com/bits-and-blooms/bitset v1.8.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/boljen/go-bitmap v0.0.0-20151001105940-23cd2fb0ce7d h1:zsO4lp+bjv5XvPTF58Vq+qgmZEYZttJK+CWtSZhKenI= github.com/boljen/go-bitmap v0.0.0-20151001105940-23cd2fb0ce7d/go.mod h1:f1iKL6ZhUWvbk7PdWVmOaak10o86cqMUYEmn1CZNGEI= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= -github.com/btcsuite/btcd v0.22.0-beta.0.20220204213055-eaf0459ff879/go.mod h1:osu7EoKiL36UThEgzYPqdRaxeo0NU8VoXqgcnwpey0g= -github.com/btcsuite/btcd v0.22.0-beta.0.20220207191057-4dc4ff7963b4/go.mod h1:7alexyj/lHlOtr2PJK7L/+HDJZpcGDn/pAU98r7DY08= -github.com/btcsuite/btcd v0.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= -github.com/btcsuite/btcd v0.23.1/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= -github.com/btcsuite/btcd v0.23.3/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= -github.com/btcsuite/btcd v0.23.5-0.20230228185050-38331963bddd h1:v2Bs8yLhwv+8XYU96OOnhZ5BEj8ZlNGownexUO0e80I= -github.com/btcsuite/btcd v0.23.5-0.20230228185050-38331963bddd/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= +github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= +github.com/btcsuite/btcd v0.24.0 h1:gL3uHE/IaFj6fcZSu03SvqPMSx7s/dPzfpG/atRwWdo= +github.com/btcsuite/btcd v0.24.0/go.mod h1:K4IDc1593s8jKXIF7yS7yCTSxrknB9z0STzc2j6XgE4= github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= -github.com/btcsuite/btcd/btcec/v2 v2.1.1/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= -github.com/btcsuite/btcd/btcutil v1.1.1/go.mod h1:nbKlBMNm9FGsdvKvu0essceubPiAcI57pYBNnsLAa34= -github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= -github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= -github.com/btcsuite/btcd/btcutil/psbt v1.1.8 h1:4voqtT8UppT7nmKQkXV+T9K8UyQjKOn2z/ycpmJK8wg= -github.com/btcsuite/btcd/btcutil/psbt v1.1.8/go.mod h1:kA6FLH/JfUx++j9pYU0pyu+Z8XGBQuuTmuKYUf6q7/U= +github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8= +github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 h1:KdUfX2zKommPRa+PD0sWZUyXe9w277ABlgELO7H04IM= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/btcwallet v0.16.10-0.20230621165747-9c21f464ce13 h1:7i0CzK+PP4+Dth9ia/eIBFRw8+K6MT8MfoFqBH43Xts= -github.com/btcsuite/btcwallet v0.16.10-0.20230621165747-9c21f464ce13/go.mod h1:Hl4PP/tSNcgN6himfx/020mYSa19a1qkqTuqQBUU97w= -github.com/btcsuite/btcwallet/wallet/txauthor v1.3.2 h1:etuLgGEojecsDOYTII8rYiGHjGyV5xTqsXi+ZQ715UU= -github.com/btcsuite/btcwallet/wallet/txauthor v1.3.2/go.mod h1:Zpk/LOb2sKqwP2lmHjaZT9AdaKsHPSbNLm2Uql5IQ/0= -github.com/btcsuite/btcwallet/wallet/txrules v1.2.0 h1:BtEN5Empw62/RVnZ0VcJaVtVlBijnLlJY+dwjAye2Bg= -github.com/btcsuite/btcwallet/wallet/txrules v1.2.0/go.mod h1:AtkqiL7ccKWxuLYtZm8Bu8G6q82w4yIZdgq6riy60z0= -github.com/btcsuite/btcwallet/wallet/txsizes v1.2.2/go.mod h1:q08Rms52VyWyXcp5zDc4tdFRKkFgNsMQrv3/LvE1448= -github.com/btcsuite/btcwallet/wallet/txsizes v1.2.3 h1:PszOub7iXVYbtGybym5TGCp9Dv1h1iX4rIC3HICZGLg= -github.com/btcsuite/btcwallet/wallet/txsizes v1.2.3/go.mod h1:q08Rms52VyWyXcp5zDc4tdFRKkFgNsMQrv3/LvE1448= -github.com/btcsuite/btcwallet/walletdb v1.3.5/go.mod h1:oJDxAEUHVtnmIIBaa22wSBPTVcs6hUp5NKWmI8xDwwU= -github.com/btcsuite/btcwallet/walletdb v1.4.0 h1:/C5JRF+dTuE2CNMCO/or5N8epsrhmSM4710uBQoYPTQ= -github.com/btcsuite/btcwallet/walletdb v1.4.0/go.mod h1:oJDxAEUHVtnmIIBaa22wSBPTVcs6hUp5NKWmI8xDwwU= -github.com/btcsuite/btcwallet/wtxmgr v1.5.0 h1:WO0KyN4l6H3JWnlFxfGR7r3gDnlGT7W2cL8vl6av4SU= -github.com/btcsuite/btcwallet/wtxmgr v1.5.0/go.mod h1:TQVDhFxseiGtZwEPvLgtfyxuNUDsIdaJdshvWzR0HJ4= -github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= -github.com/btcsuite/golangcrypto v0.0.0-20150304025918-53f62d9b43e8/go.mod h1:tYvUd8KLhm/oXvUeSEs2VlLghFjQt9+ZaF9ghH0JNjc= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= -github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= -github.com/btcsuite/winsvc v1.0.0 h1:J9B4L7e3oqhXOcm+2IuNApwzQec85lE+QaikUcCs+dk= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= -github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= +github.com/bufbuild/protocompile v0.6.0 h1:Uu7WiSQ6Yj9DbkdnOe7U4mNKp58y9WDMKDn28/ZlunY= +github.com/bufbuild/protocompile v0.6.0/go.mod h1:YNP35qEYoYGme7QMtz5SBCoN4kL4g12jTtjuzRNdjpE= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= @@ -374,86 +357,93 @@ github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= -github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= -github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/cockroachdb/apd/v2 v2.0.2 h1:weh8u7Cneje73dDh+2tEVLUvyBc89iwepWCD8b8034E= github.com/cockroachdb/apd/v2 v2.0.2/go.mod h1:DDxRlzC2lo3/vSlmSoS7JkqbbrARPuFOGr0B9pvN3Gw= -github.com/cockroachdb/apd/v3 v3.1.0 h1:MK3Ow7LH0W8zkd5GMKA1PvS9qG3bWFI95WaVNfyZJ/w= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= -github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5 h1:xD/lrqdvwsc+O2bjSSi3YqY73Ke3LAiSCx49aCesA0E= -github.com/cockroachdb/errors v1.9.1 h1:yFVvsI0VxmRShfawbt/laCIDy/mtTqqnvoNgiy5bEV8= +github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= +github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= +github.com/cockroachdb/errors v1.11.1 h1:xSEW75zKaKCWzR3OfxXUxgrk/NtT4G1MiOv5lWZazG8= +github.com/cockroachdb/errors v1.11.1/go.mod h1:8MUxA3Gi6b25tYlFEBGLf+D8aISL+M4MIpiWMSNRfxw= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= -github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 h1:ytcWPaNPhNoGMWEhDvS3zToKcDpRsLuRolQJBVGdozk= -github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/pebble v0.0.0-20231102162011-844f0582c2eb h1:6Po+YYKT5B5ZXN0wd2rwFBaebM0LufPf8p4zxOd48Kg= +github.com/cockroachdb/pebble v0.0.0-20231102162011-844f0582c2eb/go.mod h1:acMRUGd/BK8AUmQNK3spUCCGzFLZU2bSST3NMXSq2Kc= +github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= +github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/coinbase/rosetta-sdk-go/types v1.0.0 h1:jpVIwLcPoOeCR6o1tU+Xv7r5bMONNbHU7MuEHboiFuA= -github.com/coinbase/rosetta-sdk-go/types v1.0.0/go.mod h1:eq7W2TMRH22GTW0N0beDnN931DW0/WOI1R2sdHNHG4c= -github.com/cometbft/cometbft v0.37.2 h1:XB0yyHGT0lwmJlFmM4+rsRnczPlHoAKFX6K8Zgc2/Jc= -github.com/cometbft/cometbft v0.37.2/go.mod h1:Y2MMMN//O5K4YKd8ze4r9jmk4Y7h0ajqILXbH5JQFVs= -github.com/cometbft/cometbft-db v0.8.0 h1:vUMDaH3ApkX8m0KZvOFFy9b5DZHBAjsnEuo9AKVZpjo= -github.com/cometbft/cometbft-db v0.8.0/go.mod h1:6ASCP4pfhmrCBpfk01/9E1SI29nD3HfVHrY4PG8x5c0= -github.com/confio/ics23/go v0.9.0 h1:cWs+wdbS2KRPZezoaaj+qBleXgUk5WOQFMP3CQFGTr4= -github.com/confio/ics23/go v0.9.0/go.mod h1:4LPZ2NYqnYIVRklaozjNR1FScgDJ2s5Xrp+e/mYVRak= +github.com/cometbft/cometbft v0.38.5 h1:4lOcK5VTPrfbLOhNHmPYe6c7eDXHtBdMCQuKbAfFJdU= +github.com/cometbft/cometbft v0.38.5/go.mod h1:0tqKin+KQs8zDwzYD8rPHzSBIDNPuB4NrwwGDNb/hUg= +github.com/cometbft/cometbft-db v0.9.1 h1:MIhVX5ja5bXNHF8EYrThkG9F7r9kSfv8BX4LWaxWJ4M= +github.com/cometbft/cometbft-db v0.9.1/go.mod h1:iliyWaoV0mRwBJoizElCwwRA9Tf7jZJOURcRZF9m60U= +github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= +github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= +github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= +github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= +github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= -github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f h1:JOrtw2xFKzlg+cbHpyrpLDmnN1HqhBfnX7WDiW7eG2c= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= -github.com/cosmos/cosmos-proto v1.0.0-beta.2 h1:X3OKvWgK9Gsejo0F1qs5l8Qn6xJV/AzgIWR2wZ8Nua8= -github.com/cosmos/cosmos-proto v1.0.0-beta.2/go.mod h1:+XRCLJ14pr5HFEHIUcn51IKXD1Fy3rkEQqt4WqmN4V0= -github.com/cosmos/cosmos-sdk v0.47.3 h1:r0hGmZoAzP2D+MaPaFGHwAaTdFQq3pNpHaUp1BsffbM= -github.com/cosmos/cosmos-sdk v0.47.3/go.mod h1:c4OfLdAykA9zsj1CqrxBRqXzVz48I++JSvIMPSPcEmk= -github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= +github.com/cosmos/cosmos-db v1.0.0 h1:EVcQZ+qYag7W6uorBKFPvX6gRjw6Uq2hIh4hCWjuQ0E= +github.com/cosmos/cosmos-db v1.0.0/go.mod h1:iBvi1TtqaedwLdcrZVYRSSCb6eSy61NLj4UNmdIgs0U= +github.com/cosmos/cosmos-proto v1.0.0-beta.3 h1:VitvZ1lPORTVxkmF2fAp3IiA61xVwArQYKXTdEcpW6o= +github.com/cosmos/cosmos-proto v1.0.0-beta.3/go.mod h1:t8IASdLaAq+bbHbjq4p960BvcTqtwuAxid3b/2rOD6I= +github.com/cosmos/cosmos-sdk v0.50.4-0.20240126152601-c4a2fe2b8987 h1:Pjvcy7wHUoYh253LvNv5Dyx+d3SNkRPsDZH+FytqZ3w= +github.com/cosmos/cosmos-sdk v0.50.4-0.20240126152601-c4a2fe2b8987/go.mod h1:0D9mrUy1eAUMQuvYzf2xvhEPk2ta9w7XH1zcYvyFiuM= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= github.com/cosmos/gogogateway v1.2.0 h1:Ae/OivNhp8DqBi/sh2A8a1D0y638GpL3tkmLQAiKxTE= github.com/cosmos/gogogateway v1.2.0/go.mod h1:iQpLkGWxYcnCdz5iAdLcRBSw3h7NXeOkZ4GUkT+tbFI= github.com/cosmos/gogoproto v1.4.2/go.mod h1:cLxOsn1ljAHSV527CHOtaIP91kK6cCrZETRBrkzItWU= -github.com/cosmos/gogoproto v1.4.10 h1:QH/yT8X+c0F4ZDacDv3z+xE3WU1P1Z3wQoLMBRJoKuI= -github.com/cosmos/gogoproto v1.4.10/go.mod h1:3aAZzeRWpAwr+SS/LLkICX2/kDFyaYVzckBDzygIxek= -github.com/cosmos/iavl v0.20.0 h1:fTVznVlepH0KK8NyKq8w+U7c2L6jofa27aFX6YGlm38= -github.com/cosmos/iavl v0.20.0/go.mod h1:WO7FyvaZJoH65+HFOsDir7xU9FWk2w9cHXNW1XHcl7A= +github.com/cosmos/gogoproto v1.4.11 h1:LZcMHrx4FjUgrqQSWeaGC1v/TeuVFqSLa43CC6aWR2g= +github.com/cosmos/gogoproto v1.4.11/go.mod h1:/g39Mh8m17X8Q/GDEs5zYTSNaNnInBSohtaxzQnYq1Y= +github.com/cosmos/iavl v1.0.0 h1:bw6t0Mv/mVCJvlMTOPHWLs5uUE3BRBfVWCRelOzl+so= +github.com/cosmos/iavl v1.0.0/go.mod h1:CmTGqMnRnucjxbjduneZXT+0vPgNElYvdefjX2q9tYc= +github.com/cosmos/ibc-go/modules/capability v1.0.0 h1:r/l++byFtn7jHYa09zlAdSeevo8ci1mVZNO9+V0xsLE= +github.com/cosmos/ibc-go/modules/capability v1.0.0/go.mod h1:D81ZxzjZAe0ZO5ambnvn1qedsFQ8lOwtqicG6liLBco= +github.com/cosmos/ibc-go/v8 v8.0.0 h1:QKipnr/NGwc+9L7NZipURvmSIu+nw9jOIWTJuDBqOhg= +github.com/cosmos/ibc-go/v8 v8.0.0/go.mod h1:C6IiJom0F3cIQCD5fKwVPDrDK9j/xTu563AWuOmXois= github.com/cosmos/ics23/go v0.10.0 h1:iXqLLgp2Lp+EdpIuwXTYIQU+AiHj9mOC2X9ab++bZDM= github.com/cosmos/ics23/go v0.10.0/go.mod h1:ZfJSmng/TBNTBkFemHHHj5YY7VAU/MBU980F4VU1NG0= -github.com/cosmos/ledger-cosmos-go v0.12.2 h1:/XYaBlE2BJxtvpkHiBm97gFGSGmYGKunKyF3nNqAXZA= -github.com/cosmos/ledger-cosmos-go v0.12.2/go.mod h1:ZcqYgnfNJ6lAXe4HPtWgarNEY+B74i+2/8MhZw4ziiI= -github.com/cosmos/relayer/v2 v2.4.1 h1:oQpx5S1f2qCtWIevgmM7tczEvuSurBF37yOXokwwqMg= -github.com/cosmos/relayer/v2 v2.4.1/go.mod h1:g74emrKs5e55PDjBJj9sG+Es5EtUFN5S9jMpDH9gHJU= -github.com/cosmos/rosetta-sdk-go v0.10.0 h1:E5RhTruuoA7KTIXUcMicL76cffyeoyvNybzUGSKFTcM= -github.com/cosmos/rosetta-sdk-go v0.10.0/go.mod h1:SImAZkb96YbwvoRkzSMQB6noNJXFgWl/ENIznEoYQI4= +github.com/cosmos/keyring v1.2.0 h1:8C1lBP9xhImmIabyXW4c3vFjjLiBdGCmfLUfeZlV1Yo= +github.com/cosmos/keyring v1.2.0/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA= +github.com/cosmos/ledger-cosmos-go v0.13.3 h1:7ehuBGuyIytsXbd4MP43mLeoN2LTOEnk5nvue4rK+yM= +github.com/cosmos/ledger-cosmos-go v0.13.3/go.mod h1:HENcEP+VtahZFw38HZ3+LS3Iv5XV6svsnkk9vdJtLr8= +github.com/cosmos/relayer/v2 v2.4.3-0.20231227002143-820caf5ab483 h1:l8Elru92qhdzwJdOYDEKcDfFPEdPPFH5jTRL7OZWGMA= +github.com/cosmos/relayer/v2 v2.4.3-0.20231227002143-820caf5ab483/go.mod h1:eBKSRbCx2zhqpvzZG4+HcDacWz4BywqgcLBkiyzuGYI= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA= +github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= github.com/creachadair/taskgroup v0.4.2 h1:jsBLdAJE42asreGss2xZGZ8fJra7WtwnHWeJFxv2Li8= github.com/creachadair/taskgroup v0.4.2/go.mod h1:qiXUOSrbwAY3u0JPGTzObbE3yf9hcXHDKBZ2ZjpCbgM= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= -github.com/cucumber/common/gherkin/go/v22 v22.0.0 h1:4K8NqptbvdOrjL9DEea6HFjSpbdT9+Q5kgLpmmsHYl0= -github.com/cucumber/common/messages/go/v17 v17.1.1 h1:RNqopvIFyLWnKv0LfATh34SWBhXeoFTJnSrgm9cT/Ts= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0= github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= -github.com/decred/dcrd/lru v1.0.0 h1:Kbsb1SFDsIlaupWPwsPp+dkxiBY1frcS07PCPgotKz8= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= @@ -466,23 +456,26 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= -github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= +github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/docker v23.0.8+incompatible h1:z4ZCIwfqHgOEwhxmAWugSL1PFtPQmLP60EVhJYJPaX8= +github.com/docker/docker v23.0.8+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= -github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q= -github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo= -github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= -github.com/dvsekhvalnov/jose2go v1.5.0 h1:3j8ya4Z4kMCwT5nXIKFSV84YS+HdqSSO0VsTQxaLAeM= -github.com/dvsekhvalnov/jose2go v1.5.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= +github.com/dvsekhvalnov/jose2go v1.6.0 h1:Y9gnSnP4qEI0+/uQkHvFXeD2PLPJeXEL+ySMEA2EjTY= +github.com/dvsekhvalnov/jose2go v1.6.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/emicklei/dot v1.6.0 h1:vUzuoVE8ipzS7QkES4UfxdpCwdU2U97m2Pb2tQCoYRY= +github.com/emicklei/dot v1.6.0/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -494,32 +487,36 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.m github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v0.10.1 h1:c0g45+xCJhdgFGw7a5QAfdS4byAbud7miNWJ1WwEVf8= -github.com/ethereum/go-ethereum v1.11.3 h1:uuBkYUJW9aY5JYi3+sqLHz+XWyo5fmn/ab9XcbtVDTU= -github.com/ethereum/go-ethereum v1.11.3/go.mod h1:rBUvAl5cdVrAei9q5lgOU7RSEuPJk1nlBDnS/YSoKQE= +github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY= +github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= +github.com/ethereum/go-ethereum v1.13.5 h1:U6TCRciCqZRe4FPXmy1sMGxTfuk8P7u2UoinF3VbaFk= +github.com/ethereum/go-ethereum v1.13.5/go.mod h1:yMTu38GSuyxaYzQMViqNmQ1s3cE84abZexQmTgenWk0= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/felixge/httpsnoop v1.0.2 h1:+nS9g82KMXccJ/wp0zyRW9ZBHFETmMGtkk+2CTTrW4o= -github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/fergusstrange/embedded-postgres v1.10.0 h1:YnwF6xAQYmKLAXXrrRx4rHDLih47YJwVPvg8jeKfdNg= -github.com/fergusstrange/embedded-postgres v1.10.0/go.mod h1:a008U8/Rws5FtIOTGYDYa7beVWsT3qVKyqExqYYjL+c= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= -github.com/frankban/quicktest v1.2.2/go.mod h1:Qh/WofXFeiAFII1aEBu529AtJo6Zg2VHscnEsbBnJ20= -github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/getsentry/sentry-go v0.25.0 h1:q6Eo+hS+yoJlTO3uu/azhQadsD8V+jQn2D8VvX1eOyI= +github.com/getsentry/sentry-go v0.25.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14= github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= -github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= -github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +github.com/gin-gonic/gin v1.8.1 h1:4+fr/el88TOO3ewCmQr8cx/CtZ/umlIRIs5M4NTNjf8= +github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk= +github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= +github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -536,46 +533,44 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= -github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= +github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= +github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= -github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY= +github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= +github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ= +github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= -github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= -github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= +github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= +github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= +github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= -github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gofrs/uuid v4.3.0+incompatible h1:CaSVZxm5B+7o45rtab4jC2G37WGYX1zQfuU2i6DSvnc= +github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/googleapis v1.4.1-0.20201022092350-68b0159b7869/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0= github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= -github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs= -github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v0.0.0-20210429001901-424d2337a529/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= -github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= +github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68= +github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -613,16 +608,15 @@ github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.2.1-0.20190312032427-6f77996f0c42/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 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= @@ -636,8 +630,9 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= @@ -648,6 +643,7 @@ github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIG github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw= +github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us= github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -659,25 +655,25 @@ github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/s2a-go v0.1.3 h1:FAgZmpLl/SXurPEZyCMPBIiiYeTbqfjlbdnCNTAkbGE= -github.com/google/s2a-go v0.1.3/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= +github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= +github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= +github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= -github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k= -github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= +github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= +github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= @@ -687,36 +683,31 @@ github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99 github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo= github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= -github.com/googleapis/gax-go/v2 v2.8.0 h1:UBtEZqx1bjXtOQ5BVTkuYghXrr3N4V123VKJK67vJZc= -github.com/googleapis/gax-go/v2 v2.8.0/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= +github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= +github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= -github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= -github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= +github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE= +github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= +github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= +github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= +github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.5.0 h1:ajue7SzQMywqRjg2fK7dcpc0QhFGpTR2plWfV4EZWR4= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.5.0/go.mod h1:r1hZAcvfFXuYmcKyCJI9wlyOPIZUJl6FCB8Cpca/NLE= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= -github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= github.com/gtank/merlin v0.1.1 h1:eQ90iG7K9pOhtereWsmyRJ6RAwcP4tHTDBHXNg+u5is= github.com/gtank/merlin v0.1.1/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= github.com/gtank/ristretto255 v0.1.2 h1:JEqUCPA1NvLq5DwYtuzigd7ss8fwbYay9fi4/5uMzcc= @@ -728,13 +719,19 @@ github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-getter v1.7.1 h1:SWiSWN/42qdpR0MdhaOc/bLR48PLuP1ZQtYLRlM69uY= -github.com/hashicorp/go-getter v1.7.1/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744= +github.com/hashicorp/go-getter v1.7.2 h1:uJDtyXwEfalmp1PqdxuhZqrNkUyClZAhVeZYTArbqkg= +github.com/hashicorp/go-getter v1.7.2/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744= +github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= +github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-metrics v0.5.1 h1:rfPwUqFU6uZXNvGl4hzjY8LEBsqFVU4si1H9/Hqck/U= +github.com/hashicorp/go-metrics v0.5.1/go.mod h1:KEjodfebIOuBYSAe/bHTm+HChmKSxAOXPBieMLYozDE= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-plugin v1.5.2 h1:aWv8eimFqWlsEiMrYZdPYl+FdHaBJSN4AWwGWfT1G2Y= +github.com/hashicorp/go-plugin v1.5.2/go.mod h1:w1sAEES3g3PuV/RzUrgow20W2uErMly84hhD3um1WL4= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo= @@ -751,27 +748,30 @@ github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09 github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= -github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= +github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= +github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/hdevalence/ed25519consensus v0.1.0 h1:jtBwzzcHuTmFrQN6xQZn6CQEO/V9f7HsjsjeEZ6auqU= github.com/hdevalence/ed25519consensus v0.1.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3sus+7FctEyM4RqDxYNzo= -github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e h1:pIYdhNkDh+YENVNi3gto8n9hAmRxKxoar0iE6BLucjw= -github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e/go.mod h1:j9cQbcqHQujT0oKJ38PylVfqohClLr3CvDC+Qcg+lhU= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= -github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM= -github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= +github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= +github.com/holiman/uint256 v1.2.3 h1:K8UWO1HUJpRMXBxbmaY1Y8IAMZC/RsKB+ArEnnK4l5o= +github.com/holiman/uint256 v1.2.3/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= +github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2tzCixLaUPQ= @@ -780,56 +780,12 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= -github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= -github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= -github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= -github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= -github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= -github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= -github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= -github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= -github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= -github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= -github.com/jackc/pgconn v1.10.0 h1:4EYhlDVEMsJ30nNj0mmgwIUXoq7e9sMJrVC2ED6QlCU= -github.com/jackc/pgconn v1.10.0/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= -github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= -github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= -github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= -github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c= -github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65 h1:DadwsjnMwFjfWc9y5Wi/+Zz7xoE5ALHsRQlOctkOiHc= -github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= -github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= -github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= -github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= -github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= -github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= -github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= -github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= -github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.1.1 h1:7PQ/4gLoqnl87ZxL7xjO0DR5gYuviDCZxQJsUlFW1eI= -github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg= -github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= -github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= -github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= -github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= -github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= -github.com/jackc/pgtype v1.8.1 h1:9k0IXtdJXHJbyAWQgbWr1lU+MEhPXZz6RIXxfR5oxXs= -github.com/jackc/pgtype v1.8.1/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= -github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= -github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= -github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= -github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= -github.com/jackc/pgx/v4 v4.13.0 h1:JCjhT5vmhMAf/YwBHLvrBn4OGdIQBiFG6ym8Zmdx570= -github.com/jackc/pgx/v4 v4.13.0/go.mod h1:9P4X524sErlaxj0XSGZk7s+LD0eOyu1ZDUrrpznYDF0= -github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc= github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= -github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= +github.com/jhump/protoreflect v1.15.3 h1:6SFRuqU45u9hIZPJAoZ8c28T3nK64BNdp9w6jFonzls= +github.com/jhump/protoreflect v1.15.3/go.mod h1:4ORHmSBmlCW8fh3xHmJMGyul1zNqZK4Elxc8qKP+p1k= github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg= github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= @@ -840,10 +796,7 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfC github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= -github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= 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= @@ -857,133 +810,75 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X github.com/jsternberg/zap-logfmt v1.3.0 h1:z1n1AOHVVydOOVuyphbOKyR4NICDQFiJMn1IK5hVQ5Y= github.com/jsternberg/zap-logfmt v1.3.0/go.mod h1:N3DENp9WNmCZxvkBD/eReWwz1149BK6jEN9cQ4fNwZE= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU= -github.com/juju/clock v1.0.3 h1:yJHIsWXeU8j3QcBdiess09SzfiXRRrsjKPn2whnMeds= -github.com/juju/clock v1.0.3/go.mod h1:HIBvJ8kiV/n7UHwKuCkdYL4l/MDECztHR2sAvWDxxf0= -github.com/juju/errors v1.0.0 h1:yiq7kjCLll1BiaRuNY53MGI0+EQ3rF6GB+wvboZDefM= -github.com/juju/errors v1.0.0/go.mod h1:B5x9thDqx0wIMH3+aLIMP9HjItInYWObRovoCFM5Qe8= github.com/juju/fslock v0.0.0-20160525022230-4d5c94c67b4b h1:FQ7+9fxhyp82ks9vAuyPzG0/vVbWwMwLJ+P6yJI5FN8= github.com/juju/fslock v0.0.0-20160525022230-4d5c94c67b4b/go.mod h1:HMcgvsgd0Fjj4XXDkbjdmlbI505rUPBs6WBMYg2pXks= -github.com/juju/loggo v1.0.0 h1:Y6ZMQOGR9Aj3BGkiWx7HBbIx6zNwNkxhVNOHU2i1bl0= -github.com/juju/loggo v1.0.0/go.mod h1:NIXFioti1SmKAlKNuUwbMenNdef59IF52+ZzuOmHYkg= -github.com/juju/testing v1.0.2 h1:OR90RqCd9CJONxXamZAjLknpZdtqDyxqW8IwCbgw3i4= -github.com/juju/testing v1.0.2/go.mod h1:h3Vd2rzB57KrdsBEy6R7bmSKPzP76BnNavt7i8PerwQ= -github.com/juju/utils/v3 v3.0.2 h1:6Hel0EXKSM4SOQFHfRel74ZvRp4O0QuxSSf3p3W2FNA= -github.com/juju/utils/v3 v3.0.2/go.mod h1:8csUcj1VRkfjNIRzBFWzLFCMLwLqsRWvkmhfVAUwbC4= 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/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/kkdai/bstream v1.0.0 h1:Se5gHwgp2VT2uHfDrkbbgbgEvV9cimLELwrPJctSjg8= github.com/kkdai/bstream v1.0.0/go.mod h1:FDnDOHt5Yx4p3FaHcioFT0QjDOtgUpvjeZqAs+NVZZA= -github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= -github.com/klauspost/compress v1.16.3 h1:XuJt9zzcnaz6a16/OU53ZjWp/v7/42WcR5t2a0PcNQY= -github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= -github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= -github.com/klauspost/pgzip v1.2.4/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= -github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE= -github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= +github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= +github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.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/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= +github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= -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= -github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= -github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf h1:HZKvJUHlcXI/f/O0Avg7t8sqkPo78HFzjmeYFl6DPnc= -github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf/go.mod h1:vxmQPeIQxPf6Jf9rM8R+B4rKBqLA2AjttNxkFBL2Plk= -github.com/lightninglabs/neutrino v0.15.0 h1:yr3uz36fLAq8hyM0TRUVlef1TRNoWAqpmmNlVtKUDtI= -github.com/lightninglabs/neutrino v0.15.0/go.mod h1:pmjwElN/091TErtSE9Vd5W4hpxoG2/+xlb+HoPm9Gug= -github.com/lightninglabs/neutrino/cache v1.1.1 h1:TllWOSlkABhpgbWJfzsrdUaDH2fBy/54VSIB4vVqV8M= -github.com/lightninglabs/neutrino/cache v1.1.1/go.mod h1:XJNcgdOw1LQnanGjw8Vj44CvguYA25IMKjWFZczwZuo= -github.com/lightningnetwork/lightning-onion v1.2.1-0.20221202012345-ca23184850a1 h1:Wm0g70gkcAu2pGpNZwfWPSVOY21j8IyYsNewwK4OkT4= -github.com/lightningnetwork/lightning-onion v1.2.1-0.20221202012345-ca23184850a1/go.mod h1:7dDx73ApjEZA0kcknI799m2O5kkpfg4/gr7N092ojNo= github.com/lightningnetwork/lnd v0.16.4-beta.rc1 h1:L8ktsv1lM5esVtiOlEtOBqU1dCoDckbm0FkcketBskQ= github.com/lightningnetwork/lnd v0.16.4-beta.rc1/go.mod h1:sK9F98TpFuO/fjLCX4jEjc65qr2GZGs8IquVde1N46I= -github.com/lightningnetwork/lnd/clock v1.0.1/go.mod h1:KnQudQ6w0IAMZi1SgvecLZQZ43ra2vpDNj7H/aasemg= -github.com/lightningnetwork/lnd/clock v1.1.0 h1:/yfVAwtPmdx45aQBoXQImeY7sOIEr7IXlImRMBOZ7GQ= -github.com/lightningnetwork/lnd/clock v1.1.0/go.mod h1:KnQudQ6w0IAMZi1SgvecLZQZ43ra2vpDNj7H/aasemg= -github.com/lightningnetwork/lnd/healthcheck v1.2.2 h1:im+qcpgSuteqRCGeorT9yqVXuLrS6A7/acYzGgarMS4= -github.com/lightningnetwork/lnd/healthcheck v1.2.2/go.mod h1:IWY0GChlarRbXFkFDdE4WY5POYJabe/7/H1iCZt4ZKs= -github.com/lightningnetwork/lnd/kvdb v1.4.1 h1:l/nLBPLbdvP/lajMtrFMLzAi5OoLTH3+zUU6SwoEEv8= -github.com/lightningnetwork/lnd/kvdb v1.4.1/go.mod h1:f+F7Da8HTa8MePFsdWvusGRdcmWTgSWykGsVyC02Z5M= -github.com/lightningnetwork/lnd/queue v1.1.0 h1:YpCJjlIvVxN/R7ww2aNiY8ex7U2fucZDLJ67tI3HFx8= -github.com/lightningnetwork/lnd/queue v1.1.0/go.mod h1:YTkTVZCxz8tAYreH27EO3s8572ODumWrNdYW2E/YKxg= -github.com/lightningnetwork/lnd/ticker v1.0.0/go.mod h1:iaLXJiVgI1sPANIF2qYYUJXjoksPNvGNYowB8aRbpX0= -github.com/lightningnetwork/lnd/ticker v1.1.0 h1:ShoBiRP3pIxZHaETndfQ5kEe+S4NdAY1hiX7YbZ4QE4= -github.com/lightningnetwork/lnd/ticker v1.1.0/go.mod h1:ubqbSVCn6RlE0LazXuBr7/Zi6QT0uQo++OgIRBxQUrk= -github.com/lightningnetwork/lnd/tlv v1.1.0 h1:gsyte75HVuA/X59O+BhaISHM6OobZ0YesPbdu+xG1h0= -github.com/lightningnetwork/lnd/tlv v1.1.0/go.mod h1:0+JKp4un47MG1lnj6jKa8woNeB1X7w3yF4MZB1NHiiE= -github.com/lightningnetwork/lnd/tor v1.0.0/go.mod h1:RDtaAdwfAm+ONuPYwUhNIH1RAvKPv+75lHPOegUcz64= -github.com/lightningnetwork/lnd/tor v1.1.0 h1:iXO7fSzjxTI+p88KmtpbuyuRJeNfgtpl9QeaAliILXE= -github.com/lightningnetwork/lnd/tor v1.1.0/go.mod h1:RDtaAdwfAm+ONuPYwUhNIH1RAvKPv+75lHPOegUcz64= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= -github.com/linxGnu/grocksdb v1.7.16 h1:Q2co1xrpdkr5Hx3Fp+f+f7fRGhQFQhvi/+226dtLmA8= -github.com/linxGnu/grocksdb v1.7.16/go.mod h1:JkS7pl5qWpGpuVb3bPqTz8nC12X3YtPZT+Xq7+QfQo4= -github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796 h1:sjOGyegMIhvgfq5oaue6Td+hxZuf3tDC8lAPrFldqFw= -github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796/go.mod h1:3p7ZTf9V1sNPI5H8P3NkTFF4LuwMdPl2DodF60qAKqY= -github.com/ltcsuite/ltcutil v0.0.0-20181217130922-17f3b04680b6/go.mod h1:8Vg/LTOO0KYa/vlHWJ6XZAevPQThGH5sufO0Hrou/lA= -github.com/lunixbochs/vtclean v0.0.0-20160125035106-4fbf7632a2c6/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= +github.com/linxGnu/grocksdb v1.8.6 h1:O7I6SIGPrypf3f/gmrrLUBQDKfO8uOoYdWf4gLS06tc= +github.com/linxGnu/grocksdb v1.8.6/go.mod h1:xZCIb5Muw+nhbDK4Y5UJuOrin5MceOuiXkVUR7vp4WY= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= -github.com/mattn/go-colorable v0.0.6/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= 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.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.0-20160806122752-66b8e73f3f5c/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= 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/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= -github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= -github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/mholt/archiver/v3 v3.5.0 h1:nE8gZIrw66cu4osS/U7UW7YDuGMHssxKutU8IfWxwWE= -github.com/mholt/archiver/v3 v3.5.0/go.mod h1:qqTTPUK/HZPFgFQ/TJ3BzvTpF/dPtFVJXdQbCmeMxwc= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg= -github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 h1:QRUSJEgZn2Snx0EmT/QLXibWjSUDjKWvXIT19NBVp94= github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= @@ -1002,6 +897,9 @@ github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:F github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= +github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= +github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -1023,30 +921,37 @@ github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxzi github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= -github.com/nwaples/rardecode v1.1.2 h1:Cj0yZY6T1Zx1R7AhTbyGSALm44/Mmq+BAPc4B/p/d3M= -github.com/nwaples/rardecode v1.1.2/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a h1:dlRvE5fWabOchtH7znfiFCcOvmIYgOeAS5ifBXBlh9Q= +github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= +github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.20.0 h1:8W0cWlwFkflGPLltQvLRB7ZVD5HuP6ng320w2IS245Q= +github.com/onsi/gomega v1.26.0 h1:03cDLK28U6hWvCAns6NeydX3zIm4SF3ci69ulidS32Q= +github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034= +github.com/opencontainers/image-spec v1.1.0-rc2/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= github.com/opencontainers/runc v1.1.5 h1:L44KXEpKmfWDcS02aeGm8QNTFXTo2D+8MYGDIJ/GDEs= +github.com/opencontainers/runc v1.1.5/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg= github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= @@ -1056,31 +961,32 @@ github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJ github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA= +github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= -github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= +github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= +github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= -github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 h1:hDSdbBuw3Lefr6R18ax0tZ2BJeNB3NehB3trOwYBsdU= -github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/petermattis/goid v0.0.0-20230904192822-1876fd5063bc h1:8bQZVK1X6BJR/6nYUPxQEP+ReTsceJTKizeuwjWOPUA= +github.com/petermattis/goid v0.0.0-20230904192822-1876fd5063bc/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pierrec/lz4/v4 v4.0.3/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= -github.com/pierrec/lz4/v4 v4.1.8 h1:ieHkV+i2BRzngO4Wd/3HGowuZStgq6QkPsD1eolNAO4= -github.com/pierrec/lz4/v4 v4.1.8/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= +github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= -github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= @@ -1088,114 +994,107 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.15.0 h1:5fCgGYogn0hFdhyhLbw7hEsWxufKtY9klyvdNfFlFhM= -github.com/prometheus/client_golang v1.15.0/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk= +github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= +github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 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.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= -github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= -github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= +github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= +github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= -github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= -github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= -github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/regen-network/gocuke v0.6.2 h1:pHviZ0kKAq2U2hN2q3smKNxct6hS0mGByFMHGnWA97M= github.com/regen-network/protobuf v1.3.3-alpha.regen.1 h1:OHEc+q5iIAXpqiqFKeLpu5NwTIkVXUs48vFMwzqpqY4= github.com/regen-network/protobuf v1.3.3-alpha.regen.1/go.mod h1:2DjTFR1HhMQhiWC5sZ4OhQ3+NtdbZ6oBDKQwq5Ou+FI= -github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk= -github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= +github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/fastuuid v1.2.0 h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi2s= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.8.3 h1:O+qNyWn7Z+F9M0ILBHgMVPuB1xTOucVd5gtaYyXBpRo= github.com/rs/cors v1.8.3/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= -github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= -github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= -github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= -github.com/rs/zerolog v1.29.1 h1:cO+d60CHkknCbvzEWxP0S9K6KqyTjrCNUy1LdQLCGPc= -github.com/rs/zerolog v1.29.1/go.mod h1:Le6ESbR7hc+DP6Lt1THiV8CQSdkkNrd3R0XbEgp3ZBU= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A= +github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0= github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= -github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= -github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= -github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= -github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= -github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= -github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= -github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= -github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/spf13/viper v1.16.0 h1:rGGH0XDZhdUOryiDWjmIvUSWpbNqisK8Wk0Vyefw8hc= -github.com/spf13/viper v1.16.0/go.mod h1:yg78JgCJcbrQOvV9YLXgkLaZqUidkY9K+Dd1FofRzQg= +github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= +github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= +github.com/strangelove-ventures/cometbft v0.37.3-0.20231004194858-c01e8d5bcac3 h1:sOdCYxFMTVbEGvJ6LfjQsm+tQbB5YdUpvMcXJnHBFm4= +github.com/strangelove-ventures/cometbft v0.37.3-0.20231004194858-c01e8d5bcac3/go.mod h1:Jgux5ULdCs9N7ARy9NHe+hPfJQhUFpYF6+/+gmcqsGw= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -1206,28 +1105,26 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= -github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= -github.com/supranational/blst v0.3.8 h1:glwLF4oBRSJOTr05lRBgNwGQST0ndP2wg29fSeTRKCY= -github.com/supranational/blst v0.3.8/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= +github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= -github.com/tidwall/btree v1.6.0 h1:LDZfKfQIBHGHWSwckhXI0RPSXzlo+KYdjK7FWSqOzzg= -github.com/tidwall/btree v1.6.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= -github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw= -github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk= -github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o= -github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ= +github.com/tidwall/btree v1.7.0 h1:L1fkJH/AuEh5zBnnBbmTwQ5Lt+bRJ5A8EWecslvo9iI= +github.com/tidwall/btree v1.7.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 h1:uruHq4dN7GR16kFc5fp3d1RIYzJW5onx8Ybykw2YQFA= -github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= @@ -1235,9 +1132,8 @@ github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0= -github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= -github.com/ulikunitz/xz v0.5.7/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= @@ -1246,9 +1142,7 @@ github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtX github.com/urfave/cli v1.22.14 h1:ebbhrRiGK2i4naQJr+1Xj92HXZCrK7MsyTS/ob3HnAk= github.com/urfave/cli v1.22.14/go.mod h1:X0eDS6pD6Exaclxm99NJ3FiCDRED7vIHpx2mDOHLvkA= github.com/vulpine-io/io-test v1.0.0 h1:Ot8vMh+ssm1VWDAwJ3U4C5qG9aRnr5YfQFZPNZBAUGI= -github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= -github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= +github.com/vulpine-io/io-test v1.0.0/go.mod h1:X1I+p5GCxVX9m4nFd1HBtr2bVX9v1ZE6x8w+Obt36AU= 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/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -1257,30 +1151,14 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de 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/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= -github.com/zondax/hid v0.9.1 h1:gQe66rtmyZ8VeGFcOpbuH3r7erYtNEAezCAYu8LdkJo= -github.com/zondax/hid v0.9.1/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= -github.com/zondax/ledger-go v0.14.1 h1:Pip65OOl4iJ84WTpA4BKChvOufMhhbxED3BaihoZN4c= -github.com/zondax/ledger-go v0.14.1/go.mod h1:fZ3Dqg6qcdXWSOJFKMG8GCTnD7slO/RL2feOQv8K320= +github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= +github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= +github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw= +github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.5-0.20200615073812-232d8fc87f50/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= -go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= -go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= +go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA= +go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= -go.etcd.io/etcd/api/v3 v3.5.9 h1:4wSsluwyTbGGmyjJktOf3wFQoTBIURXHnq9n/G/JQHs= -go.etcd.io/etcd/api/v3 v3.5.9/go.mod h1:uyAal843mC8uUVSLWz6eHa/d971iDGnCRpmKd2Z+X8k= -go.etcd.io/etcd/client/pkg/v3 v3.5.9 h1:oidDC4+YEuSIQbsR94rY9gur91UPL6DnxDCIYd2IGsE= -go.etcd.io/etcd/client/pkg/v3 v3.5.9/go.mod h1:y+CzeSmkMpWN2Jyu1npecjB9BBnABxGM4pN8cGuJeL4= -go.etcd.io/etcd/client/v2 v2.305.7 h1:AELPkjNR3/igjbO7CjyF1fPuVPjrblliiKj+Y6xSGOU= -go.etcd.io/etcd/client/v2 v2.305.7/go.mod h1:GQGT5Z3TBuAQGvgPfhR7VPySu/SudxmEkRq9BgzFU6s= -go.etcd.io/etcd/client/v3 v3.5.9 h1:r5xghnU7CwbUxD/fbUtRyJGaYNfDun8sp/gTr1hew6E= -go.etcd.io/etcd/client/v3 v3.5.9/go.mod h1:i/Eo5LrZ5IKqpbtpPDuaUnDOUv471oDg8cjQaUr2MbA= -go.etcd.io/etcd/pkg/v3 v3.5.7 h1:obOzeVwerFwZ9trMWapU/VjDcYUJb5OfgC1zqEGWO/0= -go.etcd.io/etcd/pkg/v3 v3.5.7/go.mod h1:kcOfWt3Ov9zgYdOiJ/o1Y9zFfLhQjylTgL4Lru8opRo= -go.etcd.io/etcd/raft/v3 v3.5.7 h1:aN79qxLmV3SvIq84aNTliYGmjwsW6NqJSnqmI1HLJKc= -go.etcd.io/etcd/raft/v3 v3.5.7/go.mod h1:TflkAb/8Uy6JFBxcRaH2Fr6Slm9mCPVdI2efzxY96yU= -go.etcd.io/etcd/server/v3 v3.5.7 h1:BTBD8IJUV7YFgsczZMHhMTS67XuA4KpRquL0MFOJGRk= -go.etcd.io/etcd/server/v3 v3.5.7/go.mod h1:gxBgT84issUVBRpZ3XkW1T55NjOb4vZZRI4wVvNhf4A= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= @@ -1292,65 +1170,41 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.36.3 h1:syAz40OyelLZo42+3U68Phisvrx4qh+4wpdZw7eUUdY= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.36.3/go.mod h1:Dts42MGkzZne2yCru741+bFiTMWkIj/LLRizad7b9tw= -go.opentelemetry.io/otel v1.0.1/go.mod h1:OPEOD4jIT2SlZPMmwT6FqZz2C0ZNdQqiWcoK6M0SNFU= -go.opentelemetry.io/otel v1.11.0 h1:kfToEGMDq6TrVrJ9Vht84Y8y9enykSZzDDZglV0kIEk= -go.opentelemetry.io/otel v1.11.0/go.mod h1:H2KtuEphyMvlhZ+F7tg9GRhAOe60moNx61Ex+WmiKkk= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.1 h1:ofMbch7i29qIUf7VtF+r0HRF6ac0SBaPSziSsKp7wkk= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.1/go.mod h1:Kv8liBeVNFkkkbilbgWRpV+wWuu+H5xdOT6HAgd30iw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.0.1 h1:CFMFNoz+CGprjFAFy+RJFrfEe4GBia3RRm2a4fREvCA= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.0.1/go.mod h1:xOvWoTOrQjxjW61xtOmD/WKGRYb/P4NzRo3bs65U6Rk= -go.opentelemetry.io/otel/sdk v1.0.1 h1:wXxFEWGo7XfXupPwVJvTBOaPBC9FEg0wB8hMNrKk+cA= -go.opentelemetry.io/otel/sdk v1.0.1/go.mod h1:HrdXne+BiwsOHYYkBE5ysIcv2bvdZstxzmCQhxTcZkI= -go.opentelemetry.io/otel/trace v1.0.1/go.mod h1:5g4i4fKLaX2BQpSBsxw8YYcgKpMMSW3x7ZTuYBr3sUk= -go.opentelemetry.io/otel/trace v1.11.0 h1:20U/Vj42SX+mASlXLmSGBg6jpI1jQtv682lZtTAOVFI= -go.opentelemetry.io/otel/trace v1.11.0/go.mod h1:nyYjis9jy0gytE9LXGU+/m1sHTKbRY0fX0hulNNDP1U= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v0.9.0 h1:C0g6TWmQYvjKRnljRULLWUVJGy8Uvu0NEL/5frY2/t4= -go.opentelemetry.io/proto/otlp v0.9.0/go.mod h1:1vKfU9rv61e9EVGthD1zNvUbiwPcimSsOPU9brfSHJg= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= +go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= -go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= -go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= -go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= -go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= +go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= -golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1362,8 +1216,8 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= -golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc= -golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1390,8 +1244,8 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1433,17 +1287,13 @@ golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/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-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= @@ -1456,8 +1306,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1470,7 +1320,6 @@ golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210615190721-d04028783cf1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= @@ -1484,8 +1333,8 @@ golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= -golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= -golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= +golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ= +golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= 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= @@ -1500,8 +1349,8 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1513,9 +1362,7 @@ golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1524,10 +1371,8 @@ golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1562,14 +1407,11 @@ golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/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-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1582,6 +1424,7 @@ golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/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-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1598,22 +1441,20 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220624220833-87e55d714810/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-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= 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= @@ -1625,14 +1466,14 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA= -golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/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-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1642,18 +1483,17 @@ golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1687,7 +1527,6 @@ golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= @@ -1695,10 +1534,8 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= +golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1757,8 +1594,8 @@ google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= -google.golang.org/api v0.122.0 h1:zDobeejm3E7pEG1mNHvdxvjs5XJoCMzyNH+CmwL94Es= -google.golang.org/api v0.122.0/go.mod h1:gcitW0lvnyWjSp9nKxAbdHKIZ6vF4aajGueeslZOyms= +google.golang.org/api v0.153.0 h1:N1AwGhielyKFaUqH07/ZSIQR3uNPcV7NVw0vj+j4iR4= +google.golang.org/api v0.153.0/go.mod h1:3qNJX5eOmhiWYc67jRA/3GsDw97UFb5ivv7Y2PrriAY= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1766,8 +1603,9 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -1807,10 +1645,8 @@ google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -1820,7 +1656,6 @@ google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQ google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= @@ -1878,12 +1713,12 @@ google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqw google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= -google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e h1:Ao9GzfUMPH3zjVfzXG5rlWlk+Q8MXWKwWpwVQE1MXfw= -google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:zqTuNwFlFRsw5zIts5VnzLQxSRqh+CGOTVMlYbY0Eyk= -google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc h1:kVKPf/IiYSBWEWtkIn6wZXwWGCnLKcC8oWfZvXjsGnM= -google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc h1:XSJ8Vk1SWuNr8S18z1NZSziL0CPIXLCCMDOEFtHBOFc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= +google.golang.org/genproto v0.0.0-20231211222908-989df2bf70f3 h1:1hfbdAfFbkmpg41000wDVqr7jUpK/Yo+LPnIxxGzmkg= +google.golang.org/genproto v0.0.0-20231211222908-989df2bf70f3/go.mod h1:5RBcpGRxr25RbDzY5w+dmaqpSEvl8Gwl1x2CICf60ic= +google.golang.org/genproto/googleapis/api v0.0.0-20231120223509-83a465c0220f h1:2yNACc1O40tTnrsbk9Cv6oxiW8pxI/pXj0wRtdlYmgY= +google.golang.org/genproto/googleapis/api v0.0.0-20231120223509-83a465c0220f/go.mod h1:Uy9bTZJqmfrw2rIBxgGLnamc78euZULUBrLZ9XTITKI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0 h1:/jFB8jK5R3Sq3i/lmeZO0cATSzFfZaJq1J2Euan3XKU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0/go.mod h1:FUoWkonphQm3RhTS+kOEhF8h0iDpm4tdXolVCeZ9KKA= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= @@ -1916,7 +1751,6 @@ google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnD google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= @@ -1926,8 +1760,8 @@ google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACu google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.56.1 h1:z0dNfjIl0VpaZ9iSVjA6daGatAYwPGstTjt5vkRMFkQ= -google.golang.org/grpc v1.56.1/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= +google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= +google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -1944,31 +1778,22 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20160105164936-4f90aeace3a2/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= -gopkg.in/errgo.v1 v1.0.1 h1:oQFRXzZ7CkBGdm1XZm/EbQYaYNNEElNBOd09M6cqNso= -gopkg.in/errgo.v1 v1.0.1/go.mod h1:3NjfXwocQRYAPTq4/fzX+CwUhPRcR/azYRhj8G+LqMo= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= -gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/macaroon-bakery.v2 v2.0.1 h1:0N1TlEdfLP4HXNCg7MQUMp5XwvOoxk+oe9Owr2cpvsc= -gopkg.in/macaroon-bakery.v2 v2.0.1/go.mod h1:B4/T17l+ZWGwxFSZQmlBwp25x+og7OkhETfr3S9MbIA= -gopkg.in/macaroon.v2 v2.0.0 h1:LVWycAfeJBUjCIqfR9gqlo7I8vmiXRr51YEOZ1suop8= -gopkg.in/macaroon.v2 v2.0.0/go.mod h1:+I6LnTMkm/uV5ew/0nsulNjL16SK4+C8yDmRUzHR17I= -gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= -gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= @@ -1987,8 +1812,8 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= -gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o= +gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= +gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1997,38 +1822,16 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh 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= -lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI= -lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= -modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw= -modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0= -modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw= -modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY= -modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk= -modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM= -modernc.org/libc v1.22.2 h1:4U7v51GyhlWqQmwCHj28Rdq2Yzwk55ovjFrdPjs8Hb0= -modernc.org/libc v1.22.2/go.mod h1:uvQavJ1pZ0hIoC/jfqNoMLURIMhKzINIWypNM17puug= -modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ= -modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/memory v1.4.0 h1:crykUfNSnMAXaOJnnxcSzbUGMqkLWjklJKkBK2nwZwk= -modernc.org/memory v1.4.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= -modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= -modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= -modernc.org/sqlite v1.20.3 h1:SqGJMMxjj1PHusLxdYxeQSodg7Jxn9WWkaAQjKrntZs= -modernc.org/sqlite v1.20.3/go.mod h1:zKcGyrICaxNTMEHSr1HQ2GUraP0j+845GYw37+EyT6A= -modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY= -modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= -modernc.org/tcl v1.15.0 h1:oY+JeD11qVVSgVvodMJsu7Edf8tr5E/7tuhF5cNYz34= -modernc.org/token v1.0.1 h1:A3qvTqOwexpfZZeyI0FeGPDlSWX5pjZu9hF4lU+EKWg= -modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= -modernc.org/z v1.7.0 h1:xkDw/KepgEjeizO2sNco+hqYkU12taxQFqPEmgm1GWE= nhooyr.io/websocket v1.8.6 h1:s+C3xAMLwGmlI31Nyn/eAehUlZPwfYZu2JXM621Q5/k= nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= -pgregory.net/rapid v0.5.5 h1:jkgx1TjbQPD/feRoK+S/mXw9e1uj6WilpHrXJowi6oA= -pgregory.net/rapid v0.5.5/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= +pgregory.net/rapid v1.1.0 h1:CMa0sjHSru3puNx+J0MIAuiiEV4N0qj8/cMWGBBCsjw= +pgregory.net/rapid v1.1.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= +rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/itest/babylon_node_handler.go b/itest/babylon_node_handler.go index e7caaef9..f5e63e20 100644 --- a/itest/babylon_node_handler.go +++ b/itest/babylon_node_handler.go @@ -8,46 +8,23 @@ import ( "os/exec" "path/filepath" "runtime" + "strings" "testing" "github.com/babylonchain/babylon/types" "github.com/stretchr/testify/require" - - "github.com/babylonchain/btc-validator/service" - "github.com/babylonchain/btc-validator/val" ) -func baseDir() (string, error) { - tempPath := os.TempDir() - - tempName, err := os.MkdirTemp(tempPath, "zBabylonTest") - if err != nil { - return "", err - } - - err = os.Chmod(tempName, 0755) - - if err != nil { - return "", err - } - - return tempName, nil -} - type babylonNode struct { - cmd *exec.Cmd - pidFile string - dataDir string - juryKeyName string - slashingAddr string + cmd *exec.Cmd + pidFile string + dataDir string } -func newBabylonNode(dataDir string, cmd *exec.Cmd, juryKeyName, slashingAddr string) *babylonNode { +func newBabylonNode(dataDir string, cmd *exec.Cmd) *babylonNode { return &babylonNode{ - dataDir: dataDir, - cmd: cmd, - juryKeyName: juryKeyName, - slashingAddr: slashingAddr, + dataDir: dataDir, + cmd: cmd, } } @@ -125,8 +102,8 @@ type BabylonNodeHandler struct { babylonNode *babylonNode } -func NewBabylonNodeHandler(t *testing.T) *BabylonNodeHandler { - testDir, err := baseDir() +func NewBabylonNodeHandler(t *testing.T, covenantQuorum int, covenantPks []*types.BIP340PubKey) *BabylonNodeHandler { + testDir, err := baseDir("zBabylonTest") require.NoError(t, err) defer func() { if err != nil { @@ -137,26 +114,13 @@ func NewBabylonNodeHandler(t *testing.T) *BabylonNodeHandler { nodeDataDir := filepath.Join(testDir, "node0", "babylond") - // the Jury key needs to be created before babylond is started - chainID := "chain-test" - sdkCtx, err := service.CreateClientCtx( - nodeDataDir, - chainID, - ) - require.NoError(t, err) - juryKeyName := "jury-key" - krController, err := val.NewKeyringController( - sdkCtx, - juryKeyName, - "test", - ) - require.NoError(t, err) - juryPk, err := krController.CreateJuryKey() - require.NoError(t, err) - juryPkBip340 := types.NewBIP340PubKeyFromBTCPK(juryPk) - slashingAddr := "SZtRT4BySL3o4efdGLh3k7Kny8GAnsBrSW" + var covenantPksStr []string + for _, pk := range covenantPks { + covenantPksStr = append(covenantPksStr, pk.MarshalHex()) + } + initTestnetCmd := exec.Command( "babylond", "testnet", @@ -167,7 +131,8 @@ func NewBabylonNodeHandler(t *testing.T) *BabylonNodeHandler { "--chain-id=chain-test", "--additional-sender-account", fmt.Sprintf("--slashing-address=%s", slashingAddr), - fmt.Sprintf("--jury-pk=%s", juryPkBip340.MarshalHex()), + fmt.Sprintf("--covenant-quorum=%d", covenantQuorum), + fmt.Sprintf("--covenant-pks=%s", strings.Join(covenantPksStr, ",")), ) var stderr bytes.Buffer @@ -192,7 +157,7 @@ func NewBabylonNodeHandler(t *testing.T) *BabylonNodeHandler { startCmd.Stdout = f return &BabylonNodeHandler{ - babylonNode: newBabylonNode(testDir, startCmd, juryKeyName, slashingAddr), + babylonNode: newBabylonNode(testDir, startCmd), } } @@ -217,11 +182,3 @@ func (w *BabylonNodeHandler) GetNodeDataDir() string { dir := filepath.Join(w.babylonNode.dataDir, "node0", "babylond") return dir } - -func (w *BabylonNodeHandler) GetJuryKeyName() string { - return w.babylonNode.juryKeyName -} - -func (w *BabylonNodeHandler) GetSlashingAddress() string { - return w.babylonNode.slashingAddr -} diff --git a/itest/e2e_test.go b/itest/e2e_test.go index 10251ae3..4139b3fe 100644 --- a/itest/e2e_test.go +++ b/itest/e2e_test.go @@ -5,23 +5,15 @@ package e2etest import ( "math/rand" - "os" "testing" "time" "github.com/babylonchain/babylon/testutil/datagen" - btcstakingtypes "github.com/babylonchain/babylon/x/btcstaking/types" "github.com/btcsuite/btcd/btcec/v2" - "github.com/cosmos/cosmos-sdk/crypto/keyring" - "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - "github.com/sirupsen/logrus" "github.com/stretchr/testify/require" - "github.com/babylonchain/btc-validator/clientcontroller" - "github.com/babylonchain/btc-validator/service" - "github.com/babylonchain/btc-validator/types" - "github.com/babylonchain/btc-validator/val" - "github.com/babylonchain/btc-validator/valcfg" + "github.com/babylonchain/finality-provider/finality-provider/service" + "github.com/babylonchain/finality-provider/types" ) var ( @@ -29,246 +21,163 @@ var ( stakingAmount = int64(20000) ) -func TestPoller(t *testing.T) { - handler := NewBabylonNodeHandler(t) - - err := handler.Start() - require.NoError(t, err) - defer handler.Stop() - - defaultConfig := valcfg.DefaultBBNConfig() - logger := logrus.New() - logger.SetLevel(logrus.DebugLevel) - logger.Out = os.Stdout - defaultPollerConfig := valcfg.DefaultChainPollerConfig() - - bc, err := clientcontroller.NewBabylonController(handler.GetNodeDataDir(), &defaultConfig, logger) - require.NoError(t, err) - - poller := service.NewChainPoller(logger, &defaultPollerConfig, bc) - require.NoError(t, err) - - // Set auto calculated start height to 1, as we have disabled automatic start height calculation - err = poller.Start(1) - require.NoError(t, err) - defer poller.Stop() - - // Get 3 blocks which should be received in order - select { - case info := <-poller.GetBlockInfoChan(): - require.Equal(t, uint64(1), info.Height) - - case <-time.After(10 * time.Second): - t.Fatalf("Failed to get block info") - } - - select { - case info := <-poller.GetBlockInfoChan(): - require.Equal(t, uint64(2), info.Height) - - case <-time.After(10 * time.Second): - t.Fatalf("Failed to get block info") - } - - select { - case info := <-poller.GetBlockInfoChan(): - require.Equal(t, uint64(3), info.Height) - - case <-time.After(10 * time.Second): - t.Fatalf("Failed to get block info") - } -} - -// TestValidatorLifeCycle tests the whole life cycle of a validator +// TestFinalityProviderLifeCycle tests the whole life cycle of a finality-provider // creation -> registration -> randomness commitment -> -// activation with BTC delegation and Jury sig -> +// activation with BTC delegation and Covenant sig -> // vote submission -> block finalization -func TestValidatorLifeCycle(t *testing.T) { - tm := StartManagerWithValidator(t, 1, false) +func TestFinalityProviderLifeCycle(t *testing.T) { + tm, fpInsList := StartManagerWithFinalityProvider(t, 1) defer tm.Stop(t) - app := tm.Va - valIns := app.ListValidatorInstances()[0] + fpIns := fpInsList[0] // check the public randomness is committed - tm.WaitForValPubRandCommitted(t, valIns) + tm.WaitForFpPubRandCommitted(t, fpIns) // send a BTC delegation - delData := tm.InsertBTCDelegation(t, valIns.MustGetBtcPk(), stakingTime, stakingAmount) + _ = tm.InsertBTCDelegation(t, []*btcec.PublicKey{fpIns.MustGetBtcPk()}, stakingTime, stakingAmount) // check the BTC delegation is pending dels := tm.WaitForNPendingDels(t, 1) - require.True(t, dels[0].BabylonPk.Equals(delData.DelegatorBabylonKey)) - // submit Jury sig - _ = tm.AddJurySignature(t, dels[0]) + // send covenant sigs + tm.InsertCovenantSigForDelegation(t, dels[0]) // check the BTC delegation is active - dels = tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) - require.True(t, dels[0].BabylonPk.Equals(delData.DelegatorBabylonKey)) - - // check there's a block finalized - _ = tm.WaitForNFinalizedBlocks(t, 1) -} - -// TestMultipleValidators tests starting with multiple validators -func TestMultipleValidators(t *testing.T) { - n := 3 - tm := StartManagerWithValidator(t, n, false) - defer tm.Stop(t) - - app := tm.Va - valInstances := app.ListValidatorInstances() - - // submit BTC delegations for each validator - for _, valIns := range valInstances { - tm.Wg.Add(1) - go func(v *service.ValidatorInstance) { - defer tm.Wg.Done() - // check the public randomness is committed - tm.WaitForValPubRandCommitted(t, v) - - // send a BTC delegation - _ = tm.InsertBTCDelegation(t, v.MustGetBtcPk(), stakingTime, stakingAmount) - }(valIns) - } - tm.Wg.Wait() - - // check the 3 BTC delegations are pending - dels := tm.WaitForNPendingDels(t, 3) - - // submit Jury sigs for each delegation - for _, del := range dels { - tm.Wg.Add(1) - go func(btcDel *btcstakingtypes.BTCDelegation) { - defer tm.Wg.Done() - _ = tm.AddJurySignature(t, btcDel) - }(del) - } - tm.Wg.Wait() - - for _, valIns := range valInstances { - tm.Wg.Add(1) - go func(v *service.ValidatorInstance) { - defer tm.Wg.Done() - _ = tm.WaitForValNActiveDels(t, v.GetBtcPkBIP340(), 1) - }(valIns) - } - tm.Wg.Wait() - - // check there's a block finalized - _ = tm.WaitForNFinalizedBlocks(t, 1) -} - -func TestJurySigSubmission(t *testing.T) { - tm := StartManagerWithValidator(t, 1, true) - // changing the mode because we need to ensure the validator is also stopped when the test is finished - defer tm.Stop(t) - app := tm.Va - valIns := app.ListValidatorInstances()[0] + _ = tm.WaitForNActiveDels(t, 1) - // send BTC delegation and make sure it's deep enough in btclightclient module - delData := tm.InsertBTCDelegation(t, valIns.MustGetBtcPk(), stakingTime, stakingAmount) - - dels := tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) - require.True(t, dels[0].BabylonPk.Equals(delData.DelegatorBabylonKey)) - err := valIns.Stop() - require.NoError(t, err) + // check the last voted block is finalized + lastVotedHeight := tm.WaitForFpVoteCast(t, fpIns) + tm.CheckBlockFinalization(t, lastVotedHeight, 1) + t.Logf("the block at height %v is finalized", lastVotedHeight) } -// TestDoubleSigning tests the attack scenario where the validator +// TestDoubleSigning tests the attack scenario where the finality-provider // sends a finality vote over a conflicting block // in this case, the BTC private key should be extracted by Babylon func TestDoubleSigning(t *testing.T) { - tm := StartManagerWithValidator(t, 1, false) + tm, fpInsList := StartManagerWithFinalityProvider(t, 1) defer tm.Stop(t) - app := tm.Va - valIns := app.ListValidatorInstances()[0] + fpIns := fpInsList[0] // check the public randomness is committed - tm.WaitForValPubRandCommitted(t, valIns) + tm.WaitForFpPubRandCommitted(t, fpIns) // send a BTC delegation - delData := tm.InsertBTCDelegation(t, valIns.MustGetBtcPk(), stakingTime, stakingAmount) + _ = tm.InsertBTCDelegation(t, []*btcec.PublicKey{fpIns.MustGetBtcPk()}, stakingTime, stakingAmount) // check the BTC delegation is pending dels := tm.WaitForNPendingDels(t, 1) - require.True(t, dels[0].BabylonPk.Equals(delData.DelegatorBabylonKey)) - // submit Jury sig - _ = tm.AddJurySignature(t, dels[0]) + // send covenant sigs + tm.InsertCovenantSigForDelegation(t, dels[0]) // check the BTC delegation is active - dels = tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) - require.True(t, dels[0].BabylonPk.Equals(delData.DelegatorBabylonKey)) + _ = tm.WaitForNActiveDels(t, 1) + + // check the last voted block is finalized + lastVotedHeight := tm.WaitForFpVoteCast(t, fpIns) + tm.CheckBlockFinalization(t, lastVotedHeight, 1) + t.Logf("the block at height %v is finalized", lastVotedHeight) - // check there's a block finalized finalizedBlocks := tm.WaitForNFinalizedBlocks(t, 1) // attack: manually submit a finality vote over a conflicting block - // to trigger the extraction of validator's private key + // to trigger the extraction of finality-provider's private key r := rand.New(rand.NewSource(time.Now().UnixNano())) b := &types.BlockInfo{ - Height: finalizedBlocks[0].Height, - LastCommitHash: datagen.GenRandomLastCommitHash(r), + Height: finalizedBlocks[0].Height, + Hash: datagen.GenRandomByteArray(r, 32), } - _, extractedKey, err := valIns.TestSubmitFinalitySignatureAndExtractPrivKey(b) + _, extractedKey, err := fpIns.TestSubmitFinalitySignatureAndExtractPrivKey(b) require.NoError(t, err) require.NotNil(t, extractedKey) - localKey, err := getBtcPrivKey(app.GetKeyring(), val.KeyName(valIns.GetStoreValidator().KeyName)) - require.NoError(t, err) + localKey := tm.GetFpPrivKey(t, fpIns.GetBtcPkBIP340().MustMarshal()) require.True(t, localKey.Key.Equals(&extractedKey.Key) || localKey.Key.Negate().Equals(&extractedKey.Key)) t.Logf("the equivocation attack is successful") + + tm.WaitForFpShutDown(t, fpIns.GetBtcPkBIP340()) + + // try to start all the finality providers and the slashed one should not be restarted + err = tm.Fpa.StartHandlingAll() + require.NoError(t, err) + fps := tm.Fpa.ListFinalityProviderInstances() + require.Equal(t, 0, len(fps)) } -func getBtcPrivKey(kr keyring.Keyring, keyName val.KeyName) (*btcec.PrivateKey, error) { - k, err := kr.Key(keyName.GetBtcKeyName()) - if err != nil { - return nil, err +// TestMultipleFinalityProviders tests starting with multiple finality providers +func TestMultipleFinalityProviders(t *testing.T) { + n := 3 + tm, fpInstances := StartManagerWithFinalityProvider(t, n) + defer tm.Stop(t) + + // submit BTC delegations for each finality-provider + for _, fpIns := range fpInstances { + tm.Wg.Add(1) + go func(fpi *service.FinalityProviderInstance) { + defer tm.Wg.Done() + // check the public randomness is committed + tm.WaitForFpPubRandCommitted(t, fpi) + // send a BTC delegation + _ = tm.InsertBTCDelegation(t, []*btcec.PublicKey{fpi.MustGetBtcPk()}, stakingTime, stakingAmount) + }(fpIns) } - localKey := k.GetLocal().PrivKey.GetCachedValue() - switch v := localKey.(type) { - case *secp256k1.PrivKey: - privKey, _ := btcec.PrivKeyFromBytes(v.Key) - return privKey, nil - default: - return nil, err + tm.Wg.Wait() + + // check the BTC delegations are pending + dels := tm.WaitForNPendingDels(t, n) + require.Equal(t, n, len(dels)) + + // send covenant sigs to each of the delegations + for _, d := range dels { + // send covenant sigs + tm.InsertCovenantSigForDelegation(t, d) } + + // check the BTC delegations are active + _ = tm.WaitForNActiveDels(t, n) + + // check there's a block finalized + _ = tm.WaitForNFinalizedBlocks(t, 1) } -// TestFastSync tests the fast sync process where the validator is terminated and restarted with fast sync +// TestFastSync tests the fast sync process where the finality-provider is terminated and restarted with fast sync func TestFastSync(t *testing.T) { - tm := StartManagerWithValidator(t, 1, false) + tm, fpInsList := StartManagerWithFinalityProvider(t, 1) defer tm.Stop(t) - app := tm.Va - valIns := app.ListValidatorInstances()[0] + fpIns := fpInsList[0] // check the public randomness is committed - tm.WaitForValPubRandCommitted(t, valIns) + tm.WaitForFpPubRandCommitted(t, fpIns) // send a BTC delegation - delData := tm.InsertBTCDelegation(t, valIns.MustGetBtcPk(), stakingTime, stakingAmount) + _ = tm.InsertBTCDelegation(t, []*btcec.PublicKey{fpIns.MustGetBtcPk()}, stakingTime, stakingAmount) // check the BTC delegation is pending dels := tm.WaitForNPendingDels(t, 1) - require.True(t, dels[0].BabylonPk.Equals(delData.DelegatorBabylonKey)) - // submit Jury sig - _ = tm.AddJurySignature(t, dels[0]) + // send covenant sigs + tm.InsertCovenantSigForDelegation(t, dels[0]) - dels = tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) - require.True(t, dels[0].BabylonPk.Equals(delData.DelegatorBabylonKey)) + // check the BTC delegation is active + _ = tm.WaitForNActiveDels(t, 1) - // check there's a block finalized - finalizedBlocks := tm.WaitForNFinalizedBlocks(t, 1) + // check the last voted block is finalized + lastVotedHeight := tm.WaitForFpVoteCast(t, fpIns) + tm.CheckBlockFinalization(t, lastVotedHeight, 1) + + t.Logf("the block at height %v is finalized", lastVotedHeight) + + var finalizedBlocks []*types.BlockInfo + finalizedBlocks = tm.WaitForNFinalizedBlocks(t, 1) n := 3 - // stop the validator for a few blocks then restart to trigger the fast sync - tm.Config.FastSyncGap = uint64(n) - tm.StopAndRestartValidatorAfterNBlocks(t, n, valIns) + // stop the finality-provider for a few blocks then restart to trigger the fast sync + tm.FpConfig.FastSyncGap = uint64(n) + tm.StopAndRestartFpAfterNBlocks(t, n, fpIns) // check there are n+1 blocks finalized finalizedBlocks = tm.WaitForNFinalizedBlocks(t, n+1) @@ -276,116 +185,73 @@ func TestFastSync(t *testing.T) { t.Logf("the latest finalized block is at %v", finalizedHeight) // check if the fast sync works by checking if the gap is not more than 1 - currentHeaderRes, err := tm.BabylonClient.QueryBestHeader() - currentHeight := currentHeaderRes.Header.Height + currentHeaderRes, err := tm.BBNClient.QueryBestBlock() + currentHeight := currentHeaderRes.Height t.Logf("the current block is at %v", currentHeight) require.NoError(t, err) - require.True(t, currentHeight < int64(finalizedHeight)+int64(n)) + require.True(t, currentHeight < finalizedHeight+uint64(n)) } -func TestValidatorUnbondingSigSubmission(t *testing.T) { - tm := StartManagerWithValidator(t, 1, false) +// TestFastSync_DuplicateVotes covers a special case when the finality signature +// has inconsistent view of last voted height with the Babylon node and during +// fast-sync it submits a batch of finality sigs, one of which is rejected due +// to duplicate error +// this test covers this case by starting 3 finality providers, 2 of which +// are stopped after gaining voting power to simulate the case where no blocks +// are finalized. Then we let one of the finality providers "forget" the last +// voted height and restart all the finality providers, expecting it them to +// catch up and finalize new blocks +func TestFastSync_DuplicateVotes(t *testing.T) { + tm, fpInsList := StartManagerWithFinalityProvider(t, 3) defer tm.Stop(t) - app := tm.Va - valIns := app.ListValidatorInstances()[0] + fpIns1 := fpInsList[0] + fpIns2 := fpInsList[1] + fpIns3 := fpInsList[2] // check the public randomness is committed - tm.WaitForValPubRandCommitted(t, valIns) + tm.WaitForFpPubRandCommitted(t, fpIns1) + tm.WaitForFpPubRandCommitted(t, fpIns2) + tm.WaitForFpPubRandCommitted(t, fpIns3) - // send a BTC delegation - delData := tm.InsertBTCDelegation(t, valIns.MustGetBtcPk(), stakingTime, stakingAmount) - - // check the BTC delegation is pending - dels := tm.WaitForNPendingDels(t, 1) - - // submit Jury sig - _ = tm.AddJurySignature(t, dels[0]) - - dels = tm.WaitForValNActiveDels(t, valIns.GetBtcPkBIP340(), 1) - require.True(t, dels[0].BabylonPk.Equals(delData.DelegatorBabylonKey)) - - tm.InsertBTCUnbonding(t, delData.StakingTx, delData.DelegatorPrivKey, valIns.MustGetBtcPk()) + // send 3 BTC delegations to empower the three finality providers + _ = tm.InsertBTCDelegation(t, []*btcec.PublicKey{fpIns1.MustGetBtcPk()}, stakingTime, stakingAmount) + _ = tm.InsertBTCDelegation(t, []*btcec.PublicKey{fpIns2.MustGetBtcPk()}, stakingTime, stakingAmount) + _ = tm.InsertBTCDelegation(t, []*btcec.PublicKey{fpIns3.MustGetBtcPk()}, stakingTime, stakingAmount) - _ = tm.WaitForValNUnbondingDels(t, valIns.GetBtcPkBIP340(), 1) -} + // check the BTC delegations are pending + dels := tm.WaitForNPendingDels(t, 3) -func TestJuryUnbondingSigSubmission(t *testing.T) { - tm := StartManagerWithValidator(t, 1, true) - defer tm.Stop(t) - app := tm.Va - valIns := app.ListValidatorInstances()[0] + // send covenant sigs to each delegation + tm.InsertCovenantSigForDelegation(t, dels[0]) + tm.InsertCovenantSigForDelegation(t, dels[1]) + tm.InsertCovenantSigForDelegation(t, dels[2]) - // send BTC delegation and make sure it's deep enough in btclightclient module - delData := tm.InsertBTCDelegation(t, valIns.MustGetBtcPk(), stakingTime, stakingAmount) + // check the BTC delegations are active + _ = tm.WaitForNActiveDels(t, 3) - var ( - dels []*btcstakingtypes.BTCDelegation - err error - ) - require.Eventually(t, func() bool { - dels, err = tm.BabylonClient.QueryPendingBTCDelegations() - if err != nil { - return false - } - return len(dels) == 1 - }, eventuallyWaitTimeOut, eventuallyPollTime) - require.True(t, dels[0].BabylonPk.Equals(delData.DelegatorBabylonKey)) - - currentBtcTip, err := tm.BabylonClient.QueryBtcLightClientTip() + // stop 2 of the finality providers so that no blocks will be finalized + err := fpIns2.Stop() require.NoError(t, err) - params, err := tm.BabylonClient.GetStakingParams() + err = fpIns3.Stop() require.NoError(t, err) - require.Eventually(t, func() bool { - dels, err = tm.BabylonClient.QueryBTCValidatorDelegations(valIns.GetBtcPkBIP340(), 1000) - if err != nil { - return false - } - status := dels[0].GetStatus(currentBtcTip.Height, params.FinalizationTimeoutBlocks) - return len(dels) == 1 && status == btcstakingtypes.BTCDelegationStatus_ACTIVE - }, eventuallyWaitTimeOut, eventuallyPollTime) - require.True(t, dels[0].BabylonPk.Equals(delData.DelegatorBabylonKey)) - - tm.InsertBTCUnbonding(t, delData.StakingTx, delData.DelegatorPrivKey, valIns.MustGetBtcPk()) - require.Eventually(t, func() bool { - dels, err = tm.BabylonClient.QueryBTCValidatorDelegations(valIns.GetBtcPkBIP340(), 1000) - if err != nil { - return false - } - return len(dels) == 1 && dels[0].BtcUndelegation != nil - }, eventuallyWaitTimeOut, eventuallyPollTime) + // make sure fp1 has cast a finality vote + // and then make it "forget" the last voted height + lastVotedHeight := tm.WaitForFpVoteCast(t, fpIns1) + fpIns1.MustUpdateStateAfterFinalitySigSubmission(lastVotedHeight - 1) - dels, err = tm.BabylonClient.QueryBTCValidatorDelegations(valIns.GetBtcPkBIP340(), 1000) + // stop fp1, restarts all the fps after 3 blocks for them to catch up + // and expect a block will be finalized + n := 3 + tm.FpConfig.FastSyncGap = uint64(n) + tm.StopAndRestartFpAfterNBlocks(t, n, fpIns1) + err = fpIns2.Start() require.NoError(t, err) - delegationWithUndelegation := dels[0] - - validatorPrivKey, err := valIns.BtcPrivKey() + err = fpIns3.Start() require.NoError(t, err) - - tm.AddValidatorUnbondingSignature( - t, - delegationWithUndelegation, - validatorPrivKey, - ) - - // after providing validator unbodning signature, we should wait for jury to provide both valid signatures require.Eventually(t, func() bool { - dels, err = tm.BabylonClient.QueryBTCValidatorDelegations(valIns.GetBtcPkBIP340(), 1000) - if err != nil { - return false - } - - if len(dels) != 1 { - return false - } - - del := dels[0] - - if del.BtcUndelegation == nil { - return false - } - - return del.BtcUndelegation.HasJurySigs() - }, 1*time.Minute, eventuallyPollTime) + finalizedBlocks := tm.WaitForNFinalizedBlocks(t, 1) + return finalizedBlocks[0].Height > lastVotedHeight + }, eventuallyWaitTimeOut, eventuallyPollTime) } diff --git a/itest/eotsmanager_handler.go b/itest/eotsmanager_handler.go new file mode 100644 index 00000000..2c644500 --- /dev/null +++ b/itest/eotsmanager_handler.go @@ -0,0 +1,49 @@ +package e2etest + +import ( + "testing" + + "github.com/lightningnetwork/lnd/signal" + "github.com/stretchr/testify/require" + "go.uber.org/zap" + + "github.com/babylonchain/finality-provider/eotsmanager" + "github.com/babylonchain/finality-provider/eotsmanager/config" + "github.com/babylonchain/finality-provider/eotsmanager/service" +) + +type EOTSServerHandler struct { + t *testing.T + interceptor *signal.Interceptor + eotsServer *service.Server +} + +func NewEOTSServerHandler(t *testing.T, cfg *config.Config, eotsHomeDir string) *EOTSServerHandler { + shutdownInterceptor, err := signal.Intercept() + require.NoError(t, err) + + logger := zap.NewNop() + eotsManager, err := eotsmanager.NewLocalEOTSManager(eotsHomeDir, cfg, logger) + require.NoError(t, err) + + eotsServer := service.NewEOTSManagerServer(cfg, logger, eotsManager, shutdownInterceptor) + + return &EOTSServerHandler{ + t: t, + eotsServer: eotsServer, + interceptor: &shutdownInterceptor, + } +} + +func (eh *EOTSServerHandler) Start() { + go eh.startServer() +} + +func (eh *EOTSServerHandler) startServer() { + err := eh.eotsServer.RunUntilShutdown() + require.NoError(eh.t, err) +} + +func (eh *EOTSServerHandler) Stop() { + eh.interceptor.RequestShutdown() +} diff --git a/itest/test_manager.go b/itest/test_manager.go index 18417c15..e89ec430 100644 --- a/itest/test_manager.go +++ b/itest/test_manager.go @@ -10,42 +10,57 @@ import ( "testing" "time" + sdkmath "cosmossdk.io/math" "github.com/babylonchain/babylon/btcstaking" + asig "github.com/babylonchain/babylon/crypto/schnorr-adaptor-signature" "github.com/babylonchain/babylon/testutil/datagen" bbntypes "github.com/babylonchain/babylon/types" btcctypes "github.com/babylonchain/babylon/x/btccheckpoint/types" btclctypes "github.com/babylonchain/babylon/x/btclightclient/types" bstypes "github.com/babylonchain/babylon/x/btcstaking/types" "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" + "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - sdktypes "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - "github.com/cosmos/relayer/v2/relayer/provider" - "github.com/sirupsen/logrus" "github.com/stretchr/testify/require" - - "github.com/babylonchain/btc-validator/clientcontroller" - "github.com/babylonchain/btc-validator/service" - "github.com/babylonchain/btc-validator/types" - "github.com/babylonchain/btc-validator/valcfg" + "go.uber.org/zap" + + fpcc "github.com/babylonchain/finality-provider/clientcontroller" + "github.com/babylonchain/finality-provider/eotsmanager/client" + eotsconfig "github.com/babylonchain/finality-provider/eotsmanager/config" + fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" + "github.com/babylonchain/finality-provider/finality-provider/service" + "github.com/babylonchain/finality-provider/types" ) var ( eventuallyWaitTimeOut = 1 * time.Minute eventuallyPollTime = 500 * time.Millisecond + btcNetworkParams = &chaincfg.SimNetParams + + fpNamePrefix = "test-fp-" + monikerPrefix = "moniker-" + chainID = "chain-test" + passphrase = "testpass" + hdPath = "" + simnetParams = &chaincfg.SimNetParams ) -var btcNetworkParams = &chaincfg.SimNetParams - type TestManager struct { - Wg sync.WaitGroup - BabylonHandler *BabylonNodeHandler - Config *valcfg.Config - Va *service.ValidatorApp - BabylonClient *clientcontroller.BabylonController + Wg sync.WaitGroup + BabylonHandler *BabylonNodeHandler + EOTSServerHandler *EOTSServerHandler + FpConfig *fpcfg.Config + EOTSConfig *eotsconfig.Config + Fpa *service.FinalityProviderApp + EOTSClient *client.EOTSManagerGRpcClient + BBNClient *fpcc.BabylonController + StakingParams *types.StakingParams + CovenantPrivKeys []*btcec.PrivateKey + baseDir string } type TestDelegationData struct { @@ -53,105 +68,126 @@ type TestDelegationData struct { DelegatorKey *btcec.PublicKey DelegatorBabylonPrivKey *secp256k1.PrivKey DelegatorBabylonKey *secp256k1.PubKey - StakingTx *bstypes.BabylonBTCTaprootTx SlashingTx *bstypes.BTCSlashingTx + StakingTx *wire.MsgTx StakingTxInfo *btcctypes.TransactionInfo DelegatorSig *bbntypes.BIP340Signature + FpPks []*btcec.PublicKey SlashingAddr string + ChangeAddr string StakingTime uint16 StakingAmount int64 } -func StartManager(t *testing.T, isJury bool) *TestManager { - bh := NewBabylonNodeHandler(t) - - err := bh.Start() +func StartManager(t *testing.T) *TestManager { + testDir, err := tempDirWithName("fpe2etest") require.NoError(t, err) - logger := logrus.New() - logger.SetLevel(logrus.DebugLevel) - logger.Out = os.Stdout - - // setup validator config - testDir, err := tempDirWithName("vale2etest") - require.NoError(t, err) + logger := zap.NewNop() - cfg := defaultValidatorConfig(bh.GetNodeDataDir(), testDir, isJury) + // 1. generate covenant committee + covenantQuorum := 2 + numCovenants := 3 + covenantPrivKeys, covenantPubKeys := generateCovenantCommittee(numCovenants, t) - bc, err := clientcontroller.NewBabylonController(bh.GetNodeDataDir(), cfg.BabylonConfig, logger) - // making sure the fee is sufficient - cfg.BabylonConfig.GasAdjustment = 1.5 - cfg.BabylonConfig.GasPrices = "0.1ubbn" + // 2. prepare Babylon node + bh := NewBabylonNodeHandler(t, covenantQuorum, covenantPubKeys) + err = bh.Start() + require.NoError(t, err) + fpHomeDir := filepath.Join(testDir, "fp-home") + cfg := defaultFpConfig(bh.GetNodeDataDir(), fpHomeDir) + bc, err := fpcc.NewBabylonController(cfg.BabylonConfig, &cfg.BTCNetParams, logger) require.NoError(t, err) - valApp, err := service.NewValidatorAppFromConfig(cfg, logger, bc) + // 3. prepare EOTS manager + eotsHomeDir := filepath.Join(testDir, "eots-home") + eotsCfg := defaultEOTSConfig() + eh := NewEOTSServerHandler(t, eotsCfg, eotsHomeDir) + eh.Start() + eotsCli, err := client.NewEOTSManagerGRpcClient(cfg.EOTSManagerAddress) require.NoError(t, err) - err = valApp.Start() + // 4. prepare finality-provider + fpApp, err := service.NewFinalityProviderApp(fpHomeDir, cfg, bc, eotsCli, logger) + require.NoError(t, err) + err = fpApp.Start() require.NoError(t, err) tm := &TestManager{ - BabylonHandler: bh, - Config: cfg, - Va: valApp, - BabylonClient: bc, + BabylonHandler: bh, + EOTSServerHandler: eh, + FpConfig: cfg, + EOTSConfig: eotsCfg, + Fpa: fpApp, + EOTSClient: eotsCli, + BBNClient: bc, + CovenantPrivKeys: covenantPrivKeys, + baseDir: testDir, } - tm.WaitForNodeStart(t) + tm.WaitForServicesStart(t) return tm } -func (tm *TestManager) WaitForNodeStart(t *testing.T) { - +func (tm *TestManager) WaitForServicesStart(t *testing.T) { + // wait for Babylon node starts require.Eventually(t, func() bool { - _, err := tm.BabylonClient.GetStakingParams() - - return err == nil + params, err := tm.BBNClient.QueryStakingParams() + if err != nil { + return false + } + tm.StakingParams = params + return true }, eventuallyWaitTimeOut, eventuallyPollTime) + + t.Logf("Babylon node is started") } -func StartManagerWithValidator(t *testing.T, n int, isJury bool) *TestManager { - tm := StartManager(t, isJury) - app := tm.Va +func StartManagerWithFinalityProvider(t *testing.T, n int) (*TestManager, []*service.FinalityProviderInstance) { + tm := StartManager(t) + app := tm.Fpa - var ( - valNamePrefix = "test-val-" - monikerPrefix = "moniker-" - ) for i := 0; i < n; i++ { - valName := valNamePrefix + strconv.Itoa(i) + fpName := fpNamePrefix + strconv.Itoa(i) moniker := monikerPrefix + strconv.Itoa(i) - commission := sdktypes.OneDec() - _, err := app.CreateValidator(valName, newDescription(moniker), &commission) + commission := sdkmath.LegacyZeroDec() + desc, err := newDescription(moniker).Marshal() + require.NoError(t, err) + cfg := app.GetConfig() + _, err = service.CreateChainKey(cfg.BabylonConfig.KeyDirectory, cfg.BabylonConfig.ChainID, fpName, keyring.BackendTest, passphrase, hdPath) + require.NoError(t, err) + res, err := app.CreateFinalityProvider(fpName, chainID, passphrase, hdPath, desc, &commission) require.NoError(t, err) - _, bbnPk, err := app.RegisterValidator(valName) + fpPk, err := bbntypes.NewBIP340PubKey(res.StoreFp.BtcPk) require.NoError(t, err) - err = app.StartHandlingValidator(bbnPk) + _, err = app.RegisterFinalityProvider(fpPk.MarshalHex()) require.NoError(t, err) - valIns, err := app.GetValidatorInstance(bbnPk) + err = app.StartHandlingFinalityProvider(fpPk, passphrase) require.NoError(t, err) - require.True(t, valIns.IsRunning()) + fpIns, err := app.GetFinalityProviderInstance(fpPk) + require.NoError(t, err) + require.True(t, fpIns.IsRunning()) require.NoError(t, err) - // check validators on Babylon side + // check finality providers on Babylon side require.Eventually(t, func() bool { - vals, err := tm.BabylonClient.QueryValidators() + fps, err := tm.BBNClient.QueryFinalityProviders() if err != nil { - t.Logf("failed to query validtors from Babylon %s", err.Error()) + t.Logf("failed to query finality providers from Babylon %s", err.Error()) return false } - if len(vals) != i+1 { + if len(fps) != i+1 { return false } - for _, v := range vals { - if !strings.Contains(v.Description.Moniker, monikerPrefix) { + for _, fp := range fps { + if !strings.Contains(fp.Description.Moniker, monikerPrefix) { return false } - if !v.Commission.Equal(sdktypes.OneDec()) { + if !fp.Commission.Equal(sdkmath.LegacyZeroDec()) { return false } } @@ -160,43 +196,43 @@ func StartManagerWithValidator(t *testing.T, n int, isJury bool) *TestManager { }, eventuallyWaitTimeOut, eventuallyPollTime) } - require.Equal(t, n, len(app.ListValidatorInstances())) + fpInsList := app.ListFinalityProviderInstances() + require.Equal(t, n, len(fpInsList)) - t.Logf("the test manager is running with %v validators", n) + t.Logf("the test manager is running with %v finality-provider(s)", len(fpInsList)) - return tm + return tm, fpInsList } func (tm *TestManager) Stop(t *testing.T) { - err := tm.Va.Stop() + err := tm.Fpa.Stop() require.NoError(t, err) err = tm.BabylonHandler.Stop() require.NoError(t, err) - err = os.RemoveAll(tm.Config.DatabaseConfig.Path) - require.NoError(t, err) - err = os.RemoveAll(tm.Config.BabylonConfig.KeyDirectory) + err = os.RemoveAll(tm.baseDir) require.NoError(t, err) + tm.EOTSServerHandler.Stop() } -func (tm *TestManager) WaitForValRegistered(t *testing.T, bbnPk *secp256k1.PubKey) { +func (tm *TestManager) WaitForFpRegistered(t *testing.T, bbnPk *secp256k1.PubKey) { require.Eventually(t, func() bool { - queriedValidators, err := tm.BabylonClient.QueryValidators() + queriedFps, err := tm.BBNClient.QueryFinalityProviders() if err != nil { return false } - return len(queriedValidators) == 1 && queriedValidators[0].BabylonPk.Equals(bbnPk) + return len(queriedFps) == 1 && queriedFps[0].BabylonPk.Equals(bbnPk) }, eventuallyWaitTimeOut, eventuallyPollTime) - t.Logf("the validator is successfully registered") + t.Logf("the finality-provider is successfully registered") } -func (tm *TestManager) WaitForValPubRandCommitted(t *testing.T, valIns *service.ValidatorInstance) { +func (tm *TestManager) WaitForFpPubRandCommitted(t *testing.T, fpIns *service.FinalityProviderInstance) { require.Eventually(t, func() bool { - randPairs, err := valIns.GetCommittedPubRandPairList() + lastCommittedHeight, err := fpIns.GetLastCommittedHeight() if err != nil { return false } - return int(tm.Config.NumPubRand) == len(randPairs) + return lastCommittedHeight > 0 }, eventuallyWaitTimeOut, eventuallyPollTime) t.Logf("public randomness is successfully committed") @@ -208,7 +244,9 @@ func (tm *TestManager) WaitForNPendingDels(t *testing.T, n int) []*bstypes.BTCDe err error ) require.Eventually(t, func() bool { - dels, err = tm.BabylonClient.QueryPendingBTCDelegations() + dels, err = tm.BBNClient.QueryPendingDelegations( + 100, + ) if err != nil { return false } @@ -220,56 +258,77 @@ func (tm *TestManager) WaitForNPendingDels(t *testing.T, n int) []*bstypes.BTCDe return dels } -func (tm *TestManager) WaitForValNActiveDels(t *testing.T, btcPk *bbntypes.BIP340PubKey, n int) []*bstypes.BTCDelegation { - var dels []*bstypes.BTCDelegation - currentBtcTip, err := tm.BabylonClient.QueryBtcLightClientTip() - require.NoError(t, err) - params, err := tm.BabylonClient.GetStakingParams() - require.NoError(t, err) +func (tm *TestManager) WaitForNActiveDels(t *testing.T, n int) []*bstypes.BTCDelegation { + var ( + dels []*bstypes.BTCDelegation + err error + ) require.Eventually(t, func() bool { - dels, err = tm.BabylonClient.QueryBTCValidatorDelegations(btcPk, 1000) + dels, err = tm.BBNClient.QueryActiveDelegations( + 100, + ) if err != nil { return false } - return len(dels) == n && CheckDelsStatus(dels, currentBtcTip.Height, params.FinalizationTimeoutBlocks, bstypes.BTCDelegationStatus_ACTIVE) + return len(dels) == n }, eventuallyWaitTimeOut, eventuallyPollTime) - t.Logf("the delegation is active, validators should start voting") + t.Logf("delegations are active") return dels } -func (tm *TestManager) WaitForValNUnbondingDels(t *testing.T, btcPk *bbntypes.BIP340PubKey, n int) []*bstypes.BTCDelegation { +func generateCovenantCommittee(numCovenants int, t *testing.T) ([]*btcec.PrivateKey, []*bbntypes.BIP340PubKey) { var ( - dels []*bstypes.BTCDelegation - err error + covenantPrivKeys []*btcec.PrivateKey + covenantPubKeys []*bbntypes.BIP340PubKey ) - // wait for our validator to: - // - detect new unbonding - // - send signature + + for i := 0; i < numCovenants; i++ { + privKey, err := btcec.NewPrivateKey() + require.NoError(t, err) + covenantPrivKeys = append(covenantPrivKeys, privKey) + pubKey := bbntypes.NewBIP340PubKeyFromBTCPK(privKey.PubKey()) + covenantPubKeys = append(covenantPubKeys, pubKey) + } + + return covenantPrivKeys, covenantPubKeys +} + +func (tm *TestManager) CheckBlockFinalization(t *testing.T, height uint64, num int) { + // we need to ensure votes are collected at the given height require.Eventually(t, func() bool { - dels, err = tm.BabylonClient.QueryBTCValidatorDelegations(btcPk, 1000) + votes, err := tm.BBNClient.QueryVotesAtHeight(height) if err != nil { + t.Logf("failed to get the votes at height %v: %s", height, err.Error()) return false } + return len(votes) == num + }, eventuallyWaitTimeOut, eventuallyPollTime) - return len(dels) == 1 && dels[0].BtcUndelegation != nil && dels[0].BtcUndelegation.ValidatorUnbondingSig != nil - - }, 1*time.Minute, eventuallyPollTime) - - return dels + // as the votes have been collected, the block should be finalized + require.Eventually(t, func() bool { + b, err := tm.BBNClient.QueryBlock(height) + if err != nil { + t.Logf("failed to query block at height %v: %s", height, err.Error()) + return false + } + return b.Finalized + }, eventuallyWaitTimeOut, eventuallyPollTime) } -func CheckDelsStatus(dels []*bstypes.BTCDelegation, btcHeight uint64, w uint64, status bstypes.BTCDelegationStatus) bool { - allChecked := true - for _, d := range dels { - s := d.GetStatus(btcHeight, w) - if s != status { - allChecked = false +func (tm *TestManager) WaitForFpVoteCast(t *testing.T, fpIns *service.FinalityProviderInstance) uint64 { + var lastVotedHeight uint64 + require.Eventually(t, func() bool { + if fpIns.GetLastVotedHeight() > 0 { + lastVotedHeight = fpIns.GetLastVotedHeight() + return true + } else { + return false } - } + }, eventuallyWaitTimeOut, eventuallyPollTime) - return allChecked + return lastVotedHeight } func (tm *TestManager) WaitForNFinalizedBlocks(t *testing.T, n int) []*types.BlockInfo { @@ -278,7 +337,7 @@ func (tm *TestManager) WaitForNFinalizedBlocks(t *testing.T, n int) []*types.Blo err error ) require.Eventually(t, func() bool { - blocks, err = tm.BabylonClient.QueryLatestFinalizedBlocks(uint64(n)) + blocks, err = tm.BBNClient.QueryLatestFinalizedBlocks(uint64(n)) if err != nil { t.Logf("failed to get the latest finalized block: %s", err.Error()) return false @@ -291,123 +350,187 @@ func (tm *TestManager) WaitForNFinalizedBlocks(t *testing.T, n int) []*types.Blo return blocks } -func (tm *TestManager) WaitForValStopped(t *testing.T, bbnPk *secp256k1.PubKey) { +func (tm *TestManager) WaitForFpShutDown(t *testing.T, pk *bbntypes.BIP340PubKey) { require.Eventually(t, func() bool { - _, err := tm.Va.GetValidatorInstance(bbnPk) + _, err := tm.Fpa.GetFinalityProviderInstance(pk) return err != nil }, eventuallyWaitTimeOut, eventuallyPollTime) + + t.Logf("the finality-provider instance %s is shutdown", pk.MarshalHex()) } -func (tm *TestManager) StopAndRestartValidatorAfterNBlocks(t *testing.T, n int, valIns *service.ValidatorInstance) { - headerBeforeStop, err := tm.BabylonClient.QueryBestHeader() +func (tm *TestManager) StopAndRestartFpAfterNBlocks(t *testing.T, n int, fpIns *service.FinalityProviderInstance) { + blockBeforeStop, err := tm.BBNClient.QueryBestBlock() require.NoError(t, err) - err = valIns.Stop() + err = fpIns.Stop() require.NoError(t, err) require.Eventually(t, func() bool { - headerAfterStop, err := tm.BabylonClient.QueryBestHeader() + headerAfterStop, err := tm.BBNClient.QueryBestBlock() if err != nil { return false } - return headerAfterStop.Header.Height >= int64(n)+headerBeforeStop.Header.Height + return headerAfterStop.Height >= uint64(n)+blockBeforeStop.Height }, eventuallyWaitTimeOut, eventuallyPollTime) - t.Log("restarting the validator instance") + t.Log("restarting the finality-provider instance") + + tm.FpConfig.PollerConfig.AutoChainScanningMode = true + err = fpIns.Start() + require.NoError(t, err) +} - tm.Config.ValidatorModeConfig.AutoChainScanningMode = true - err = valIns.Start() +func (tm *TestManager) GetFpPrivKey(t *testing.T, fpPk []byte) *btcec.PrivateKey { + record, err := tm.EOTSClient.KeyRecord(fpPk, passphrase) require.NoError(t, err) + return record.PrivKey } -func (tm *TestManager) AddJurySignature(t *testing.T, btcDel *bstypes.BTCDelegation) *provider.RelayerTxResponse { +func (tm *TestManager) InsertCovenantSigForDelegation(t *testing.T, btcDel *bstypes.BTCDelegation) { slashingTx := btcDel.SlashingTx stakingTx := btcDel.StakingTx - stakingMsgTx, err := stakingTx.ToMsgTx() + stakingMsgTx, err := bbntypes.NewBTCTxFromBytes(stakingTx) require.NoError(t, err) - // get Jury private key from the keyring - juryPrivKey := tm.GetJuryPrivKey(t) + params := tm.StakingParams - jurySig, err := slashingTx.Sign( - stakingMsgTx, - stakingTx.Script, - juryPrivKey, - &tm.Config.ActiveNetParams, + stakingInfo, err := btcstaking.BuildStakingInfo( + btcDel.BtcPk.MustToBTCPK(), + // TODO: Handle multiple providers + []*btcec.PublicKey{btcDel.FpBtcPkList[0].MustToBTCPK()}, + params.CovenantPks, + params.CovenantQuorum, + btcDel.GetStakingTime(), + btcutil.Amount(btcDel.TotalSat), + simnetParams, ) require.NoError(t, err) - - res, err := tm.BabylonClient.SubmitJurySig(btcDel.ValBtcPk, btcDel.BtcPk, stakingMsgTx.TxHash().String(), jurySig) + stakingTxUnbondingPathInfo, err := stakingInfo.UnbondingPathSpendInfo() require.NoError(t, err) - return res -} + idx, err := bbntypes.GetOutputIdxInBTCTx(stakingMsgTx, stakingInfo.StakingOutput) + require.NoError(t, err) -// delegation must containt undelgation object -func (tm *TestManager) AddValidatorUnbondingSignature( - t *testing.T, - btcDel *bstypes.BTCDelegation, - validatorSk *btcec.PrivateKey, -) { - stakingTx := btcDel.StakingTx - stakingMsgTx, err := stakingTx.ToMsgTx() + require.NoError(t, err) + slashingPathInfo, err := stakingInfo.SlashingPathSpendInfo() + require.NoError(t, err) + // get covenant private key from the keyring + valEncKey, err := asig.NewEncryptionKeyFromBTCPK(btcDel.FpBtcPkList[0].MustToBTCPK()) require.NoError(t, err) - unbondingTx := btcDel.BtcUndelegation.UnbondingTx + unbondingMsgTx, err := bbntypes.NewBTCTxFromBytes(btcDel.BtcUndelegation.UnbondingTx) + require.NoError(t, err) + unbondingInfo, err := btcstaking.BuildUnbondingInfo( + btcDel.BtcPk.MustToBTCPK(), + []*btcec.PublicKey{btcDel.FpBtcPkList[0].MustToBTCPK()}, + params.CovenantPks, + params.CovenantQuorum, + uint16(btcDel.UnbondingTime), + btcutil.Amount(unbondingMsgTx.TxOut[0].Value), + simnetParams, + ) + require.NoError(t, err) - valSig, err := unbondingTx.Sign( + // Covenant 0 signatures + covenantAdaptorStakingSlashing1, err := slashingTx.EncSign( stakingMsgTx, - stakingTx.Script, - validatorSk, - btcNetworkParams, + idx, + slashingPathInfo.RevealedLeaf.Script, + tm.CovenantPrivKeys[0], + valEncKey, + ) + require.NoError(t, err) + covenantUnbondingSig1, err := btcstaking.SignTxWithOneScriptSpendInputFromTapLeaf( + unbondingMsgTx, + stakingInfo.StakingOutput, + tm.CovenantPrivKeys[0], + stakingTxUnbondingPathInfo.RevealedLeaf, ) require.NoError(t, err) - stakingTxHash := stakingMsgTx.TxHash().String() + // slashing unbonding tx sig + unbondingTxSlashingPathInfo, err := unbondingInfo.SlashingPathSpendInfo() + require.NoError(t, err) + covenantAdaptorUnbondingSlashing1, err := btcDel.BtcUndelegation.SlashingTx.EncSign( + unbondingMsgTx, + 0, + unbondingTxSlashingPathInfo.RevealedLeaf.Script, + tm.CovenantPrivKeys[0], + valEncKey, + ) + require.NoError(t, err) - _, err = tm.BabylonClient.SubmitValidatorUnbondingSig( - btcDel.ValBtcPk, - btcDel.BtcPk, - stakingTxHash, - valSig, + _, err = tm.BBNClient.SubmitCovenantSigs( + tm.CovenantPrivKeys[0].PubKey(), + stakingMsgTx.TxHash().String(), + [][]byte{covenantAdaptorStakingSlashing1.MustMarshal()}, + covenantUnbondingSig1, + [][]byte{covenantAdaptorUnbondingSlashing1.MustMarshal()}, ) require.NoError(t, err) -} -func (tm *TestManager) GetJuryPrivKey(t *testing.T) *btcec.PrivateKey { - kr := tm.Va.GetKeyring() - juryKeyName := tm.BabylonHandler.GetJuryKeyName() - k, err := kr.Key(juryKeyName) + // Covenant 1 signatures + covenantAdaptorStakingSlashing2, err := slashingTx.EncSign( + stakingMsgTx, + idx, + slashingPathInfo.RevealedLeaf.Script, + tm.CovenantPrivKeys[1], + valEncKey, + ) + require.NoError(t, err) + covenantUnbondingSig2, err := btcstaking.SignTxWithOneScriptSpendInputFromTapLeaf( + unbondingMsgTx, + stakingInfo.StakingOutput, + tm.CovenantPrivKeys[1], + stakingTxUnbondingPathInfo.RevealedLeaf, + ) require.NoError(t, err) - localKey := k.GetLocal().PrivKey.GetCachedValue() - require.IsType(t, &secp256k1.PrivKey{}, localKey) - juryPrivKey, _ := btcec.PrivKeyFromBytes(localKey.(*secp256k1.PrivKey).Key) - return juryPrivKey -} -func (tm *TestManager) InsertBTCDelegation(t *testing.T, valBtcPk *btcec.PublicKey, stakingTime uint16, stakingAmount int64) *TestDelegationData { - r := rand.New(rand.NewSource(time.Now().UnixNano())) + // slashing unbonding tx sig + + covenantAdaptorUnbondingSlashing2, err := btcDel.BtcUndelegation.SlashingTx.EncSign( + unbondingMsgTx, + 0, + unbondingTxSlashingPathInfo.RevealedLeaf.Script, + tm.CovenantPrivKeys[1], + valEncKey, + ) - // examine staking params - params, err := tm.BabylonClient.GetStakingParams() - slashingAddr := params.SlashingAddress require.NoError(t, err) - require.Equal(t, tm.BabylonHandler.GetSlashingAddress(), slashingAddr) - require.Greater(t, stakingTime, uint16(params.ComfirmationTimeBlocks)) - juryPk, err := tm.Va.GetJuryPk() + _, err = tm.BBNClient.SubmitCovenantSigs( + tm.CovenantPrivKeys[1].PubKey(), + stakingMsgTx.TxHash().String(), + [][]byte{covenantAdaptorStakingSlashing2.MustMarshal()}, + covenantUnbondingSig2, + [][]byte{covenantAdaptorUnbondingSlashing2.MustMarshal()}, + ) require.NoError(t, err) - require.Equal(t, params.JuryPk.SerializeCompressed()[1:], juryPk.SerializeCompressed()[1:]) +} + +func (tm *TestManager) InsertBTCDelegation(t *testing.T, fpPks []*btcec.PublicKey, stakingTime uint16, stakingAmount int64) *TestDelegationData { + params := tm.StakingParams + r := rand.New(rand.NewSource(time.Now().UnixNano())) // delegator BTC key pairs, staking tx and slashing tx delBtcPrivKey, delBtcPubKey, err := datagen.GenRandomBTCKeyPair(r) require.NoError(t, err) - stakingTx, slashingTx, err := datagen.GenBTCStakingSlashingTx( - r, btcNetworkParams, delBtcPrivKey, valBtcPk, juryPk, stakingTime, stakingAmount, tm.BabylonHandler.GetSlashingAddress()) - require.NoError(t, err) - // get msgTx - stakingMsgTx, err := stakingTx.ToMsgTx() - require.NoError(t, err) + unbondingTime := uint16(tm.StakingParams.MinimumUnbondingTime()) + 1 + testStakingInfo := datagen.GenBTCStakingSlashingInfo( + r, + t, + btcNetworkParams, + delBtcPrivKey, + fpPks, + params.CovenantPks, + params.CovenantQuorum, + stakingTime, + stakingAmount, + params.SlashingAddress.String(), + params.SlashingRate, + unbondingTime, + ) // delegator Babylon key pairs delBabylonPrivKey, delBabylonPubKey, err := datagen.GenRandomSecp256k1KeyPair(r) @@ -418,9 +541,9 @@ func (tm *TestManager) InsertBTCDelegation(t *testing.T, valBtcPk *btcec.PublicK require.NoError(t, err) // create and insert BTC headers which include the staking tx to get staking tx info - currentBtcTip, err := tm.BabylonClient.QueryBtcLightClientTip() + currentBtcTip, err := tm.BBNClient.QueryBtcLightClientTip() require.NoError(t, err) - blockWithStakingTx := datagen.CreateBlockWithTransaction(r, currentBtcTip.Header.ToBlockHeader(), stakingMsgTx) + blockWithStakingTx := datagen.CreateBlockWithTransaction(r, currentBtcTip.Header.ToBlockHeader(), testStakingInfo.StakingTx) accumulatedWork := btclctypes.CalcWork(&blockWithStakingTx.HeaderBytes) accumulatedWork = btclctypes.CumulativeWork(accumulatedWork, *currentBtcTip.Work) parentBlockHeaderInfo := &btclctypes.BTCHeaderInfo{ @@ -429,116 +552,123 @@ func (tm *TestManager) InsertBTCDelegation(t *testing.T, valBtcPk *btcec.PublicK Height: currentBtcTip.Height + 1, Work: &accumulatedWork, } - headers := make([]*bbntypes.BTCHeaderBytes, 0) - headers = append(headers, &blockWithStakingTx.HeaderBytes) + headers := make([]bbntypes.BTCHeaderBytes, 0) + headers = append(headers, blockWithStakingTx.HeaderBytes) for i := 0; i < int(params.ComfirmationTimeBlocks); i++ { headerInfo := datagen.GenRandomValidBTCHeaderInfoWithParent(r, *parentBlockHeaderInfo) - headers = append(headers, headerInfo.Header) + headers = append(headers, *headerInfo.Header) parentBlockHeaderInfo = headerInfo } - _, err = tm.BabylonClient.InsertBtcBlockHeaders(headers) + _, err = tm.BBNClient.InsertBtcBlockHeaders(headers) require.NoError(t, err) btcHeader := blockWithStakingTx.HeaderBytes - txInfo := btcctypes.NewTransactionInfo(&btcctypes.TransactionKey{Index: 1, Hash: btcHeader.Hash()}, stakingTx.Tx, blockWithStakingTx.SpvProof.MerkleNodes) + serializedStakingTx, err := bbntypes.SerializeBTCTx(testStakingInfo.StakingTx) + require.NoError(t, err) + txInfo := btcctypes.NewTransactionInfo(&btcctypes.TransactionKey{Index: 1, Hash: btcHeader.Hash()}, serializedStakingTx, blockWithStakingTx.SpvProof.MerkleNodes) + + slashignSpendInfo, err := testStakingInfo.StakingInfo.SlashingPathSpendInfo() + require.NoError(t, err) // delegator sig - delegatorSig, err := slashingTx.Sign( - stakingMsgTx, - stakingTx.Script, + delegatorSig, err := testStakingInfo.SlashingTx.Sign( + testStakingInfo.StakingTx, + 0, + slashignSpendInfo.GetPkScriptPath(), delBtcPrivKey, + ) + require.NoError(t, err) + + unbondingValue := stakingAmount - 1000 + stakingTxHash := testStakingInfo.StakingTx.TxHash() + + testUnbondingInfo := datagen.GenBTCUnbondingSlashingInfo( + r, + t, btcNetworkParams, + delBtcPrivKey, + fpPks, + params.CovenantPks, + params.CovenantQuorum, + wire.NewOutPoint(&stakingTxHash, 0), + unbondingTime, + unbondingValue, + params.SlashingAddress.String(), + params.SlashingRate, + unbondingTime, ) + + unbondingTxMsg := testUnbondingInfo.UnbondingTx + + unbondingSlashingPathInfo, err := testUnbondingInfo.UnbondingInfo.SlashingPathSpendInfo() require.NoError(t, err) - // submit the BTC delegation to Babylon - _, err = tm.BabylonClient.CreateBTCDelegation( - delBabylonPubKey.(*secp256k1.PubKey), pop, stakingTx, txInfo, slashingTx, delegatorSig) + unbondingSig, err := testUnbondingInfo.SlashingTx.Sign( + unbondingTxMsg, + 0, + unbondingSlashingPathInfo.GetPkScriptPath(), + delBtcPrivKey, + ) require.NoError(t, err) + serializedUnbondingTx, err := bbntypes.SerializeBTCTx(testUnbondingInfo.UnbondingTx) + require.NoError(t, err) + + // submit the BTC delegation to Babylon + _, err = tm.BBNClient.CreateBTCDelegation( + delBabylonPubKey.(*secp256k1.PubKey), + bbntypes.NewBIP340PubKeyFromBTCPK(delBtcPubKey), + fpPks, + pop, + uint32(stakingTime), + stakingAmount, + txInfo, + testStakingInfo.SlashingTx, + delegatorSig, + serializedUnbondingTx, + uint32(unbondingTime), + unbondingValue, + testUnbondingInfo.SlashingTx, + unbondingSig) + require.NoError(t, err) + + t.Log("successfully submitted a BTC delegation") + return &TestDelegationData{ DelegatorPrivKey: delBtcPrivKey, DelegatorKey: delBtcPubKey, DelegatorBabylonPrivKey: delBabylonPrivKey.(*secp256k1.PrivKey), DelegatorBabylonKey: delBabylonPubKey.(*secp256k1.PubKey), - StakingTx: stakingTx, - SlashingTx: slashingTx, + FpPks: fpPks, + StakingTx: testStakingInfo.StakingTx, + SlashingTx: testStakingInfo.SlashingTx, StakingTxInfo: txInfo, DelegatorSig: delegatorSig, - SlashingAddr: tm.BabylonHandler.GetSlashingAddress(), + SlashingAddr: params.SlashingAddress.String(), StakingTime: stakingTime, StakingAmount: stakingAmount, } } -func (tm *TestManager) InsertBTCUnbonding( - t *testing.T, - stakingTx *bstypes.BabylonBTCTaprootTx, - stakerPrivKey *btcec.PrivateKey, - validatorPk *btcec.PublicKey, -) { - r := rand.New(rand.NewSource(time.Now().UnixNano())) - params, err := tm.BabylonClient.GetStakingParams() - require.NoError(t, err) - slashingAddr := params.SlashingAddress - stakingMsgTx, err := stakingTx.ToMsgTx() - require.NoError(t, err) - stakingTxHash := stakingTx.MustGetTxHash() - stakingTxChainHash, err := chainhash.NewHashFromStr(stakingTxHash) - require.NoError(t, err) - - stakingOutputIdx, err := btcstaking.GetIdxOutputCommitingToScript( - stakingMsgTx, stakingTx.Script, btcNetworkParams, - ) - require.NoError(t, err) - - stakingValue := stakingMsgTx.TxOut[stakingOutputIdx].Value - fee := int64(1000) - - unbondingTx, slashUnbondingTx, err := datagen.GenBTCUnbondingSlashingTx( - r, - btcNetworkParams, - stakerPrivKey, - validatorPk, - params.JuryPk, - wire.NewOutPoint(stakingTxChainHash, uint32(stakingOutputIdx)), - uint16(params.FinalizationTimeoutBlocks)+1, - stakingValue-fee, - slashingAddr, - ) - require.NoError(t, err) - - unbondingTxMsg, err := unbondingTx.ToMsgTx() - require.NoError(t, err) +func defaultFpConfig(keyringDir, homeDir string) *fpcfg.Config { + cfg := fpcfg.DefaultConfigWithHome(homeDir) - slashingTxSig, err := slashUnbondingTx.Sign( - unbondingTxMsg, - unbondingTx.Script, - stakerPrivKey, - btcNetworkParams, - ) - require.NoError(t, err) + cfg.BitcoinNetwork = "simnet" + cfg.BTCNetParams = chaincfg.SimNetParams - _, err = tm.BabylonClient.CreateBTCUndelegation( - unbondingTx, slashUnbondingTx, slashingTxSig, - ) - require.NoError(t, err) -} - -func defaultValidatorConfig(keyringDir, testDir string, isJury bool) *valcfg.Config { - cfg := valcfg.DefaultConfig() - - cfg.ValidatorModeConfig.AutoChainScanningMode = false + cfg.PollerConfig.AutoChainScanningMode = false // babylon configs for sending transactions cfg.BabylonConfig.KeyDirectory = keyringDir // need to use this one to send otherwise we will have account sequence mismatch // errors cfg.BabylonConfig.Key = "test-spending-key" // Big adjustment to make sure we have enough gas in our transactions - cfg.BabylonConfig.GasAdjustment = 5 - cfg.DatabaseConfig.Path = filepath.Join(testDir, "db") - cfg.JuryMode = isJury - cfg.JuryModeConfig.QueryInterval = 7 * time.Second - cfg.UnbondingSigSubmissionInterval = 3 * time.Second + cfg.BabylonConfig.GasAdjustment = 20 + + return &cfg +} + +func defaultEOTSConfig() *eotsconfig.Config { + cfg := eotsconfig.DefaultConfig() return &cfg } diff --git a/itest/utils.go b/itest/utils.go new file mode 100644 index 00000000..ee51188a --- /dev/null +++ b/itest/utils.go @@ -0,0 +1,20 @@ +package e2etest + +import "os" + +func baseDir(pattern string) (string, error) { + tempPath := os.TempDir() + + tempName, err := os.MkdirTemp(tempPath, pattern) + if err != nil { + return "", err + } + + err = os.Chmod(tempName, 0755) + + if err != nil { + return "", err + } + + return tempName, nil +} diff --git a/service/keyring.go b/keyring/keyring.go similarity index 82% rename from service/keyring.go rename to keyring/keyring.go index bef3a482..36b526b3 100644 --- a/service/keyring.go +++ b/keyring/keyring.go @@ -1,17 +1,18 @@ -package service +package keyring import ( "fmt" "os" "path" + "strings" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/crypto/keyring" - "github.com/babylonchain/btc-validator/codec" + "github.com/babylonchain/finality-provider/codec" ) -func CreateKeyring(keyringDir string, chainId string, backend string) (keyring.Keyring, error) { +func CreateKeyring(keyringDir string, chainId string, backend string, input *strings.Reader) (keyring.Keyring, error) { ctx, err := CreateClientCtx(keyringDir, chainId) if err != nil { return nil, err @@ -25,7 +26,7 @@ func CreateKeyring(keyringDir string, chainId string, backend string) (keyring.K ctx.ChainID, backend, ctx.KeyringDir, - ctx.Input, + input, ctx.Codec, ctx.KeyringOptions...) if err != nil { @@ -44,7 +45,7 @@ func CreateClientCtx(keyringDir string, chainId string) (client.Context, error) if err != nil { return client.Context{}, err } - keyringDir = path.Join(homeDir, ".btc-validator") + keyringDir = path.Join(homeDir, ".finality-provider") } return client.Context{}. diff --git a/keyring/keyringcontroller.go b/keyring/keyringcontroller.go new file mode 100644 index 00000000..14e2cca7 --- /dev/null +++ b/keyring/keyringcontroller.go @@ -0,0 +1,146 @@ +package keyring + +import ( + "fmt" + "strings" + + bstypes "github.com/babylonchain/babylon/x/btcstaking/types" + "github.com/btcsuite/btcd/btcec/v2" + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + sdksecp256k1 "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + "github.com/cosmos/go-bip39" + + "github.com/babylonchain/finality-provider/types" +) + +const ( + secp256k1Type = "secp256k1" + mnemonicEntropySize = 256 +) + +type ChainKeyringController struct { + kr keyring.Keyring + fpName string + // input is to send passphrase to kr + input *strings.Reader +} + +func NewChainKeyringController(ctx client.Context, name, keyringBackend string) (*ChainKeyringController, error) { + if name == "" { + return nil, fmt.Errorf("the key name should not be empty") + } + + if keyringBackend == "" { + return nil, fmt.Errorf("the keyring backend should not be empty") + } + + inputReader := strings.NewReader("") + kr, err := keyring.New( + ctx.ChainID, + keyringBackend, + ctx.KeyringDir, + inputReader, + ctx.Codec, + ctx.KeyringOptions...) + if err != nil { + return nil, fmt.Errorf("failed to create keyring: %w", err) + } + + return &ChainKeyringController{ + fpName: name, + kr: kr, + input: inputReader, + }, nil +} + +func NewChainKeyringControllerWithKeyring(kr keyring.Keyring, name string, input *strings.Reader) (*ChainKeyringController, error) { + if name == "" { + return nil, fmt.Errorf("the key name should not be empty") + } + + return &ChainKeyringController{ + kr: kr, + fpName: name, + input: input, + }, nil +} + +func (kc *ChainKeyringController) GetKeyring() keyring.Keyring { + return kc.kr +} + +func (kc *ChainKeyringController) CreateChainKey(passphrase, hdPath string) (*types.ChainKeyInfo, error) { + keyringAlgos, _ := kc.kr.SupportedAlgorithms() + algo, err := keyring.NewSigningAlgoFromString(secp256k1Type, keyringAlgos) + if err != nil { + return nil, err + } + + // read entropy seed straight from tmcrypto.Rand and convert to mnemonic + entropySeed, err := bip39.NewEntropy(mnemonicEntropySize) + if err != nil { + return nil, err + } + + mnemonic, err := bip39.NewMnemonic(entropySeed) + if err != nil { + return nil, err + } + + // we need to repeat the passphrase to mock the reentry + kc.input.Reset(passphrase + "\n" + passphrase) + record, err := kc.kr.NewAccount(kc.fpName, mnemonic, passphrase, hdPath, algo) + if err != nil { + return nil, err + } + + privKey := record.GetLocal().PrivKey.GetCachedValue() + accAddress, err := record.GetAddress() + if err != nil { + return nil, err + } + + switch v := privKey.(type) { + case *sdksecp256k1.PrivKey: + sk, pk := btcec.PrivKeyFromBytes(v.Key) + return &types.ChainKeyInfo{ + Name: kc.fpName, + AccAddress: accAddress, + PublicKey: pk, + PrivateKey: sk, + Mnemonic: mnemonic, + }, nil + default: + return nil, fmt.Errorf("unsupported key type in keyring") + } +} + +// CreatePop creates proof-of-possession of Babylon and BTC public keys +// the input is the bytes of BTC public key used to sign +// this requires both keys created beforehand +func (kc *ChainKeyringController) CreatePop(btcPrivKey *btcec.PrivateKey, passphrase string) (*bstypes.ProofOfPossession, error) { + bbnPrivKey, err := kc.GetChainPrivKey(passphrase) + if err != nil { + return nil, err + } + + return bstypes.NewPoP(bbnPrivKey, btcPrivKey) +} + +func (kc *ChainKeyringController) GetChainPrivKey(passphrase string) (*sdksecp256k1.PrivKey, error) { + kc.input.Reset(passphrase) + k, err := kc.kr.Key(kc.fpName) + if err != nil { + return nil, fmt.Errorf("failed to get private key: %w", err) + } + + privKeyCached := k.GetLocal().PrivKey.GetCachedValue() + + switch v := privKeyCached.(type) { + case *sdksecp256k1.PrivKey: + return v, nil + default: + return nil, fmt.Errorf("unsupported key type in keyring") + } +} diff --git a/keyring/keyringcontroller_test.go b/keyring/keyringcontroller_test.go new file mode 100644 index 00000000..d63c8a71 --- /dev/null +++ b/keyring/keyringcontroller_test.go @@ -0,0 +1,71 @@ +package keyring_test + +import ( + "math/rand" + "os" + "path/filepath" + "testing" + + "go.uber.org/zap" + + fpstore "github.com/babylonchain/finality-provider/finality-provider/store" + + "github.com/babylonchain/babylon/types" + "github.com/btcsuite/btcd/chaincfg" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + "github.com/stretchr/testify/require" + + fpkr "github.com/babylonchain/finality-provider/keyring" + + "github.com/babylonchain/finality-provider/eotsmanager" + "github.com/babylonchain/finality-provider/testutil" +) + +var ( + passphrase = "testpass" + hdPath = "" +) + +// FuzzCreatePoP tests the creation of PoP +func FuzzCreatePoP(f *testing.F) { + testutil.AddRandomSeedsToFuzzer(f, 10) + f.Fuzz(func(t *testing.T, seed int64) { + r := rand.New(rand.NewSource(seed)) + + keyName := testutil.GenRandomHexStr(r, 4) + sdkCtx := testutil.GenSdkContext(r, t) + + chainID := testutil.GenRandomHexStr(r, 4) + kc, err := fpkr.NewChainKeyringController(sdkCtx, keyName, keyring.BackendTest) + require.NoError(t, err) + + eotsHome := filepath.Join(t.TempDir(), "eots-home") + cfg := testutil.GenEOTSConfig(r, t) + em, err := eotsmanager.NewLocalEOTSManager(eotsHome, cfg, zap.NewNop()) + defer func() { + err := os.RemoveAll(eotsHome) + require.NoError(t, err) + }() + require.NoError(t, err) + + btcPkBytes, err := em.CreateKey(keyName, passphrase, hdPath) + require.NoError(t, err) + btcPk, err := types.NewBIP340PubKey(btcPkBytes) + require.NoError(t, err) + keyInfo, err := kc.CreateChainKey(passphrase, hdPath) + require.NoError(t, err) + bbnPk := &secp256k1.PubKey{Key: keyInfo.PublicKey.SerializeCompressed()} + fpRecord, err := em.KeyRecord(btcPk.MustMarshal(), passphrase) + require.NoError(t, err) + pop, err := kc.CreatePop(fpRecord.PrivKey, passphrase) + require.NoError(t, err) + fp := fpstore.NewStoreFinalityProvider(bbnPk, btcPk, keyName, chainID, pop, testutil.EmptyDescription(), testutil.ZeroCommissionRate()) + + btcSig := new(types.BIP340Signature) + err = btcSig.Unmarshal(fp.Pop.BtcSig) + require.NoError(t, err) + err = pop.Verify(bbnPk, btcPk, &chaincfg.SimNetParams) + require.NoError(t, err) + }) +} diff --git a/log/log.go b/log/log.go new file mode 100644 index 00000000..fd3643c4 --- /dev/null +++ b/log/log.go @@ -0,0 +1,76 @@ +package log + +import ( + "fmt" + "github.com/babylonchain/finality-provider/util" + "io" + "os" + "path/filepath" + "strings" + "time" + + zaplogfmt "github.com/jsternberg/zap-logfmt" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" +) + +func NewRootLogger(format string, level string, w io.Writer) (*zap.Logger, error) { + cfg := zap.NewProductionEncoderConfig() + cfg.EncodeTime = func(ts time.Time, encoder zapcore.PrimitiveArrayEncoder) { + encoder.AppendString(ts.UTC().Format("2006-01-02T15:04:05.000000Z07:00")) + } + cfg.LevelKey = "lvl" + + var enc zapcore.Encoder + switch format { + case "json": + enc = zapcore.NewJSONEncoder(cfg) + case "auto", "console": + enc = zapcore.NewConsoleEncoder(cfg) + case "logfmt": + enc = zaplogfmt.NewEncoder(cfg) + default: + return nil, fmt.Errorf("unrecognized log format %q", format) + } + + var lvl zapcore.Level + switch strings.ToLower(level) { + case "panic": + lvl = zap.PanicLevel + case "fatal": + lvl = zap.FatalLevel + case "error": + lvl = zap.ErrorLevel + case "warn", "warning": + lvl = zap.WarnLevel + case "info": + lvl = zap.InfoLevel + case "debug": + lvl = zap.DebugLevel + default: + return nil, fmt.Errorf("unsupported log level: %s", level) + } + + return zap.New(zapcore.NewCore( + enc, + zapcore.AddSync(w), + lvl, + )), nil +} + +func NewRootLoggerWithFile(logFile string, level string) (*zap.Logger, error) { + if err := util.MakeDirectory(filepath.Dir(logFile)); err != nil { + return nil, err + } + f, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) + if err != nil { + return nil, err + } + mw := io.MultiWriter(os.Stdout, f) + + logger, err := NewRootLogger("console", level, mw) + if err != nil { + return nil, err + } + return logger, nil +} diff --git a/proto/validators.go b/proto/validators.go deleted file mode 100644 index 29a5ce3b..00000000 --- a/proto/validators.go +++ /dev/null @@ -1,54 +0,0 @@ -package proto - -import ( - "encoding/hex" - "fmt" - - bbn "github.com/babylonchain/babylon/types" - "github.com/btcsuite/btcd/btcec/v2" - "github.com/btcsuite/btcd/btcec/v2/schnorr" - "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" -) - -func (v *StoreValidator) GetBabylonPK() *secp256k1.PubKey { - return &secp256k1.PubKey{ - Key: v.BabylonPk, - } -} - -func NewBabylonPkFromHex(hexStr string) (*secp256k1.PubKey, error) { - pkBytes, err := hex.DecodeString(hexStr) - if err != nil { - return nil, err - } - - return &secp256k1.PubKey{Key: pkBytes}, nil -} - -func (v *StoreValidator) GetBabylonPkHexString() string { - return hex.EncodeToString(v.BabylonPk) -} - -func (v *StoreValidator) MustGetBTCPK() *btcec.PublicKey { - btcPubKey, err := schnorr.ParsePubKey(v.BtcPk) - if err != nil { - panic(fmt.Errorf("failed to parse BTC PK: %w", err)) - } - return btcPubKey -} - -func (v *StoreValidator) MustGetBIP340BTCPK() *bbn.BIP340PubKey { - btcPK := v.MustGetBTCPK() - return bbn.NewBIP340PubKeyFromBTCPK(btcPK) -} - -func NewValidatorInfo(v *StoreValidator) *ValidatorInfo { - return &ValidatorInfo{ - BabylonPkHex: v.GetBabylonPkHexString(), - BtcPkHex: v.MustGetBIP340BTCPK().MarshalHex(), - Description: v.Description, - LastVotedHeight: v.LastVotedHeight, - LastCommittedHeight: v.LastCommittedHeight, - Status: v.Status, - } -} diff --git a/proto/validators.pb.go b/proto/validators.pb.go deleted file mode 100644 index ba2522ef..00000000 --- a/proto/validators.pb.go +++ /dev/null @@ -1,1536 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.31.0 -// protoc (unknown) -// source: validators.proto - -package proto - -import ( - _ "github.com/cosmos/cosmos-proto" - types "github.com/cosmos/cosmos-sdk/x/staking/types" - _ "github.com/cosmos/gogoproto/gogoproto" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// ValidatorStatus is the status of a BTC validator -// a Validator object has 4 states: -// - Created - created and managed by validator client, not registered to -// babylon yet -// - Registered - created and registered to Babylon, but not voting yet (No -// delegated stake) -// - Active - created and registered to Babylon with stake to vote -// - Inactive - created and registered to Babylon with no stake to vote. -// Validator was already active. -// -// Valid State Transactions: -// - Created -> Registered -// - Registered -> Active -// - Active -> Inactive -// - Inactive -> Active -type ValidatorStatus int32 - -const ( - // CREATED defines a validator that is awaiting registration - ValidatorStatus_CREATED ValidatorStatus = 0 - // REGISTERED defines a validator that has been registered - // to Babylon but has no delegated stake - ValidatorStatus_REGISTERED ValidatorStatus = 1 - // ACTIVE defines a validator that is delegated to vote - ValidatorStatus_ACTIVE ValidatorStatus = 2 - // INACTIVE defines a validator whose delegations are reduced to zero but not slashed - ValidatorStatus_INACTIVE ValidatorStatus = 3 - // SLASHED defines a validator that has been slashed - ValidatorStatus_SLASHED ValidatorStatus = 4 -) - -// Enum value maps for ValidatorStatus. -var ( - ValidatorStatus_name = map[int32]string{ - 0: "CREATED", - 1: "REGISTERED", - 2: "ACTIVE", - 3: "INACTIVE", - 4: "SLASHED", - } - ValidatorStatus_value = map[string]int32{ - "CREATED": 0, - "REGISTERED": 1, - "ACTIVE": 2, - "INACTIVE": 3, - "SLASHED": 4, - } -) - -func (x ValidatorStatus) Enum() *ValidatorStatus { - p := new(ValidatorStatus) - *p = x - return p -} - -func (x ValidatorStatus) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (ValidatorStatus) Descriptor() protoreflect.EnumDescriptor { - return file_validators_proto_enumTypes[0].Descriptor() -} - -func (ValidatorStatus) Type() protoreflect.EnumType { - return &file_validators_proto_enumTypes[0] -} - -func (x ValidatorStatus) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use ValidatorStatus.Descriptor instead. -func (ValidatorStatus) EnumDescriptor() ([]byte, []int) { - return file_validators_proto_rawDescGZIP(), []int{0} -} - -type GetInfoRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *GetInfoRequest) Reset() { - *x = GetInfoRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_validators_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetInfoRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetInfoRequest) ProtoMessage() {} - -func (x *GetInfoRequest) ProtoReflect() protoreflect.Message { - mi := &file_validators_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetInfoRequest.ProtoReflect.Descriptor instead. -func (*GetInfoRequest) Descriptor() ([]byte, []int) { - return file_validators_proto_rawDescGZIP(), []int{0} -} - -type GetInfoResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` -} - -func (x *GetInfoResponse) Reset() { - *x = GetInfoResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_validators_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetInfoResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetInfoResponse) ProtoMessage() {} - -func (x *GetInfoResponse) ProtoReflect() protoreflect.Message { - mi := &file_validators_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetInfoResponse.ProtoReflect.Descriptor instead. -func (*GetInfoResponse) Descriptor() ([]byte, []int) { - return file_validators_proto_rawDescGZIP(), []int{1} -} - -func (x *GetInfoResponse) GetVersion() string { - if x != nil { - return x.Version - } - return "" -} - -type CreateValidatorRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // key_name is the identifier key in keyring - KeyName string `protobuf:"bytes,1,opt,name=key_name,json=keyName,proto3" json:"key_name,omitempty"` - // description defines the description terms for the validator - Description *types.Description `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` - // commission defines the commission rate for the validator - // TODO failed to use the customized type: github.com/cosmos/cosmos-sdk/types.Dec - Commission string `protobuf:"bytes,3,opt,name=commission,proto3" json:"commission,omitempty"` -} - -func (x *CreateValidatorRequest) Reset() { - *x = CreateValidatorRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_validators_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *CreateValidatorRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CreateValidatorRequest) ProtoMessage() {} - -func (x *CreateValidatorRequest) ProtoReflect() protoreflect.Message { - mi := &file_validators_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use CreateValidatorRequest.ProtoReflect.Descriptor instead. -func (*CreateValidatorRequest) Descriptor() ([]byte, []int) { - return file_validators_proto_rawDescGZIP(), []int{2} -} - -func (x *CreateValidatorRequest) GetKeyName() string { - if x != nil { - return x.KeyName - } - return "" -} - -func (x *CreateValidatorRequest) GetDescription() *types.Description { - if x != nil { - return x.Description - } - return nil -} - -func (x *CreateValidatorRequest) GetCommission() string { - if x != nil { - return x.Commission - } - return "" -} - -type CreateValidatorResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // babylon_pk is the Babylon secp256k1 PK of this BTC validator - BabylonPk string `protobuf:"bytes,1,opt,name=babylon_pk,json=babylonPk,proto3" json:"babylon_pk,omitempty"` - // btc_pk is the BTC secp256k1 PK of the validator encoded in BIP-340 spec - BtcPk string `protobuf:"bytes,2,opt,name=btc_pk,json=btcPk,proto3" json:"btc_pk,omitempty"` -} - -func (x *CreateValidatorResponse) Reset() { - *x = CreateValidatorResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_validators_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *CreateValidatorResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CreateValidatorResponse) ProtoMessage() {} - -func (x *CreateValidatorResponse) ProtoReflect() protoreflect.Message { - mi := &file_validators_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use CreateValidatorResponse.ProtoReflect.Descriptor instead. -func (*CreateValidatorResponse) Descriptor() ([]byte, []int) { - return file_validators_proto_rawDescGZIP(), []int{3} -} - -func (x *CreateValidatorResponse) GetBabylonPk() string { - if x != nil { - return x.BabylonPk - } - return "" -} - -func (x *CreateValidatorResponse) GetBtcPk() string { - if x != nil { - return x.BtcPk - } - return "" -} - -type RegisterValidatorRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // the key name of the BTC validator - KeyName string `protobuf:"bytes,1,opt,name=key_name,json=keyName,proto3" json:"key_name,omitempty"` -} - -func (x *RegisterValidatorRequest) Reset() { - *x = RegisterValidatorRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_validators_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RegisterValidatorRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RegisterValidatorRequest) ProtoMessage() {} - -func (x *RegisterValidatorRequest) ProtoReflect() protoreflect.Message { - mi := &file_validators_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RegisterValidatorRequest.ProtoReflect.Descriptor instead. -func (*RegisterValidatorRequest) Descriptor() ([]byte, []int) { - return file_validators_proto_rawDescGZIP(), []int{4} -} - -func (x *RegisterValidatorRequest) GetKeyName() string { - if x != nil { - return x.KeyName - } - return "" -} - -type RegisterValidatorResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // hash of the successful Babylon registration transaction - TxHash string `protobuf:"bytes,1,opt,name=tx_hash,json=txHash,proto3" json:"tx_hash,omitempty"` -} - -func (x *RegisterValidatorResponse) Reset() { - *x = RegisterValidatorResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_validators_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RegisterValidatorResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RegisterValidatorResponse) ProtoMessage() {} - -func (x *RegisterValidatorResponse) ProtoReflect() protoreflect.Message { - mi := &file_validators_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RegisterValidatorResponse.ProtoReflect.Descriptor instead. -func (*RegisterValidatorResponse) Descriptor() ([]byte, []int) { - return file_validators_proto_rawDescGZIP(), []int{5} -} - -func (x *RegisterValidatorResponse) GetTxHash() string { - if x != nil { - return x.TxHash - } - return "" -} - -type AddFinalitySignatureRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // babylon_pk is the Babylon secp256k1 PK of this BTC validator - BabylonPk []byte `protobuf:"bytes,1,opt,name=babylon_pk,json=babylonPk,proto3" json:"babylon_pk,omitempty"` - // height is the height of the Babylon block - Height uint64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` - // last_commit_hash is the last commit hash of the Babylon block - LastCommitHash []byte `protobuf:"bytes,3,opt,name=last_commit_hash,json=lastCommitHash,proto3" json:"last_commit_hash,omitempty"` -} - -func (x *AddFinalitySignatureRequest) Reset() { - *x = AddFinalitySignatureRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_validators_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AddFinalitySignatureRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AddFinalitySignatureRequest) ProtoMessage() {} - -func (x *AddFinalitySignatureRequest) ProtoReflect() protoreflect.Message { - mi := &file_validators_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AddFinalitySignatureRequest.ProtoReflect.Descriptor instead. -func (*AddFinalitySignatureRequest) Descriptor() ([]byte, []int) { - return file_validators_proto_rawDescGZIP(), []int{6} -} - -func (x *AddFinalitySignatureRequest) GetBabylonPk() []byte { - if x != nil { - return x.BabylonPk - } - return nil -} - -func (x *AddFinalitySignatureRequest) GetHeight() uint64 { - if x != nil { - return x.Height - } - return 0 -} - -func (x *AddFinalitySignatureRequest) GetLastCommitHash() []byte { - if x != nil { - return x.LastCommitHash - } - return nil -} - -type AddFinalitySignatureResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // hash of the successful Babylon finality signature submission transaction - TxHash string `protobuf:"bytes,1,opt,name=tx_hash,json=txHash,proto3" json:"tx_hash,omitempty"` - // the hex string of the extracted Bitcoin secp256k1 private key - ExtractedSkHex string `protobuf:"bytes,2,opt,name=extracted_sk_hex,json=extractedSkHex,proto3" json:"extracted_sk_hex,omitempty"` - // the hex string of the local Bitcoin secp256k1 private key - LocalSkHex string `protobuf:"bytes,3,opt,name=local_sk_hex,json=localSkHex,proto3" json:"local_sk_hex,omitempty"` -} - -func (x *AddFinalitySignatureResponse) Reset() { - *x = AddFinalitySignatureResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_validators_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AddFinalitySignatureResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AddFinalitySignatureResponse) ProtoMessage() {} - -func (x *AddFinalitySignatureResponse) ProtoReflect() protoreflect.Message { - mi := &file_validators_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AddFinalitySignatureResponse.ProtoReflect.Descriptor instead. -func (*AddFinalitySignatureResponse) Descriptor() ([]byte, []int) { - return file_validators_proto_rawDescGZIP(), []int{7} -} - -func (x *AddFinalitySignatureResponse) GetTxHash() string { - if x != nil { - return x.TxHash - } - return "" -} - -func (x *AddFinalitySignatureResponse) GetExtractedSkHex() string { - if x != nil { - return x.ExtractedSkHex - } - return "" -} - -func (x *AddFinalitySignatureResponse) GetLocalSkHex() string { - if x != nil { - return x.LocalSkHex - } - return "" -} - -type QueryValidatorRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // babylon_pk is the Babylon secp256k1 PK of this BTC validator - BabylonPk []byte `protobuf:"bytes,1,opt,name=babylon_pk,json=babylonPk,proto3" json:"babylon_pk,omitempty"` -} - -func (x *QueryValidatorRequest) Reset() { - *x = QueryValidatorRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_validators_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *QueryValidatorRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*QueryValidatorRequest) ProtoMessage() {} - -func (x *QueryValidatorRequest) ProtoReflect() protoreflect.Message { - mi := &file_validators_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use QueryValidatorRequest.ProtoReflect.Descriptor instead. -func (*QueryValidatorRequest) Descriptor() ([]byte, []int) { - return file_validators_proto_rawDescGZIP(), []int{8} -} - -func (x *QueryValidatorRequest) GetBabylonPk() []byte { - if x != nil { - return x.BabylonPk - } - return nil -} - -type QueryValidatorResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Validator *ValidatorInfo `protobuf:"bytes,1,opt,name=validator,proto3" json:"validator,omitempty"` -} - -func (x *QueryValidatorResponse) Reset() { - *x = QueryValidatorResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_validators_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *QueryValidatorResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*QueryValidatorResponse) ProtoMessage() {} - -func (x *QueryValidatorResponse) ProtoReflect() protoreflect.Message { - mi := &file_validators_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use QueryValidatorResponse.ProtoReflect.Descriptor instead. -func (*QueryValidatorResponse) Descriptor() ([]byte, []int) { - return file_validators_proto_rawDescGZIP(), []int{9} -} - -func (x *QueryValidatorResponse) GetValidator() *ValidatorInfo { - if x != nil { - return x.Validator - } - return nil -} - -type QueryValidatorListRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *QueryValidatorListRequest) Reset() { - *x = QueryValidatorListRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_validators_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *QueryValidatorListRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*QueryValidatorListRequest) ProtoMessage() {} - -func (x *QueryValidatorListRequest) ProtoReflect() protoreflect.Message { - mi := &file_validators_proto_msgTypes[10] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use QueryValidatorListRequest.ProtoReflect.Descriptor instead. -func (*QueryValidatorListRequest) Descriptor() ([]byte, []int) { - return file_validators_proto_rawDescGZIP(), []int{10} -} - -type QueryValidatorListResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Validators []*ValidatorInfo `protobuf:"bytes,1,rep,name=validators,proto3" json:"validators,omitempty"` // TODO add pagination in case the list gets large -} - -func (x *QueryValidatorListResponse) Reset() { - *x = QueryValidatorListResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_validators_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *QueryValidatorListResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*QueryValidatorListResponse) ProtoMessage() {} - -func (x *QueryValidatorListResponse) ProtoReflect() protoreflect.Message { - mi := &file_validators_proto_msgTypes[11] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use QueryValidatorListResponse.ProtoReflect.Descriptor instead. -func (*QueryValidatorListResponse) Descriptor() ([]byte, []int) { - return file_validators_proto_rawDescGZIP(), []int{11} -} - -func (x *QueryValidatorListResponse) GetValidators() []*ValidatorInfo { - if x != nil { - return x.Validators - } - return nil -} - -type StoreValidator struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // babylon_pk is the Babylon secp256k1 PK of this BTC validator - BabylonPk []byte `protobuf:"bytes,1,opt,name=babylon_pk,json=babylonPk,proto3" json:"babylon_pk,omitempty"` - // btc_pk is the BTC secp256k1 PK of the validator encoded in BIP-340 spec - BtcPk []byte `protobuf:"bytes,2,opt,name=btc_pk,json=btcPk,proto3" json:"btc_pk,omitempty"` - // description defines the description terms for the validator - Description *types.Description `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` - // commission defines the commission rate for the validator - // TODO failed to use the customized type: github.com/cosmos/cosmos-sdk/types.Dec - Commission string `protobuf:"bytes,4,opt,name=commission,proto3" json:"commission,omitempty"` - // pop is the proof of possession of babylon_pk and btc_pk - Pop *ProofOfPossession `protobuf:"bytes,5,opt,name=pop,proto3" json:"pop,omitempty"` - // key_name is the identifier of the keyring - KeyName string `protobuf:"bytes,6,opt,name=key_name,json=keyName,proto3" json:"key_name,omitempty"` - // last_voted_height defines the height of the last voted Babylon block - LastVotedHeight uint64 `protobuf:"varint,7,opt,name=last_voted_height,json=lastVotedHeight,proto3" json:"last_voted_height,omitempty"` - // last_committed_height defines the height of the last Babylon block - // to which the validator committed a randomness pair - LastCommittedHeight uint64 `protobuf:"varint,8,opt,name=last_committed_height,json=lastCommittedHeight,proto3" json:"last_committed_height,omitempty"` - // last_processed_height defines the height of the last successfully processed block - // even though the vote is not cast - LastProcessedHeight uint64 `protobuf:"varint,9,opt,name=last_processed_height,json=lastProcessedHeight,proto3" json:"last_processed_height,omitempty"` - // status defines the current validator status - Status ValidatorStatus `protobuf:"varint,10,opt,name=status,proto3,enum=proto.ValidatorStatus" json:"status,omitempty"` -} - -func (x *StoreValidator) Reset() { - *x = StoreValidator{} - if protoimpl.UnsafeEnabled { - mi := &file_validators_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *StoreValidator) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*StoreValidator) ProtoMessage() {} - -func (x *StoreValidator) ProtoReflect() protoreflect.Message { - mi := &file_validators_proto_msgTypes[12] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use StoreValidator.ProtoReflect.Descriptor instead. -func (*StoreValidator) Descriptor() ([]byte, []int) { - return file_validators_proto_rawDescGZIP(), []int{12} -} - -func (x *StoreValidator) GetBabylonPk() []byte { - if x != nil { - return x.BabylonPk - } - return nil -} - -func (x *StoreValidator) GetBtcPk() []byte { - if x != nil { - return x.BtcPk - } - return nil -} - -func (x *StoreValidator) GetDescription() *types.Description { - if x != nil { - return x.Description - } - return nil -} - -func (x *StoreValidator) GetCommission() string { - if x != nil { - return x.Commission - } - return "" -} - -func (x *StoreValidator) GetPop() *ProofOfPossession { - if x != nil { - return x.Pop - } - return nil -} - -func (x *StoreValidator) GetKeyName() string { - if x != nil { - return x.KeyName - } - return "" -} - -func (x *StoreValidator) GetLastVotedHeight() uint64 { - if x != nil { - return x.LastVotedHeight - } - return 0 -} - -func (x *StoreValidator) GetLastCommittedHeight() uint64 { - if x != nil { - return x.LastCommittedHeight - } - return 0 -} - -func (x *StoreValidator) GetLastProcessedHeight() uint64 { - if x != nil { - return x.LastProcessedHeight - } - return 0 -} - -func (x *StoreValidator) GetStatus() ValidatorStatus { - if x != nil { - return x.Status - } - return ValidatorStatus_CREATED -} - -// ValidatorInfo is the basic information of a validator mainly for external usage -type ValidatorInfo struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // babylon_pk_hex is the hex string of the Babylon secp256k1 PK of this BTC validator - BabylonPkHex string `protobuf:"bytes,1,opt,name=babylon_pk_hex,json=babylonPkHex,proto3" json:"babylon_pk_hex,omitempty"` - // btc_pk_hex is the hex string of the BTC secp256k1 PK of the validator encoded in BIP-340 spec - BtcPkHex string `protobuf:"bytes,2,opt,name=btc_pk_hex,json=btcPkHex,proto3" json:"btc_pk_hex,omitempty"` - // description defines the description terms for the validator - Description *types.Description `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` - // commission defines the commission rate for the validator - // TODO failed to use the customized type: github.com/cosmos/cosmos-sdk/types.Dec - Commission string `protobuf:"bytes,4,opt,name=commission,proto3" json:"commission,omitempty"` - // last_voted_height defines the height of the last voted Babylon block - LastVotedHeight uint64 `protobuf:"varint,5,opt,name=last_voted_height,json=lastVotedHeight,proto3" json:"last_voted_height,omitempty"` - // last_committed_height defines the height of the last Babylon block - // to which the validator committed a randomness pair - LastCommittedHeight uint64 `protobuf:"varint,6,opt,name=last_committed_height,json=lastCommittedHeight,proto3" json:"last_committed_height,omitempty"` - // status defines the current validator status - Status ValidatorStatus `protobuf:"varint,7,opt,name=status,proto3,enum=proto.ValidatorStatus" json:"status,omitempty"` -} - -func (x *ValidatorInfo) Reset() { - *x = ValidatorInfo{} - if protoimpl.UnsafeEnabled { - mi := &file_validators_proto_msgTypes[13] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ValidatorInfo) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ValidatorInfo) ProtoMessage() {} - -func (x *ValidatorInfo) ProtoReflect() protoreflect.Message { - mi := &file_validators_proto_msgTypes[13] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ValidatorInfo.ProtoReflect.Descriptor instead. -func (*ValidatorInfo) Descriptor() ([]byte, []int) { - return file_validators_proto_rawDescGZIP(), []int{13} -} - -func (x *ValidatorInfo) GetBabylonPkHex() string { - if x != nil { - return x.BabylonPkHex - } - return "" -} - -func (x *ValidatorInfo) GetBtcPkHex() string { - if x != nil { - return x.BtcPkHex - } - return "" -} - -func (x *ValidatorInfo) GetDescription() *types.Description { - if x != nil { - return x.Description - } - return nil -} - -func (x *ValidatorInfo) GetCommission() string { - if x != nil { - return x.Commission - } - return "" -} - -func (x *ValidatorInfo) GetLastVotedHeight() uint64 { - if x != nil { - return x.LastVotedHeight - } - return 0 -} - -func (x *ValidatorInfo) GetLastCommittedHeight() uint64 { - if x != nil { - return x.LastCommittedHeight - } - return 0 -} - -func (x *ValidatorInfo) GetStatus() ValidatorStatus { - if x != nil { - return x.Status - } - return ValidatorStatus_CREATED -} - -// ProofOfPossession is the proof of possession that a Babylon secp256k1 -// secret key and a Bitcoin secp256k1 secret key are held by the same -// person -type ProofOfPossession struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // babylon_sig is the signature generated via sign(sk_babylon, pk_btc) - BabylonSig []byte `protobuf:"bytes,1,opt,name=babylon_sig,json=babylonSig,proto3" json:"babylon_sig,omitempty"` - // btc_sig is the signature generated via sign(sk_btc, babylon_sig) - // the signature follows encoding in BIP-340 spec - BtcSig []byte `protobuf:"bytes,2,opt,name=btc_sig,json=btcSig,proto3" json:"btc_sig,omitempty"` -} - -func (x *ProofOfPossession) Reset() { - *x = ProofOfPossession{} - if protoimpl.UnsafeEnabled { - mi := &file_validators_proto_msgTypes[14] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ProofOfPossession) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ProofOfPossession) ProtoMessage() {} - -func (x *ProofOfPossession) ProtoReflect() protoreflect.Message { - mi := &file_validators_proto_msgTypes[14] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ProofOfPossession.ProtoReflect.Descriptor instead. -func (*ProofOfPossession) Descriptor() ([]byte, []int) { - return file_validators_proto_rawDescGZIP(), []int{14} -} - -func (x *ProofOfPossession) GetBabylonSig() []byte { - if x != nil { - return x.BabylonSig - } - return nil -} - -func (x *ProofOfPossession) GetBtcSig() []byte { - if x != nil { - return x.BtcSig - } - return nil -} - -type SchnorrRandPair struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - PubRand []byte `protobuf:"bytes,1,opt,name=pub_rand,json=pubRand,proto3" json:"pub_rand,omitempty"` - SecRand []byte `protobuf:"bytes,2,opt,name=sec_rand,json=secRand,proto3" json:"sec_rand,omitempty"` -} - -func (x *SchnorrRandPair) Reset() { - *x = SchnorrRandPair{} - if protoimpl.UnsafeEnabled { - mi := &file_validators_proto_msgTypes[15] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SchnorrRandPair) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SchnorrRandPair) ProtoMessage() {} - -func (x *SchnorrRandPair) ProtoReflect() protoreflect.Message { - mi := &file_validators_proto_msgTypes[15] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SchnorrRandPair.ProtoReflect.Descriptor instead. -func (*SchnorrRandPair) Descriptor() ([]byte, []int) { - return file_validators_proto_rawDescGZIP(), []int{15} -} - -func (x *SchnorrRandPair) GetPubRand() []byte { - if x != nil { - return x.PubRand - } - return nil -} - -func (x *SchnorrRandPair) GetSecRand() []byte { - if x != nil { - return x.SecRand - } - return nil -} - -var File_validators_proto protoreflect.FileDescriptor - -var file_validators_proto_rawDesc = []byte{ - 0x0a, 0x10, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x12, 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x14, 0x67, 0x6f, 0x67, 0x6f, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x67, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, - 0x24, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2f, - 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x5f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x22, 0x10, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x22, 0x2b, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, - 0xd4, 0x01, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, - 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, - 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x45, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x73, - 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x58, 0x0a, 0x0a, - 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x42, 0x38, 0xda, 0xde, 0x1f, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2d, 0x73, - 0x64, 0x6b, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x63, 0xd2, 0xb4, 0x2d, 0x0a, - 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x44, 0x65, 0x63, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, - 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x4f, 0x0a, 0x17, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x61, 0x62, 0x79, 0x6c, 0x6f, 0x6e, 0x5f, 0x70, 0x6b, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x62, 0x61, 0x62, 0x79, 0x6c, 0x6f, 0x6e, 0x50, 0x6b, - 0x12, 0x15, 0x0a, 0x06, 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x62, 0x74, 0x63, 0x50, 0x6b, 0x22, 0x35, 0x0a, 0x18, 0x52, 0x65, 0x67, 0x69, 0x73, - 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x34, - 0x0a, 0x19, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x74, - 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x78, - 0x48, 0x61, 0x73, 0x68, 0x22, 0x7e, 0x0a, 0x1b, 0x41, 0x64, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, - 0x69, 0x74, 0x79, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x61, 0x62, 0x79, 0x6c, 0x6f, 0x6e, 0x5f, 0x70, - 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x62, 0x61, 0x62, 0x79, 0x6c, 0x6f, 0x6e, - 0x50, 0x6b, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x6c, 0x61, - 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x6c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x48, 0x61, 0x73, 0x68, 0x22, 0x83, 0x01, 0x0a, 0x1c, 0x41, 0x64, 0x64, 0x46, 0x69, 0x6e, 0x61, - 0x6c, 0x69, 0x74, 0x79, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x78, 0x5f, 0x68, 0x61, 0x73, 0x68, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x12, 0x28, - 0x0a, 0x10, 0x65, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x6b, 0x5f, 0x68, - 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x65, 0x78, 0x74, 0x72, 0x61, 0x63, - 0x74, 0x65, 0x64, 0x53, 0x6b, 0x48, 0x65, 0x78, 0x12, 0x20, 0x0a, 0x0c, 0x6c, 0x6f, 0x63, 0x61, - 0x6c, 0x5f, 0x73, 0x6b, 0x5f, 0x68, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x53, 0x6b, 0x48, 0x65, 0x78, 0x22, 0x36, 0x0a, 0x15, 0x51, 0x75, - 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x61, 0x62, 0x79, 0x6c, 0x6f, 0x6e, 0x5f, 0x70, - 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x62, 0x61, 0x62, 0x79, 0x6c, 0x6f, 0x6e, - 0x50, 0x6b, 0x22, 0x4c, 0x0a, 0x16, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x09, - 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x09, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, - 0x22, 0x1b, 0x0a, 0x19, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x52, 0x0a, - 0x1a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x4c, - 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x0a, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, - 0x73, 0x22, 0xf2, 0x03, 0x0a, 0x0e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x61, 0x62, 0x79, 0x6c, 0x6f, 0x6e, 0x5f, - 0x70, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x62, 0x61, 0x62, 0x79, 0x6c, 0x6f, - 0x6e, 0x50, 0x6b, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x05, 0x62, 0x74, 0x63, 0x50, 0x6b, 0x12, 0x45, 0x0a, 0x0b, 0x64, 0x65, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x23, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, 0x6e, 0x67, - 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x58, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x38, 0xda, 0xde, 0x1f, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, - 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x63, 0x6f, 0x73, - 0x6d, 0x6f, 0x73, 0x2d, 0x73, 0x64, 0x6b, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x44, 0x65, - 0x63, 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x44, 0x65, 0x63, 0x52, - 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, 0x03, 0x70, - 0x6f, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x4f, 0x66, 0x50, 0x6f, 0x73, 0x73, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x52, 0x03, 0x70, 0x6f, 0x70, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x4e, 0x61, - 0x6d, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x76, 0x6f, 0x74, 0x65, 0x64, - 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6c, - 0x61, 0x73, 0x74, 0x56, 0x6f, 0x74, 0x65, 0x64, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x32, - 0x0a, 0x15, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, - 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x6c, - 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x48, 0x65, 0x69, 0x67, - 0x68, 0x74, 0x12, 0x32, 0x0a, 0x15, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, - 0x73, 0x73, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x13, 0x6c, 0x61, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, - 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x2e, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x56, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x84, 0x03, 0x0a, 0x0d, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x24, 0x0a, 0x0e, 0x62, 0x61, 0x62, 0x79, - 0x6c, 0x6f, 0x6e, 0x5f, 0x70, 0x6b, 0x5f, 0x68, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0c, 0x62, 0x61, 0x62, 0x79, 0x6c, 0x6f, 0x6e, 0x50, 0x6b, 0x48, 0x65, 0x78, 0x12, 0x1c, - 0x0a, 0x0a, 0x62, 0x74, 0x63, 0x5f, 0x70, 0x6b, 0x5f, 0x68, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x62, 0x74, 0x63, 0x50, 0x6b, 0x48, 0x65, 0x78, 0x12, 0x45, 0x0a, 0x0b, - 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x6b, 0x69, - 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x58, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x38, 0xda, 0xde, 0x1f, 0x26, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x63, - 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2d, 0x73, 0x64, 0x6b, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, - 0x44, 0x65, 0x63, 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x44, 0x65, - 0x63, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, - 0x11, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x76, 0x6f, 0x74, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x69, 0x67, - 0x68, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6c, 0x61, 0x73, 0x74, 0x56, 0x6f, - 0x74, 0x65, 0x64, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x32, 0x0a, 0x15, 0x6c, 0x61, 0x73, - 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x69, 0x67, - 0x68, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x6c, 0x61, 0x73, 0x74, 0x43, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x2e, 0x0a, - 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x4d, 0x0a, - 0x11, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x4f, 0x66, 0x50, 0x6f, 0x73, 0x73, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x62, 0x61, 0x62, 0x79, 0x6c, 0x6f, 0x6e, 0x5f, 0x73, 0x69, - 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x62, 0x61, 0x62, 0x79, 0x6c, 0x6f, 0x6e, - 0x53, 0x69, 0x67, 0x12, 0x17, 0x0a, 0x07, 0x62, 0x74, 0x63, 0x5f, 0x73, 0x69, 0x67, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x62, 0x74, 0x63, 0x53, 0x69, 0x67, 0x22, 0x47, 0x0a, 0x0f, - 0x53, 0x63, 0x68, 0x6e, 0x6f, 0x72, 0x72, 0x52, 0x61, 0x6e, 0x64, 0x50, 0x61, 0x69, 0x72, 0x12, - 0x19, 0x0a, 0x08, 0x70, 0x75, 0x62, 0x5f, 0x72, 0x61, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x07, 0x70, 0x75, 0x62, 0x52, 0x61, 0x6e, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x65, - 0x63, 0x5f, 0x72, 0x61, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x65, - 0x63, 0x52, 0x61, 0x6e, 0x64, 0x2a, 0x9f, 0x01, 0x0a, 0x0f, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x43, 0x52, 0x45, - 0x41, 0x54, 0x45, 0x44, 0x10, 0x00, 0x1a, 0x0b, 0x8a, 0x9d, 0x20, 0x07, 0x43, 0x52, 0x45, 0x41, - 0x54, 0x45, 0x44, 0x12, 0x1e, 0x0a, 0x0a, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x45, - 0x44, 0x10, 0x01, 0x1a, 0x0e, 0x8a, 0x9d, 0x20, 0x0a, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, - 0x52, 0x45, 0x44, 0x12, 0x16, 0x0a, 0x06, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x10, 0x02, 0x1a, - 0x0a, 0x8a, 0x9d, 0x20, 0x06, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x12, 0x1a, 0x0a, 0x08, 0x49, - 0x4e, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x10, 0x03, 0x1a, 0x0c, 0x8a, 0x9d, 0x20, 0x08, 0x49, - 0x4e, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x12, 0x18, 0x0a, 0x07, 0x53, 0x4c, 0x41, 0x53, 0x48, - 0x45, 0x44, 0x10, 0x04, 0x1a, 0x0b, 0x8a, 0x9d, 0x20, 0x07, 0x53, 0x4c, 0x41, 0x53, 0x48, 0x45, - 0x44, 0x1a, 0x04, 0x88, 0xa3, 0x1e, 0x00, 0x32, 0xfe, 0x03, 0x0a, 0x0d, 0x42, 0x74, 0x63, 0x56, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x38, 0x0a, 0x07, 0x47, 0x65, 0x74, - 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, - 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x11, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, - 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x1f, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, 0x0a, - 0x14, 0x41, 0x64, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x53, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x64, - 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2e, 0x41, 0x64, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x53, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, - 0x0a, 0x0e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, - 0x12, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x59, 0x0a, - 0x12, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x4c, - 0x69, 0x73, 0x74, 0x12, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, 0x65, 0x72, - 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x51, 0x75, - 0x65, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x4c, 0x69, 0x73, 0x74, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x2d, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x62, 0x61, 0x62, 0x79, 0x6c, 0x6f, 0x6e, 0x63, 0x68, - 0x61, 0x69, 0x6e, 0x2f, 0x62, 0x74, 0x63, 0x2d, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_validators_proto_rawDescOnce sync.Once - file_validators_proto_rawDescData = file_validators_proto_rawDesc -) - -func file_validators_proto_rawDescGZIP() []byte { - file_validators_proto_rawDescOnce.Do(func() { - file_validators_proto_rawDescData = protoimpl.X.CompressGZIP(file_validators_proto_rawDescData) - }) - return file_validators_proto_rawDescData -} - -var file_validators_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_validators_proto_msgTypes = make([]protoimpl.MessageInfo, 16) -var file_validators_proto_goTypes = []interface{}{ - (ValidatorStatus)(0), // 0: proto.ValidatorStatus - (*GetInfoRequest)(nil), // 1: proto.GetInfoRequest - (*GetInfoResponse)(nil), // 2: proto.GetInfoResponse - (*CreateValidatorRequest)(nil), // 3: proto.CreateValidatorRequest - (*CreateValidatorResponse)(nil), // 4: proto.CreateValidatorResponse - (*RegisterValidatorRequest)(nil), // 5: proto.RegisterValidatorRequest - (*RegisterValidatorResponse)(nil), // 6: proto.RegisterValidatorResponse - (*AddFinalitySignatureRequest)(nil), // 7: proto.AddFinalitySignatureRequest - (*AddFinalitySignatureResponse)(nil), // 8: proto.AddFinalitySignatureResponse - (*QueryValidatorRequest)(nil), // 9: proto.QueryValidatorRequest - (*QueryValidatorResponse)(nil), // 10: proto.QueryValidatorResponse - (*QueryValidatorListRequest)(nil), // 11: proto.QueryValidatorListRequest - (*QueryValidatorListResponse)(nil), // 12: proto.QueryValidatorListResponse - (*StoreValidator)(nil), // 13: proto.StoreValidator - (*ValidatorInfo)(nil), // 14: proto.ValidatorInfo - (*ProofOfPossession)(nil), // 15: proto.ProofOfPossession - (*SchnorrRandPair)(nil), // 16: proto.SchnorrRandPair - (*types.Description)(nil), // 17: cosmos.staking.v1beta1.Description -} -var file_validators_proto_depIdxs = []int32{ - 17, // 0: proto.CreateValidatorRequest.description:type_name -> cosmos.staking.v1beta1.Description - 14, // 1: proto.QueryValidatorResponse.validator:type_name -> proto.ValidatorInfo - 14, // 2: proto.QueryValidatorListResponse.validators:type_name -> proto.ValidatorInfo - 17, // 3: proto.StoreValidator.description:type_name -> cosmos.staking.v1beta1.Description - 15, // 4: proto.StoreValidator.pop:type_name -> proto.ProofOfPossession - 0, // 5: proto.StoreValidator.status:type_name -> proto.ValidatorStatus - 17, // 6: proto.ValidatorInfo.description:type_name -> cosmos.staking.v1beta1.Description - 0, // 7: proto.ValidatorInfo.status:type_name -> proto.ValidatorStatus - 1, // 8: proto.BtcValidators.GetInfo:input_type -> proto.GetInfoRequest - 3, // 9: proto.BtcValidators.CreateValidator:input_type -> proto.CreateValidatorRequest - 5, // 10: proto.BtcValidators.RegisterValidator:input_type -> proto.RegisterValidatorRequest - 7, // 11: proto.BtcValidators.AddFinalitySignature:input_type -> proto.AddFinalitySignatureRequest - 9, // 12: proto.BtcValidators.QueryValidator:input_type -> proto.QueryValidatorRequest - 11, // 13: proto.BtcValidators.QueryValidatorList:input_type -> proto.QueryValidatorListRequest - 2, // 14: proto.BtcValidators.GetInfo:output_type -> proto.GetInfoResponse - 4, // 15: proto.BtcValidators.CreateValidator:output_type -> proto.CreateValidatorResponse - 6, // 16: proto.BtcValidators.RegisterValidator:output_type -> proto.RegisterValidatorResponse - 8, // 17: proto.BtcValidators.AddFinalitySignature:output_type -> proto.AddFinalitySignatureResponse - 10, // 18: proto.BtcValidators.QueryValidator:output_type -> proto.QueryValidatorResponse - 12, // 19: proto.BtcValidators.QueryValidatorList:output_type -> proto.QueryValidatorListResponse - 14, // [14:20] is the sub-list for method output_type - 8, // [8:14] is the sub-list for method input_type - 8, // [8:8] is the sub-list for extension type_name - 8, // [8:8] is the sub-list for extension extendee - 0, // [0:8] is the sub-list for field type_name -} - -func init() { file_validators_proto_init() } -func file_validators_proto_init() { - if File_validators_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_validators_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetInfoRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_validators_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetInfoResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_validators_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CreateValidatorRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_validators_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CreateValidatorResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_validators_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RegisterValidatorRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_validators_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RegisterValidatorResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_validators_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddFinalitySignatureRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_validators_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddFinalitySignatureResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_validators_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*QueryValidatorRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_validators_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*QueryValidatorResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_validators_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*QueryValidatorListRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_validators_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*QueryValidatorListResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_validators_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StoreValidator); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_validators_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ValidatorInfo); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_validators_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProofOfPossession); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_validators_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SchnorrRandPair); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_validators_proto_rawDesc, - NumEnums: 1, - NumMessages: 16, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_validators_proto_goTypes, - DependencyIndexes: file_validators_proto_depIdxs, - EnumInfos: file_validators_proto_enumTypes, - MessageInfos: file_validators_proto_msgTypes, - }.Build() - File_validators_proto = out.File - file_validators_proto_rawDesc = nil - file_validators_proto_goTypes = nil - file_validators_proto_depIdxs = nil -} diff --git a/proto/validators.proto b/proto/validators.proto deleted file mode 100644 index ae79fb41..00000000 --- a/proto/validators.proto +++ /dev/null @@ -1,205 +0,0 @@ -syntax = "proto3"; - -package proto; - -import "gogoproto/gogo.proto"; -import "cosmos/staking/v1beta1/staking.proto"; -import "cosmos_proto/cosmos.proto"; - -option go_package = "github.com/babylonchain/btc-validator/proto"; - -service BtcValidators { - // GetInfo returns the information of the daemon - rpc GetInfo (GetInfoRequest) returns (GetInfoResponse); - - // CreateValidator generates and saves a validator object - rpc CreateValidator (CreateValidatorRequest) - returns (CreateValidatorResponse); - - // RegisterValidator sends a transactions to Babylon to register a BTC - // validator - rpc RegisterValidator (RegisterValidatorRequest) - returns (RegisterValidatorResponse); - - // AddFinalitySignature sends a transactions to Babylon to add a Finality - // signature for a block - rpc AddFinalitySignature(AddFinalitySignatureRequest) - returns (AddFinalitySignatureResponse); - - // QueryValidator queries the validator - rpc QueryValidator (QueryValidatorRequest) returns (QueryValidatorResponse); - // QueryValidatorList queries a list of validators - rpc QueryValidatorList (QueryValidatorListRequest) - returns (QueryValidatorListResponse); -} - -message GetInfoRequest { -} - -message GetInfoResponse { - string version = 1; -} - -message CreateValidatorRequest { - // key_name is the identifier key in keyring - string key_name = 1; - // description defines the description terms for the validator - cosmos.staking.v1beta1.Description description = 2; - // commission defines the commission rate for the validator - // TODO failed to use the customized type: github.com/cosmos/cosmos-sdk/types.Dec - string commission = 3 [ - (cosmos_proto.scalar) = "cosmos.Dec", - (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec" - ]; -} - -message CreateValidatorResponse { - // babylon_pk is the Babylon secp256k1 PK of this BTC validator - string babylon_pk = 1; - // btc_pk is the BTC secp256k1 PK of the validator encoded in BIP-340 spec - string btc_pk = 2; -} - -message RegisterValidatorRequest { - // the key name of the BTC validator - string key_name = 1; -} - -message RegisterValidatorResponse { - // hash of the successful Babylon registration transaction - string tx_hash = 1; -} - -message AddFinalitySignatureRequest { - // babylon_pk is the Babylon secp256k1 PK of this BTC validator - bytes babylon_pk = 1; - // height is the height of the Babylon block - uint64 height = 2; - // last_commit_hash is the last commit hash of the Babylon block - bytes last_commit_hash = 3; -} - -message AddFinalitySignatureResponse { - // hash of the successful Babylon finality signature submission transaction - string tx_hash = 1; - // the hex string of the extracted Bitcoin secp256k1 private key - string extracted_sk_hex = 2; - // the hex string of the local Bitcoin secp256k1 private key - string local_sk_hex = 3; -} - -message QueryValidatorRequest { - // babylon_pk is the Babylon secp256k1 PK of this BTC validator - bytes babylon_pk = 1; -} - -message QueryValidatorResponse { - ValidatorInfo validator = 1; -} - -message QueryValidatorListRequest { - // TODO add pagination in case the list gets large -} - -message QueryValidatorListResponse { - repeated ValidatorInfo validators = 1; - // TODO add pagination in case the list gets large -} - -message StoreValidator { - // babylon_pk is the Babylon secp256k1 PK of this BTC validator - bytes babylon_pk = 1; - // btc_pk is the BTC secp256k1 PK of the validator encoded in BIP-340 spec - bytes btc_pk = 2; - // description defines the description terms for the validator - cosmos.staking.v1beta1.Description description = 3; - // commission defines the commission rate for the validator - // TODO failed to use the customized type: github.com/cosmos/cosmos-sdk/types.Dec - string commission = 4 [ - (cosmos_proto.scalar) = "cosmos.Dec", - (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec" - ]; - // pop is the proof of possession of babylon_pk and btc_pk - ProofOfPossession pop = 5; - // key_name is the identifier of the keyring - string key_name = 6; - // last_voted_height defines the height of the last voted Babylon block - uint64 last_voted_height = 7; - // last_committed_height defines the height of the last Babylon block - // to which the validator committed a randomness pair - uint64 last_committed_height = 8; - // last_processed_height defines the height of the last successfully processed block - // even though the vote is not cast - uint64 last_processed_height = 9; - // status defines the current validator status - ValidatorStatus status = 10; -} - -// ValidatorInfo is the basic information of a validator mainly for external usage -message ValidatorInfo { - // babylon_pk_hex is the hex string of the Babylon secp256k1 PK of this BTC validator - string babylon_pk_hex = 1; - // btc_pk_hex is the hex string of the BTC secp256k1 PK of the validator encoded in BIP-340 spec - string btc_pk_hex = 2; - // description defines the description terms for the validator - cosmos.staking.v1beta1.Description description = 3; - // commission defines the commission rate for the validator - // TODO failed to use the customized type: github.com/cosmos/cosmos-sdk/types.Dec - string commission = 4 [ - (cosmos_proto.scalar) = "cosmos.Dec", - (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec" - ]; - // last_voted_height defines the height of the last voted Babylon block - uint64 last_voted_height = 5; - // last_committed_height defines the height of the last Babylon block - // to which the validator committed a randomness pair - uint64 last_committed_height = 6; - // status defines the current validator status - ValidatorStatus status = 7; -} - -// ProofOfPossession is the proof of possession that a Babylon secp256k1 -// secret key and a Bitcoin secp256k1 secret key are held by the same -// person -message ProofOfPossession { - // babylon_sig is the signature generated via sign(sk_babylon, pk_btc) - bytes babylon_sig = 1; - // btc_sig is the signature generated via sign(sk_btc, babylon_sig) - // the signature follows encoding in BIP-340 spec - bytes btc_sig = 2; -} - -message SchnorrRandPair { - bytes pub_rand = 1; - bytes sec_rand = 2; -} - -// ValidatorStatus is the status of a BTC validator -// a Validator object has 4 states: -// - Created - created and managed by validator client, not registered to -// babylon yet -// - Registered - created and registered to Babylon, but not voting yet (No -// delegated stake) -// - Active - created and registered to Babylon with stake to vote -// - Inactive - created and registered to Babylon with no stake to vote. -// Validator was already active. -// Valid State Transactions: -// - Created -> Registered -// - Registered -> Active -// - Active -> Inactive -// - Inactive -> Active -enum ValidatorStatus { - option (gogoproto.goproto_enum_prefix) = false; - - // CREATED defines a validator that is awaiting registration - CREATED = 0 [(gogoproto.enumvalue_customname) = "CREATED"]; - // REGISTERED defines a validator that has been registered - // to Babylon but has no delegated stake - REGISTERED = 1 [(gogoproto.enumvalue_customname) = "REGISTERED"]; - // ACTIVE defines a validator that is delegated to vote - ACTIVE = 2 [(gogoproto.enumvalue_customname) = "ACTIVE"]; - // INACTIVE defines a validator whose delegations are reduced to zero but not slashed - INACTIVE = 3 [(gogoproto.enumvalue_customname) = "INACTIVE"]; - // SLASHED defines a validator that has been slashed - SLASHED = 4 [(gogoproto.enumvalue_customname) = "SLASHED"]; -} diff --git a/proto/validators_grpc.pb.go b/proto/validators_grpc.pb.go deleted file mode 100644 index 64ac1744..00000000 --- a/proto/validators_grpc.pb.go +++ /dev/null @@ -1,310 +0,0 @@ -// Code generated by protoc-gen-go-grpc. DO NOT EDIT. -// versions: -// - protoc-gen-go-grpc v1.3.0 -// - protoc (unknown) -// source: validators.proto - -package proto - -import ( - context "context" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" -) - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.32.0 or later. -const _ = grpc.SupportPackageIsVersion7 - -const ( - BtcValidators_GetInfo_FullMethodName = "/proto.BtcValidators/GetInfo" - BtcValidators_CreateValidator_FullMethodName = "/proto.BtcValidators/CreateValidator" - BtcValidators_RegisterValidator_FullMethodName = "/proto.BtcValidators/RegisterValidator" - BtcValidators_AddFinalitySignature_FullMethodName = "/proto.BtcValidators/AddFinalitySignature" - BtcValidators_QueryValidator_FullMethodName = "/proto.BtcValidators/QueryValidator" - BtcValidators_QueryValidatorList_FullMethodName = "/proto.BtcValidators/QueryValidatorList" -) - -// BtcValidatorsClient is the client API for BtcValidators service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. -type BtcValidatorsClient interface { - // GetInfo returns the information of the daemon - GetInfo(ctx context.Context, in *GetInfoRequest, opts ...grpc.CallOption) (*GetInfoResponse, error) - // CreateValidator generates and saves a validator object - CreateValidator(ctx context.Context, in *CreateValidatorRequest, opts ...grpc.CallOption) (*CreateValidatorResponse, error) - // RegisterValidator sends a transactions to Babylon to register a BTC - // validator - RegisterValidator(ctx context.Context, in *RegisterValidatorRequest, opts ...grpc.CallOption) (*RegisterValidatorResponse, error) - // AddFinalitySignature sends a transactions to Babylon to add a Finality - // signature for a block - AddFinalitySignature(ctx context.Context, in *AddFinalitySignatureRequest, opts ...grpc.CallOption) (*AddFinalitySignatureResponse, error) - // QueryValidator queries the validator - QueryValidator(ctx context.Context, in *QueryValidatorRequest, opts ...grpc.CallOption) (*QueryValidatorResponse, error) - // QueryValidatorList queries a list of validators - QueryValidatorList(ctx context.Context, in *QueryValidatorListRequest, opts ...grpc.CallOption) (*QueryValidatorListResponse, error) -} - -type btcValidatorsClient struct { - cc grpc.ClientConnInterface -} - -func NewBtcValidatorsClient(cc grpc.ClientConnInterface) BtcValidatorsClient { - return &btcValidatorsClient{cc} -} - -func (c *btcValidatorsClient) GetInfo(ctx context.Context, in *GetInfoRequest, opts ...grpc.CallOption) (*GetInfoResponse, error) { - out := new(GetInfoResponse) - err := c.cc.Invoke(ctx, BtcValidators_GetInfo_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *btcValidatorsClient) CreateValidator(ctx context.Context, in *CreateValidatorRequest, opts ...grpc.CallOption) (*CreateValidatorResponse, error) { - out := new(CreateValidatorResponse) - err := c.cc.Invoke(ctx, BtcValidators_CreateValidator_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *btcValidatorsClient) RegisterValidator(ctx context.Context, in *RegisterValidatorRequest, opts ...grpc.CallOption) (*RegisterValidatorResponse, error) { - out := new(RegisterValidatorResponse) - err := c.cc.Invoke(ctx, BtcValidators_RegisterValidator_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *btcValidatorsClient) AddFinalitySignature(ctx context.Context, in *AddFinalitySignatureRequest, opts ...grpc.CallOption) (*AddFinalitySignatureResponse, error) { - out := new(AddFinalitySignatureResponse) - err := c.cc.Invoke(ctx, BtcValidators_AddFinalitySignature_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *btcValidatorsClient) QueryValidator(ctx context.Context, in *QueryValidatorRequest, opts ...grpc.CallOption) (*QueryValidatorResponse, error) { - out := new(QueryValidatorResponse) - err := c.cc.Invoke(ctx, BtcValidators_QueryValidator_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *btcValidatorsClient) QueryValidatorList(ctx context.Context, in *QueryValidatorListRequest, opts ...grpc.CallOption) (*QueryValidatorListResponse, error) { - out := new(QueryValidatorListResponse) - err := c.cc.Invoke(ctx, BtcValidators_QueryValidatorList_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// BtcValidatorsServer is the server API for BtcValidators service. -// All implementations must embed UnimplementedBtcValidatorsServer -// for forward compatibility -type BtcValidatorsServer interface { - // GetInfo returns the information of the daemon - GetInfo(context.Context, *GetInfoRequest) (*GetInfoResponse, error) - // CreateValidator generates and saves a validator object - CreateValidator(context.Context, *CreateValidatorRequest) (*CreateValidatorResponse, error) - // RegisterValidator sends a transactions to Babylon to register a BTC - // validator - RegisterValidator(context.Context, *RegisterValidatorRequest) (*RegisterValidatorResponse, error) - // AddFinalitySignature sends a transactions to Babylon to add a Finality - // signature for a block - AddFinalitySignature(context.Context, *AddFinalitySignatureRequest) (*AddFinalitySignatureResponse, error) - // QueryValidator queries the validator - QueryValidator(context.Context, *QueryValidatorRequest) (*QueryValidatorResponse, error) - // QueryValidatorList queries a list of validators - QueryValidatorList(context.Context, *QueryValidatorListRequest) (*QueryValidatorListResponse, error) - mustEmbedUnimplementedBtcValidatorsServer() -} - -// UnimplementedBtcValidatorsServer must be embedded to have forward compatible implementations. -type UnimplementedBtcValidatorsServer struct { -} - -func (UnimplementedBtcValidatorsServer) GetInfo(context.Context, *GetInfoRequest) (*GetInfoResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetInfo not implemented") -} -func (UnimplementedBtcValidatorsServer) CreateValidator(context.Context, *CreateValidatorRequest) (*CreateValidatorResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method CreateValidator not implemented") -} -func (UnimplementedBtcValidatorsServer) RegisterValidator(context.Context, *RegisterValidatorRequest) (*RegisterValidatorResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method RegisterValidator not implemented") -} -func (UnimplementedBtcValidatorsServer) AddFinalitySignature(context.Context, *AddFinalitySignatureRequest) (*AddFinalitySignatureResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method AddFinalitySignature not implemented") -} -func (UnimplementedBtcValidatorsServer) QueryValidator(context.Context, *QueryValidatorRequest) (*QueryValidatorResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method QueryValidator not implemented") -} -func (UnimplementedBtcValidatorsServer) QueryValidatorList(context.Context, *QueryValidatorListRequest) (*QueryValidatorListResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method QueryValidatorList not implemented") -} -func (UnimplementedBtcValidatorsServer) mustEmbedUnimplementedBtcValidatorsServer() {} - -// UnsafeBtcValidatorsServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to BtcValidatorsServer will -// result in compilation errors. -type UnsafeBtcValidatorsServer interface { - mustEmbedUnimplementedBtcValidatorsServer() -} - -func RegisterBtcValidatorsServer(s grpc.ServiceRegistrar, srv BtcValidatorsServer) { - s.RegisterService(&BtcValidators_ServiceDesc, srv) -} - -func _BtcValidators_GetInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetInfoRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BtcValidatorsServer).GetInfo(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: BtcValidators_GetInfo_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BtcValidatorsServer).GetInfo(ctx, req.(*GetInfoRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _BtcValidators_CreateValidator_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(CreateValidatorRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BtcValidatorsServer).CreateValidator(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: BtcValidators_CreateValidator_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BtcValidatorsServer).CreateValidator(ctx, req.(*CreateValidatorRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _BtcValidators_RegisterValidator_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RegisterValidatorRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BtcValidatorsServer).RegisterValidator(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: BtcValidators_RegisterValidator_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BtcValidatorsServer).RegisterValidator(ctx, req.(*RegisterValidatorRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _BtcValidators_AddFinalitySignature_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(AddFinalitySignatureRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BtcValidatorsServer).AddFinalitySignature(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: BtcValidators_AddFinalitySignature_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BtcValidatorsServer).AddFinalitySignature(ctx, req.(*AddFinalitySignatureRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _BtcValidators_QueryValidator_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryValidatorRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BtcValidatorsServer).QueryValidator(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: BtcValidators_QueryValidator_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BtcValidatorsServer).QueryValidator(ctx, req.(*QueryValidatorRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _BtcValidators_QueryValidatorList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryValidatorListRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BtcValidatorsServer).QueryValidatorList(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: BtcValidators_QueryValidatorList_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BtcValidatorsServer).QueryValidatorList(ctx, req.(*QueryValidatorListRequest)) - } - return interceptor(ctx, in, info, handler) -} - -// BtcValidators_ServiceDesc is the grpc.ServiceDesc for BtcValidators service. -// It's only intended for direct use with grpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var BtcValidators_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "proto.BtcValidators", - HandlerType: (*BtcValidatorsServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "GetInfo", - Handler: _BtcValidators_GetInfo_Handler, - }, - { - MethodName: "CreateValidator", - Handler: _BtcValidators_CreateValidator_Handler, - }, - { - MethodName: "RegisterValidator", - Handler: _BtcValidators_RegisterValidator_Handler, - }, - { - MethodName: "AddFinalitySignature", - Handler: _BtcValidators_AddFinalitySignature_Handler, - }, - { - MethodName: "QueryValidator", - Handler: _BtcValidators_QueryValidator_Handler, - }, - { - MethodName: "QueryValidatorList", - Handler: _BtcValidators_QueryValidatorList_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "validators.proto", -} diff --git a/service/app.go b/service/app.go deleted file mode 100644 index 7239f3d8..00000000 --- a/service/app.go +++ /dev/null @@ -1,506 +0,0 @@ -package service - -import ( - "fmt" - "sync" - - "cosmossdk.io/math" - bbntypes "github.com/babylonchain/babylon/types" - bstypes "github.com/babylonchain/babylon/x/btcstaking/types" - "github.com/btcsuite/btcd/btcec/v2" - "github.com/cosmos/cosmos-sdk/crypto/keyring" - "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - sdktypes "github.com/cosmos/cosmos-sdk/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - "github.com/sirupsen/logrus" - - "github.com/babylonchain/btc-validator/clientcontroller" - "github.com/babylonchain/btc-validator/proto" - "github.com/babylonchain/btc-validator/valcfg" - - "github.com/babylonchain/btc-validator/val" -) - -type ValidatorApp struct { - startOnce sync.Once - stopOnce sync.Once - - wg sync.WaitGroup - quit chan struct{} - - sentWg sync.WaitGroup - sentQuit chan struct{} - - eventWg sync.WaitGroup - eventQuit chan struct{} - - cc clientcontroller.ClientController - kr keyring.Keyring - vs *val.ValidatorStore - config *valcfg.Config - logger *logrus.Logger - - validatorManager *ValidatorManager - - createValidatorRequestChan chan *createValidatorRequest - registerValidatorRequestChan chan *registerValidatorRequest - validatorRegisteredEventChan chan *validatorRegisteredEvent -} - -func NewValidatorAppFromConfig( - config *valcfg.Config, - logger *logrus.Logger, - cc clientcontroller.ClientController, -) (*ValidatorApp, error) { - - kr, err := CreateKeyring(config.BabylonConfig.KeyDirectory, - config.BabylonConfig.ChainID, - config.BabylonConfig.KeyringBackend) - if err != nil { - return nil, fmt.Errorf("failed to create keyring: %w", err) - } - - valStore, err := val.NewValidatorStore(config.DatabaseConfig) - if err != nil { - return nil, fmt.Errorf("failed to open the store for validators: %w", err) - } - - if config.JuryMode { - if _, err := kr.Key(config.JuryModeConfig.JuryKeyName); err != nil { - return nil, fmt.Errorf("the program is running in Jury mode but the Jury key %s is not found: %w", - config.JuryModeConfig.JuryKeyName, err) - } - } - - vm, err := NewValidatorManager(valStore, config, kr, cc, logger) - if err != nil { - return nil, fmt.Errorf("failed to create validator manager: %w", err) - } - - return &ValidatorApp{ - cc: cc, - vs: valStore, - kr: kr, - config: config, - logger: logger, - validatorManager: vm, - quit: make(chan struct{}), - sentQuit: make(chan struct{}), - eventQuit: make(chan struct{}), - createValidatorRequestChan: make(chan *createValidatorRequest), - registerValidatorRequestChan: make(chan *registerValidatorRequest), - validatorRegisteredEventChan: make(chan *validatorRegisteredEvent), - }, nil -} - -func (app *ValidatorApp) GetConfig() *valcfg.Config { - return app.config -} - -func (app *ValidatorApp) GetValidatorStore() *val.ValidatorStore { - return app.vs -} - -func (app *ValidatorApp) GetKeyring() keyring.Keyring { - return app.kr -} - -func (app *ValidatorApp) GetJuryPk() (*btcec.PublicKey, error) { - juryPrivKey, err := app.getJuryPrivKey() - if err != nil { - return nil, err - } - return juryPrivKey.PubKey(), nil -} - -func (app *ValidatorApp) ListValidatorInstances() []*ValidatorInstance { - return app.validatorManager.listValidatorInstances() -} - -// GetValidatorInstance returns the validator instance with the given Babylon public key -func (app *ValidatorApp) GetValidatorInstance(babylonPk *secp256k1.PubKey) (*ValidatorInstance, error) { - return app.validatorManager.getValidatorInstance(babylonPk) -} - -func (app *ValidatorApp) RegisterValidator(keyName string) (*RegisterValidatorResponse, *secp256k1.PubKey, error) { - kc, err := val.NewKeyringControllerWithKeyring(app.kr, keyName) - if err != nil { - return nil, nil, err - } - if !kc.ValidatorKeyExists() { - return nil, nil, fmt.Errorf("key name %s does not exist", keyName) - } - babylonPublicKeyBytes, err := kc.GetBabylonPublicKeyBytes() - if err != nil { - return nil, nil, err - } - validator, err := app.vs.GetStoreValidator(babylonPublicKeyBytes) - if err != nil { - return nil, nil, err - } - - if validator.Status != proto.ValidatorStatus_CREATED { - return nil, nil, fmt.Errorf("validator is already registered") - } - - btcSig, err := bbntypes.NewBIP340Signature(validator.Pop.BtcSig) - if err != nil { - return nil, nil, err - } - - pop := &bstypes.ProofOfPossession{ - BabylonSig: validator.Pop.BabylonSig, - BtcSig: btcSig.MustMarshal(), - BtcSigType: bstypes.BTCSigType_BIP340, - } - - commissionRate, err := math.LegacyNewDecFromStr(validator.Commission) - if err != nil { - return nil, nil, err - } - - request := ®isterValidatorRequest{ - bbnPubKey: validator.GetBabylonPK(), - btcPubKey: validator.MustGetBIP340BTCPK(), - pop: pop, - description: validator.Description, - commission: &commissionRate, - errResponse: make(chan error, 1), - successResponse: make(chan *RegisterValidatorResponse, 1), - } - - app.registerValidatorRequestChan <- request - - select { - case err := <-request.errResponse: - return nil, nil, err - case successResponse := <-request.successResponse: - return successResponse, validator.GetBabylonPK(), nil - case <-app.quit: - return nil, nil, fmt.Errorf("validator app is shutting down") - } -} - -// StartHandlingValidator starts a validator instance with the given Babylon public key -// Note: this should be called right after the validator is registered -func (app *ValidatorApp) StartHandlingValidator(bbnPk *secp256k1.PubKey) error { - return app.validatorManager.addValidatorInstance(bbnPk) -} - -func (app *ValidatorApp) StartHandlingValidators() error { - return app.validatorManager.Start() -} - -// AddJurySignature adds a Jury signature on the given Bitcoin delegation and submits it to Babylon -// Note: this should be only called when the program is running in Jury mode -func (app *ValidatorApp) AddJurySignature(btcDel *bstypes.BTCDelegation) (*AddJurySigResponse, error) { - if btcDel.JurySig != nil { - return nil, fmt.Errorf("the Jury sig already existed in the Bitcoin delection") - } - - slashingTx := btcDel.SlashingTx - stakingTx := btcDel.StakingTx - stakingMsgTx, err := stakingTx.ToMsgTx() - if err != nil { - return nil, err - } - - // get Jury private key from the keyring - juryPrivKey, err := app.getJuryPrivKey() - if err != nil { - return nil, fmt.Errorf("failed to get Jury private key: %w", err) - } - - jurySig, err := slashingTx.Sign( - stakingMsgTx, - stakingTx.Script, - juryPrivKey, - &app.config.ActiveNetParams, - ) - if err != nil { - return nil, err - } - - stakingTxHash := stakingMsgTx.TxHash().String() - - res, err := app.cc.SubmitJurySig(btcDel.ValBtcPk, btcDel.BtcPk, stakingTxHash, jurySig) - - if err != nil { - app.logger.WithFields(logrus.Fields{ - "err": err, - "valBtcPubKey": btcDel.ValBtcPk.MarshalHex(), - "delBtcPubKey": btcDel.BtcPk.MarshalHex(), - }).Error("failed to submit Jury signature") - return nil, err - } - - if res == nil { - app.logger.WithFields(logrus.Fields{ - "err": err, - "valBtcPubKey": btcDel.ValBtcPk.MarshalHex(), - "delBtcPubKey": btcDel.BtcPk.MarshalHex(), - }).Error("failed to submit Jury signature") - return nil, fmt.Errorf("failed to submit Jury signature due to known error") - } - - return &AddJurySigResponse{ - TxHash: res.TxHash, - }, nil -} - -// AddJurySignature adds a Jury signature on the given Bitcoin delegation and submits it to Babylon -// Note: this should be only called when the program is running in Jury mode -func (app *ValidatorApp) AddJuryUnbondingSignatures(btcDel *bstypes.BTCDelegation) (*AddJurySigResponse, error) { - if btcDel == nil { - return nil, fmt.Errorf("btc delegation is nil") - } - - if btcDel.BtcUndelegation == nil { - return nil, fmt.Errorf("delegation does not have an unbonding transaction") - } - - if btcDel.BtcUndelegation.ValidatorUnbondingSig == nil { - return nil, fmt.Errorf("delegation does not have a validator signature for unbonding transaction yet") - } - - // In normal operation it is not possible to have one of this signatures and not have the other - // as only way to update this fields in delegation is by processing the MsgAddJuryUnbondingSigs msg - // which should update both fields at atomically in case of successfull transaction. - if btcDel.BtcUndelegation.JurySlashingSig != nil || btcDel.BtcUndelegation.JuryUnbondingSig != nil { - return nil, fmt.Errorf("delegation already has required jury signatures") - } - - // get Jury private key from the keyring - juryPrivKey, err := app.getJuryPrivKey() - if err != nil { - return nil, fmt.Errorf("failed to get Jury private key: %w", err) - } - - // 1. Sign unbonding transaction - stakingTx := btcDel.StakingTx - stakingMsgTx, err := stakingTx.ToMsgTx() - - if err != nil { - return nil, fmt.Errorf("failed to deserialize staking tx: %w", err) - } - - juryUnbondingSig, err := btcDel.BtcUndelegation.UnbondingTx.Sign( - stakingMsgTx, - stakingTx.Script, - juryPrivKey, - &app.config.ActiveNetParams, - ) - - if err != nil { - return nil, fmt.Errorf("failed to sign unbonding tx: %w", err) - } - - // 2. Sign slash unbonding transaction - slashUnbondigTx := btcDel.BtcUndelegation.SlashingTx - unbondingTx := btcDel.BtcUndelegation.UnbondingTx - unbondingMsgTx, err := unbondingTx.ToMsgTx() - - if err != nil { - return nil, fmt.Errorf("failed to deserialize unbonding tx: %w", err) - } - - jurySlashingUnbondingSig, err := slashUnbondigTx.Sign( - unbondingMsgTx, - unbondingTx.Script, - juryPrivKey, - &app.config.ActiveNetParams, - ) - if err != nil { - return nil, fmt.Errorf("failed to sign slash unbonding tx: %w", err) - } - - stakingTxHash := stakingMsgTx.TxHash().String() - - res, err := app.cc.SubmitJuryUnbondingSigs( - btcDel.ValBtcPk, - btcDel.BtcPk, - stakingTxHash, - juryUnbondingSig, - jurySlashingUnbondingSig, - ) - - if err != nil { - app.logger.WithFields(logrus.Fields{ - "err": err, - "valBtcPubKey": btcDel.ValBtcPk.MarshalHex(), - "delBtcPubKey": btcDel.BtcPk.MarshalHex(), - }).Error("failed to submit Jury signature") - return nil, err - } - - if res == nil { - app.logger.WithFields(logrus.Fields{ - "err": err, - "valBtcPubKey": btcDel.ValBtcPk.MarshalHex(), - "delBtcPubKey": btcDel.BtcPk.MarshalHex(), - }).Error("failed to submit Jury signature") - return nil, fmt.Errorf("failed to submit Jury signature due to known error") - } - - return &AddJurySigResponse{ - TxHash: res.TxHash, - }, nil -} - -func (app *ValidatorApp) getJuryPrivKey() (*btcec.PrivateKey, error) { - return app.getPrivKey(app.config.JuryModeConfig.JuryKeyName) -} - -func (app *ValidatorApp) getBtcPrivKey(name string) (*btcec.PrivateKey, error) { - return app.getPrivKey(val.KeyName(name).GetBtcKeyName()) -} - -func (app *ValidatorApp) getPrivKey(name string) (*btcec.PrivateKey, error) { - k, err := app.kr.Key(name) - if err != nil { - return nil, fmt.Errorf("failed to get key %s from the keyring: %w", name, err) - } - localKey := k.GetLocal().PrivKey.GetCachedValue() - switch v := localKey.(type) { - case *secp256k1.PrivKey: - privKey, _ := btcec.PrivKeyFromBytes(v.Key) - return privKey, nil - default: - return nil, fmt.Errorf("unsupported key type in keyring") - } -} - -func (app *ValidatorApp) Start() error { - var startErr error - app.startOnce.Do(func() { - app.logger.Infof("Starting ValidatorApp") - - app.eventWg.Add(1) - go app.eventLoop() - - app.sentWg.Add(1) - go app.handleSentToBabylonLoop() - - if app.IsJury() { - app.wg.Add(1) - go app.jurySigSubmissionLoop() - } else { - if err := app.StartHandlingValidators(); err != nil { - startErr = err - return - } - } - }) - - return startErr -} - -func (app *ValidatorApp) Stop() error { - var stopErr error - app.stopOnce.Do(func() { - app.logger.Infof("Stopping ValidatorApp") - - // Always stop the submission loop first to not generate additional events and actions - app.logger.Debug("Stopping submission loop") - close(app.quit) - app.wg.Wait() - - if !app.IsJury() { - app.logger.Debug("Stopping validators") - if err := app.validatorManager.Stop(); err != nil { - stopErr = err - return - } - } - - app.logger.Debug("Sent to Babylon loop stopped") - close(app.sentQuit) - app.sentWg.Wait() - - app.logger.Debug("Stopping main eventLoop") - close(app.eventQuit) - app.eventWg.Wait() - - // Closing db as last to avoid anybody to write do db - app.logger.Debug("Stopping data store") - if err := app.vs.Close(); err != nil { - stopErr = err - return - } - - app.logger.Debug("ValidatorApp successfully stopped") - - }) - return stopErr -} - -func (app *ValidatorApp) CreateValidator(keyName string, description *stakingtypes.Description, commission *sdktypes.Dec) (*CreateValidatorResult, error) { - req := &createValidatorRequest{ - keyName: keyName, - description: description, - commission: commission, - errResponse: make(chan error, 1), - successResponse: make(chan *createValidatorResponse, 1), - } - - app.createValidatorRequestChan <- req - - select { - case err := <-req.errResponse: - return nil, err - case successResponse := <-req.successResponse: - return &CreateValidatorResult{ - BtcValidatorPk: successResponse.BtcValidatorPk, - BabylonValidatorPk: successResponse.BabylonValidatorPk, - }, nil - case <-app.quit: - return nil, fmt.Errorf("validator app is shutting down") - } -} - -func (app *ValidatorApp) IsJury() bool { - return app.config.JuryMode -} - -func (app *ValidatorApp) handleCreateValidatorRequest(req *createValidatorRequest) (*createValidatorResponse, error) { - - app.logger.Debug("handling CreateValidator request") - - kr, err := val.NewKeyringControllerWithKeyring(app.kr, req.keyName) - - if err != nil { - return nil, fmt.Errorf("failed to create keyring controller: %w", err) - } - - if kr.ValidatorKeyNameTaken() { - return nil, fmt.Errorf("the key name %s is taken", kr.GetKeyName()) - } - - // TODO should not expose direct proto here, as this is internal db representation - // connected to serialization - btcPk, bbnPk, err := kr.CreateValidatorKeys() - if err != nil { - return nil, fmt.Errorf("failed to create validator: %w", err) - } - - pop, err := kr.CreatePop() - if err != nil { - return nil, fmt.Errorf("failed to create proof-of-possession of the validator: %w", err) - } - - validator := val.NewStoreValidator(bbnPk, btcPk, kr.GetKeyName(), pop, req.description, req.commission) - - if err := app.vs.SaveValidator(validator); err != nil { - return nil, fmt.Errorf("failed to save validator: %w", err) - } - - app.logger.WithFields(logrus.Fields{ - "btc_pub_key": validator.MustGetBIP340BTCPK().MarshalHex(), - "babylon_pub_key": validator.GetBabylonPkHexString(), - }).Debug("successfully created a validator") - - return &createValidatorResponse{ - BtcValidatorPk: *validator.MustGetBTCPK(), - BabylonValidatorPk: *validator.GetBabylonPK(), - }, nil -} diff --git a/service/app_test.go b/service/app_test.go deleted file mode 100644 index 411b0bcf..00000000 --- a/service/app_test.go +++ /dev/null @@ -1,163 +0,0 @@ -package service_test - -import ( - "math/rand" - "os" - "testing" - - "github.com/babylonchain/babylon/testutil/datagen" - bbntypes "github.com/babylonchain/babylon/types" - bstypes "github.com/babylonchain/babylon/x/btcstaking/types" - "github.com/btcsuite/btcd/chaincfg" - "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - "github.com/cosmos/relayer/v2/relayer/provider" - "github.com/golang/mock/gomock" - "github.com/sirupsen/logrus" - "github.com/stretchr/testify/require" - - "github.com/babylonchain/btc-validator/proto" - "github.com/babylonchain/btc-validator/service" - "github.com/babylonchain/btc-validator/testutil" - "github.com/babylonchain/btc-validator/val" - "github.com/babylonchain/btc-validator/valcfg" -) - -func FuzzRegisterValidator(f *testing.F) { - testutil.AddRandomSeedsToFuzzer(f, 10) - f.Fuzz(func(t *testing.T, seed int64) { - r := rand.New(rand.NewSource(seed)) - - // create validator app with db and mocked Babylon client - cfg := valcfg.DefaultConfig() - cfg.DatabaseConfig = testutil.GenDBConfig(r, t) - defer func() { - err := os.RemoveAll(cfg.DatabaseConfig.Path) - require.NoError(t, err) - }() - randomStartingHeight := uint64(r.Int63n(100) + 1) - cfg.ValidatorModeConfig.AutoChainScanningMode = false - cfg.ValidatorModeConfig.StaticChainScanningStartHeight = randomStartingHeight - currentHeight := randomStartingHeight + uint64(r.Int63n(10)+2) - mockClientController := testutil.PrepareMockedClientController(t, r, randomStartingHeight, currentHeight) - mockClientController.EXPECT().QueryLatestFinalizedBlocks(gomock.Any()).Return(nil, nil).AnyTimes() - app, err := service.NewValidatorAppFromConfig(&cfg, logrus.New(), mockClientController) - require.NoError(t, err) - - err = app.Start() - require.NoError(t, err) - defer func() { - err = app.Stop() - require.NoError(t, err) - }() - - // create a validator object and save it to db - validator := testutil.GenStoredValidator(r, t, app) - btcSig := new(bbntypes.BIP340Signature) - err = btcSig.Unmarshal(validator.Pop.BtcSig) - require.NoError(t, err) - pop := &bstypes.ProofOfPossession{ - BabylonSig: validator.Pop.BabylonSig, - BtcSig: btcSig.MustMarshal(), - BtcSigType: bstypes.BTCSigType_BIP340, - } - - txHash := testutil.GenRandomHexStr(r, 32) - mockClientController.EXPECT(). - RegisterValidator( - validator.GetBabylonPK(), - validator.MustGetBIP340BTCPK(), - pop, - testutil.ZeroCommissionRate(), - testutil.EmptyDescription(), - ).Return(&provider.RelayerTxResponse{TxHash: txHash}, nil).AnyTimes() - - res, _, err := app.RegisterValidator(validator.KeyName) - require.NoError(t, err) - require.Equal(t, txHash, res.TxHash) - - err = app.StartHandlingValidator(validator.GetBabylonPK()) - require.NoError(t, err) - - valAfterReg, err := app.GetValidatorInstance(validator.GetBabylonPK()) - require.NoError(t, err) - require.Equal(t, valAfterReg.GetStoreValidator().Status, proto.ValidatorStatus_REGISTERED) - }) -} - -func FuzzAddJurySig(f *testing.F) { - testutil.AddRandomSeedsToFuzzer(f, 10) - f.Fuzz(func(t *testing.T, seed int64) { - r := rand.New(rand.NewSource(seed)) - - // create validator app with db and mocked Babylon client - cfg := valcfg.DefaultConfig() - cfg.DatabaseConfig = testutil.GenDBConfig(r, t) - cfg.BabylonConfig.KeyDirectory = t.TempDir() - defer func() { - err := os.RemoveAll(cfg.DatabaseConfig.Path) - require.NoError(t, err) - err = os.RemoveAll(cfg.BabylonConfig.KeyDirectory) - require.NoError(t, err) - }() - randomStartingHeight := uint64(r.Int63n(100) + 1) - finalizedHeight := randomStartingHeight + uint64(r.Int63n(10)+1) - currentHeight := finalizedHeight + uint64(r.Int63n(10)+2) - mockClientController := testutil.PrepareMockedClientController(t, r, finalizedHeight, currentHeight) - app, err := service.NewValidatorAppFromConfig(&cfg, logrus.New(), mockClientController) - require.NoError(t, err) - - // create a validator object and save it to db - validator := testutil.GenStoredValidator(r, t, app) - btcPkBIP340 := validator.MustGetBIP340BTCPK() - btcPk := validator.MustGetBTCPK() - - // create a Jury key pair in the keyring - juryKc, err := val.NewKeyringControllerWithKeyring(app.GetKeyring(), cfg.JuryModeConfig.JuryKeyName) - require.NoError(t, err) - jurPk, err := juryKc.CreateJuryKey() - require.NoError(t, err) - require.NotNil(t, jurPk) - cfg.JuryMode = true - - err = app.Start() - require.NoError(t, err) - defer func() { - err = app.Stop() - require.NoError(t, err) - }() - - // generate BTC delegation - slashingAddr, err := datagen.GenRandomBTCAddress(r, &chaincfg.SimNetParams) - require.NoError(t, err) - delSK, delPK, err := datagen.GenRandomBTCKeyPair(r) - require.NoError(t, err) - stakingTimeBlocks := uint16(5) - stakingValue := int64(2 * 10e8) - stakingTx, slashingTx, err := datagen.GenBTCStakingSlashingTx(r, &chaincfg.SimNetParams, delSK, btcPk, jurPk, stakingTimeBlocks, stakingValue, slashingAddr.String()) - require.NoError(t, err) - delBabylonSK, delBabylonPK, err := datagen.GenRandomSecp256k1KeyPair(r) - require.NoError(t, err) - pop, err := bstypes.NewPoP(delBabylonSK, delSK) - require.NoError(t, err) - require.NoError(t, err) - delegation := &bstypes.BTCDelegation{ - ValBtcPk: btcPkBIP340, - BtcPk: bbntypes.NewBIP340PubKeyFromBTCPK(delPK), - BabylonPk: delBabylonPK.(*secp256k1.PubKey), - Pop: pop, - StakingTx: stakingTx, - SlashingTx: slashingTx, - } - - stakingMsgTx, err := stakingTx.ToMsgTx() - require.NoError(t, err) - expectedTxHash := testutil.GenRandomHexStr(r, 32) - mockClientController.EXPECT().QueryPendingBTCDelegations(). - Return([]*bstypes.BTCDelegation{delegation}, nil).AnyTimes() - mockClientController.EXPECT().SubmitJurySig(delegation.ValBtcPk, delegation.BtcPk, stakingMsgTx.TxHash().String(), gomock.Any()). - Return(&provider.RelayerTxResponse{TxHash: expectedTxHash}, nil).AnyTimes() - res, err := app.AddJurySignature(delegation) - require.NoError(t, err) - require.Equal(t, expectedTxHash, res.TxHash) - }) -} diff --git a/service/chain_poller.go b/service/chain_poller.go deleted file mode 100644 index a80ff612..00000000 --- a/service/chain_poller.go +++ /dev/null @@ -1,266 +0,0 @@ -package service - -import ( - "fmt" - "sync" - "time" - - "github.com/avast/retry-go/v4" - ctypes "github.com/cometbft/cometbft/rpc/core/types" - "github.com/sirupsen/logrus" - - "github.com/babylonchain/btc-validator/clientcontroller" - "github.com/babylonchain/btc-validator/types" - cfg "github.com/babylonchain/btc-validator/valcfg" -) - -var ( - // TODO: Maybe configurable? - RtyAttNum = uint(5) - RtyAtt = retry.Attempts(RtyAttNum) - RtyDel = retry.Delay(time.Millisecond * 400) - RtyErr = retry.LastErrorOnly(true) -) - -const ( - // TODO: Maybe configurable? - maxFailedCycles = 20 -) - -type ChainPoller struct { - startOnce sync.Once - stopOnce sync.Once - wg sync.WaitGroup - mu sync.Mutex - quit chan struct{} - - cc clientcontroller.ClientController - cfg *cfg.ChainPollerConfig - blockInfoChan chan *types.BlockInfo - nextHeight uint64 - logger *logrus.Logger -} - -func NewChainPoller( - logger *logrus.Logger, - cfg *cfg.ChainPollerConfig, - cc clientcontroller.ClientController, -) *ChainPoller { - return &ChainPoller{ - logger: logger, - cfg: cfg, - cc: cc, - blockInfoChan: make(chan *types.BlockInfo, cfg.BufferSize), - quit: make(chan struct{}), - } -} - -func (cp *ChainPoller) Start(startHeight uint64) error { - var startErr error - cp.startOnce.Do(func() { - cp.logger.Infof("Starting the chain poller") - - err := cp.validateStartHeight(startHeight) - if err != nil { - startErr = err - return - } - - cp.nextHeight = startHeight - - cp.wg.Add(1) - - go cp.pollChain() - }) - return startErr -} - -func (cp *ChainPoller) Stop() error { - var stopError error - cp.stopOnce.Do(func() { - cp.logger.Infof("Stopping the chain poller") - err := cp.cc.Close() - if err != nil { - stopError = err - return - } - close(cp.quit) - cp.wg.Wait() - }) - - return stopError -} - -// Return read only channel for incoming blocks -// TODO: Handle the case when there is more than one consumer. Currently with more than -// one consumer blocks most probably will be received out of order to those consumers. -func (cp *ChainPoller) GetBlockInfoChan() <-chan *types.BlockInfo { - return cp.blockInfoChan -} - -func (cp *ChainPoller) nodeStatusWithRetry() (*ctypes.ResultStatus, error) { - var response *ctypes.ResultStatus - - if err := retry.Do(func() error { - status, err := cp.cc.QueryNodeStatus() - if err != nil { - return err - } - response = status - return nil - }, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { - cp.logger.WithFields(logrus.Fields{ - "attempt": n + 1, - "max_attempts": RtyAttNum, - "error": err, - }).Debug("Failed to query babylon For the latest height") - })); err != nil { - return nil, err - } - return response, nil -} - -func (cp *ChainPoller) headerWithRetry(height uint64) (*ctypes.ResultHeader, error) { - var response *ctypes.ResultHeader - if err := retry.Do(func() error { - headerResult, err := cp.cc.QueryHeader(int64(height)) - if err != nil { - return err - } - response = headerResult - return nil - }, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { - cp.logger.WithFields(logrus.Fields{ - "attempt": n + 1, - "max_attempts": RtyAttNum, - "height": height, - "error": err, - }).Debug("failed to query the consumer chain for the header") - })); err != nil { - return nil, err - } - - return response, nil -} - -func (cp *ChainPoller) validateStartHeight(startHeight uint64) error { - // Infinite retry to get initial latest height - // TODO: Add possible cancellation or timeout for starting node - - if startHeight == 0 { - return fmt.Errorf("start height can't be 0") - } - - var currentBestChainHeight uint64 - for { - status, err := cp.nodeStatusWithRetry() - if err != nil { - cp.logger.WithFields(logrus.Fields{ - "error": err, - }).Error("Failed to query babylon for the latest status") - continue - } - - currentBestChainHeight = uint64(status.SyncInfo.LatestBlockHeight) - break - } - - // Allow the start height to be the next chain height - if startHeight > currentBestChainHeight+1 { - return fmt.Errorf("start height %d is more than the next chain tip height %d", startHeight, currentBestChainHeight+1) - } - - return nil -} - -func (cp *ChainPoller) pollChain() { - defer cp.wg.Done() - - var failedCycles uint64 - - for { - // TODO: Handlig of request cancellation, as otherwise shutdown will be blocked - // until request is finished - headerToRetrieve := cp.GetNextHeight() - result, err := cp.headerWithRetry(headerToRetrieve) - if err == nil && result.Header != nil { - // no error and we got the header we wanted to get, bump the state and push - // notification about data - cp.SetNextHeight(headerToRetrieve + 1) - failedCycles = 0 - - cp.logger.WithFields(logrus.Fields{ - "height": result.Header.Height, - }).Info("the poller retrieved the header from the consumer chain") - - // Push the data to the channel. - // If the cosumers are to slow i.e the buffer is full, this will block and we will - // stop retrieving data from the node. - cp.blockInfoChan <- &types.BlockInfo{ - Height: uint64(result.Header.Height), - LastCommitHash: result.Header.LastCommitHash, - } - - } else if err == nil && result.Header == nil { - // no error but header is nil, means the header is not found on node - failedCycles++ - - cp.logger.WithFields(logrus.Fields{ - "error": err, - "currFailures": failedCycles, - "headerToGet": headerToRetrieve, - }).Error("failed to retrieve header from the consumer chain. Header did not produced yet") - - } else { - failedCycles++ - - cp.logger.WithFields(logrus.Fields{ - "error": err, - "currFailures": failedCycles, - "headerToGet": headerToRetrieve, - }).Error("failed to query the consumer chain for the header") - } - - if failedCycles > maxFailedCycles { - cp.logger.Fatal("the poller has reached the max failed cycles, exiting") - } - - select { - case <-time.After(cp.cfg.PollInterval): - - case <-cp.quit: - return - } - } -} - -func (cp *ChainPoller) GetNextHeight() uint64 { - return cp.getNextHeight() -} - -func (cp *ChainPoller) getNextHeight() uint64 { - cp.mu.Lock() - defer cp.mu.Unlock() - return cp.nextHeight -} - -func (cp *ChainPoller) setNextHeight(height uint64) { - cp.mu.Lock() - defer cp.mu.Unlock() - cp.nextHeight = height -} - -func (cp *ChainPoller) SetNextHeight(height uint64) { - cp.setNextHeight(height) -} - -func (cp *ChainPoller) SetNextHeightAndClearBuffer(height uint64) { - cp.SetNextHeight(height) - cp.clearChanBuffer() -} - -func (cp *ChainPoller) clearChanBuffer() { - for len(cp.blockInfoChan) > 0 { - <-cp.blockInfoChan - } -} diff --git a/service/client/rpcclient.go b/service/client/rpcclient.go deleted file mode 100644 index fa2b2777..00000000 --- a/service/client/rpcclient.go +++ /dev/null @@ -1,97 +0,0 @@ -package client - -import ( - "context" - "fmt" - - sdktypes "github.com/cosmos/cosmos-sdk/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" - - "github.com/babylonchain/btc-validator/proto" -) - -type ValidatorServiceGRpcClient struct { - client proto.BtcValidatorsClient -} - -func NewValidatorServiceGRpcClient(remoteAddr string) (*ValidatorServiceGRpcClient, func(), error) { - conn, err := grpc.Dial(remoteAddr, grpc.WithTransportCredentials(insecure.NewCredentials())) - if err != nil { - return nil, nil, fmt.Errorf("failed to build gRPC connection to %s: %w", remoteAddr, err) - } - - cleanUp := func() { - conn.Close() - } - - return &ValidatorServiceGRpcClient{ - client: proto.NewBtcValidatorsClient(conn), - }, cleanUp, nil -} - -func (c *ValidatorServiceGRpcClient) GetInfo(ctx context.Context) (*proto.GetInfoResponse, error) { - req := &proto.GetInfoRequest{} - res, err := c.client.GetInfo(ctx, req) - if err != nil { - return nil, err - } - - return res, nil -} - -func (c *ValidatorServiceGRpcClient) RegisterValidator(ctx context.Context, keyName string) (*proto.RegisterValidatorResponse, error) { - req := &proto.RegisterValidatorRequest{KeyName: keyName} - res, err := c.client.RegisterValidator(ctx, req) - if err != nil { - return nil, err - } - - return res, nil -} - -func (c *ValidatorServiceGRpcClient) CreateValidator(ctx context.Context, keyName string, description *stakingtypes.Description, commission *sdktypes.Dec) (*proto.CreateValidatorResponse, error) { - req := &proto.CreateValidatorRequest{KeyName: keyName, Description: description, Commission: commission.String()} - res, err := c.client.CreateValidator(ctx, req) - if err != nil { - return nil, err - } - - return res, nil -} - -func (c *ValidatorServiceGRpcClient) AddFinalitySignature(ctx context.Context, bbnPk []byte, height uint64, lch []byte) (*proto.AddFinalitySignatureResponse, error) { - req := &proto.AddFinalitySignatureRequest{ - BabylonPk: bbnPk, - Height: height, - LastCommitHash: lch, - } - - res, err := c.client.AddFinalitySignature(ctx, req) - if err != nil { - return nil, err - } - - return res, nil -} - -func (c *ValidatorServiceGRpcClient) QueryValidatorList(ctx context.Context) (*proto.QueryValidatorListResponse, error) { - req := &proto.QueryValidatorListRequest{} - res, err := c.client.QueryValidatorList(ctx, req) - if err != nil { - return nil, err - } - - return res, nil -} - -func (c *ValidatorServiceGRpcClient) QueryValidatorInfo(ctx context.Context, bbnPk []byte) (*proto.QueryValidatorResponse, error) { - req := &proto.QueryValidatorRequest{BabylonPk: bbnPk} - res, err := c.client.QueryValidator(ctx, req) - if err != nil { - return nil, err - } - - return res, nil -} diff --git a/service/event_loop.go b/service/event_loop.go deleted file mode 100644 index afd0e7ba..00000000 --- a/service/event_loop.go +++ /dev/null @@ -1,166 +0,0 @@ -package service - -import ( - "encoding/hex" - "time" - - "github.com/sirupsen/logrus" - - "github.com/babylonchain/btc-validator/proto" -) - -// jurySigSubmissionLoop is the reactor to submit Jury signature for pending BTC delegations -func (app *ValidatorApp) jurySigSubmissionLoop() { - defer app.wg.Done() - - interval := app.config.JuryModeConfig.QueryInterval - jurySigTicker := time.NewTicker(interval) - - for { - select { - case <-jurySigTicker.C: - // 1. Get all pending delegations first, this are more important than the unbonding ones - dels, err := app.cc.QueryPendingBTCDelegations() - if err != nil { - app.logger.WithFields(logrus.Fields{ - "err": err, - }).Error("failed to get pending delegations") - continue - } - if len(dels) == 0 { - app.logger.WithFields(logrus.Fields{}).Debug("no pending delegations are found") - } - - for _, d := range dels { - _, err := app.AddJurySignature(d) - if err != nil { - app.logger.WithFields(logrus.Fields{ - "err": err, - "del_btc_pk": d.BtcPk, - }).Error("failed to submit Jury sig to the Bitcoin delegation") - } - } - // 2. Get all unbonding delegations - unbondingDels, err := app.cc.QueryUnbondindBTCDelegations() - - if err != nil { - app.logger.WithFields(logrus.Fields{ - "err": err, - }).Error("failed to get pending delegations") - continue - } - - if len(unbondingDels) == 0 { - app.logger.WithFields(logrus.Fields{}).Debug("no unbonding delegations are found") - } - - for _, d := range unbondingDels { - _, err := app.AddJuryUnbondingSignatures(d) - if err != nil { - app.logger.WithFields(logrus.Fields{ - "err": err, - "del_btc_pk": d.BtcPk, - }).Error("failed to submit Jury sig to the Bitcoin delegation") - } - } - - case <-app.quit: - app.logger.Debug("exiting jurySigSubmissionLoop") - return - } - } - -} - -// main event loop for the validator app -func (app *ValidatorApp) eventLoop() { - defer app.eventWg.Done() - - for { - select { - case req := <-app.createValidatorRequestChan: - resp, err := app.handleCreateValidatorRequest(req) - - if err != nil { - req.errResponse <- err - continue - } - - req.successResponse <- resp - - case ev := <-app.validatorRegisteredEventChan: - valStored, err := app.vs.GetStoreValidator(ev.bbnPubKey.Key) - - if err != nil { - // we always check if the validator is in the DB before sending the registration request - app.logger.WithFields(logrus.Fields{ - "bbn_pk": ev.bbnPubKey, - }).Fatal("registered validator not found in DB") - } - - // change the status of the validator to registered - err = app.vs.SetValidatorStatus(valStored, proto.ValidatorStatus_REGISTERED) - - if err != nil { - app.logger.WithFields(logrus.Fields{ - "bbn_pk": ev.bbnPubKey, - }).Fatal("err while saving validator to DB") - } - - // return to the caller - ev.successResponse <- &RegisterValidatorResponse{ - TxHash: ev.txHash, - } - - case <-app.eventQuit: - app.logger.Debug("exiting main eventLoop") - return - } - } -} - -// Loop for handling requests to send stuff to babylon. It is necessart to properly -// serialize bayblon sends as otherwise we would keep hitting sequence mismatch errors. -// This could be done either by send loop or by lock. We choose send loop as it is -// more flexible. -// TODO: This could be probably separate component responsible for queuing stuff -// and sending it to babylon. -func (app *ValidatorApp) handleSentToBabylonLoop() { - defer app.sentWg.Done() - for { - select { - case req := <-app.registerValidatorRequestChan: - // we won't do any retries here to not block the loop for more important messages. - // Most probably it fails due so some user error so we just return the error to the user. - // TODO: need to start passing context here to be able to cancel the request in case of app quiting - res, err := app.cc.RegisterValidator(req.bbnPubKey, req.btcPubKey, req.pop, req.commission, req.description) - - if err != nil { - app.logger.WithFields(logrus.Fields{ - "err": err, - "bbnPubKey": hex.EncodeToString(req.bbnPubKey.Key), - "btcPubKey": req.btcPubKey.MarshalHex(), - }).Error("failed to register validator") - req.errResponse <- err - continue - } - - app.logger.WithFields(logrus.Fields{ - "bbnPk": hex.EncodeToString(req.bbnPubKey.Key), - "btcPubKey": req.btcPubKey.MarshalHex(), - "txHash": res.TxHash, - }).Info("successfully registered validator on babylon") - - app.validatorRegisteredEventChan <- &validatorRegisteredEvent{ - bbnPubKey: req.bbnPubKey, - txHash: res.TxHash, - // pass the channel to the event so that we can send the response to the user which requested - // the registration - successResponse: req.successResponse, - } - case <-app.sentQuit: - app.logger.Debug("exiting sentToBabylonLoop") - return - } - } -} diff --git a/service/fastsync_test.go b/service/fastsync_test.go deleted file mode 100644 index 54800e4e..00000000 --- a/service/fastsync_test.go +++ /dev/null @@ -1,61 +0,0 @@ -package service_test - -import ( - "math/rand" - "testing" - - "github.com/cosmos/relayer/v2/relayer/provider" - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/require" - - "github.com/babylonchain/btc-validator/testutil" - "github.com/babylonchain/btc-validator/types" -) - -func FuzzFastSync(f *testing.F) { - testutil.AddRandomSeedsToFuzzer(f, 10) - f.Fuzz(func(t *testing.T, seed int64) { - r := rand.New(rand.NewSource(seed)) - - randomStartingHeight := uint64(r.Int63n(100) + 1) - finalizedHeight := randomStartingHeight + uint64(r.Int63n(10)+2) - currentHeight := finalizedHeight + uint64(r.Int63n(10)+1) - startingBlock := &types.BlockInfo{Height: randomStartingHeight, LastCommitHash: testutil.GenRandomByteArray(r, 32)} - mockClientController := testutil.PrepareMockedClientController(t, r, randomStartingHeight, currentHeight) - app, storeValidator, cleanUp := newValidatorAppWithRegisteredValidator(t, r, mockClientController, randomStartingHeight) - defer cleanUp() - err := app.Start() - require.NoError(t, err) - valIns, err := app.GetValidatorInstance(storeValidator.GetBabylonPK()) - require.NoError(t, err) - - // commit public randomness - expectedTxHash := testutil.GenRandomHexStr(r, 32) - mockClientController.EXPECT(). - CommitPubRandList(valIns.GetBtcPkBIP340(), startingBlock.Height+1, gomock.Any(), gomock.Any()). - Return(&provider.RelayerTxResponse{TxHash: expectedTxHash}, nil).AnyTimes() - mockClientController.EXPECT().QueryHeightWithLastPubRand(valIns.GetBtcPkBIP340()). - Return(uint64(0), nil).AnyTimes() - res, err := valIns.CommitPubRand(startingBlock) - require.NoError(t, err) - require.Equal(t, expectedTxHash, res.TxHash) - mockClientController.EXPECT().QueryValidatorVotingPower(storeValidator.MustGetBIP340BTCPK(), gomock.Any()). - Return(uint64(1), nil).AnyTimes() - - // fast sync - catchUpBlocks := testutil.GenBlocks(r, finalizedHeight+1, currentHeight) - expectedTxHash = testutil.GenRandomHexStr(r, 32) - finalizedBlock := &types.BlockInfo{Height: finalizedHeight, LastCommitHash: testutil.GenRandomByteArray(r, 32)} - mockClientController.EXPECT().QueryLatestFinalizedBlocks(uint64(1)).Return([]*types.BlockInfo{finalizedBlock}, nil).AnyTimes() - mockClientController.EXPECT().QueryBlocks(finalizedHeight+1, currentHeight, uint64(10)). - Return(catchUpBlocks, nil) - mockClientController.EXPECT().SubmitBatchFinalitySigs(valIns.GetBtcPkBIP340(), catchUpBlocks, gomock.Any()). - Return(&provider.RelayerTxResponse{TxHash: expectedTxHash}, nil).AnyTimes() - result, err := valIns.FastSync(finalizedHeight+1, currentHeight) - require.NoError(t, err) - require.NotNil(t, result) - require.Equal(t, expectedTxHash, result.Responses[0].TxHash) - require.Equal(t, currentHeight, valIns.GetLastVotedHeight()) - require.Equal(t, currentHeight, valIns.GetLastProcessedHeight()) - }) -} diff --git a/service/rpcserver.go b/service/rpcserver.go deleted file mode 100644 index f6c449fb..00000000 --- a/service/rpcserver.go +++ /dev/null @@ -1,219 +0,0 @@ -package service - -import ( - "context" - "encoding/hex" - "fmt" - "sync" - "sync/atomic" - - "cosmossdk.io/math" - bbntypes "github.com/babylonchain/babylon/types" - "github.com/btcsuite/btcd/btcec/v2/schnorr" - "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - "github.com/lightningnetwork/lnd/signal" - "github.com/sirupsen/logrus" - "google.golang.org/grpc" - - "github.com/babylonchain/btc-validator/proto" - "github.com/babylonchain/btc-validator/types" - "github.com/babylonchain/btc-validator/valcfg" - "github.com/babylonchain/btc-validator/version" -) - -// rpcServer is the main RPC server for the BTC-Validator daemon that handles -// gRPC incoming requests. -type rpcServer struct { - started int32 - shutdown int32 - - proto.UnimplementedBtcValidatorsServer - - interceptor signal.Interceptor - - app *ValidatorApp - - logger *logrus.Logger - - cfg *valcfg.Config - - quit chan struct{} - wg sync.WaitGroup -} - -// newRPCServer creates a new RPC sever from the set of input dependencies. -func newRPCServer( - interceptor signal.Interceptor, - l *logrus.Logger, - cfg *valcfg.Config, - v *ValidatorApp, -) (*rpcServer, error) { - - return &rpcServer{ - interceptor: interceptor, - logger: l, - quit: make(chan struct{}), - cfg: cfg, - app: v, - }, nil -} - -// Start signals that the RPC server starts accepting requests. -func (r *rpcServer) Start() error { - if atomic.AddInt32(&r.started, 1) != 1 { - return nil - } - - r.logger.Infof("Starting RPC Server") - - return nil -} - -// Stop signals that the RPC server should attempt a graceful shutdown and -// cancel any outstanding requests. -func (r *rpcServer) Stop() error { - if atomic.AddInt32(&r.shutdown, 1) != 1 { - return nil - } - - r.logger.Infof("Stopping RPC Server") - - close(r.quit) - - r.wg.Wait() - - return nil -} - -// RegisterWithGrpcServer registers the rpcServer with the passed root gRPC -// server. -func (r *rpcServer) RegisterWithGrpcServer(grpcServer *grpc.Server) error { - // Register the main RPC server. - proto.RegisterBtcValidatorsServer(grpcServer, r) - return nil -} - -// GetInfo returns general information relating to the active daemon -func (r *rpcServer) GetInfo(context.Context, *proto.GetInfoRequest) (*proto.GetInfoResponse, error) { - - return &proto.GetInfoResponse{ - Version: version.Version(), - }, nil -} - -// CreateValidator generates a validator object and saves it in the database -func (r *rpcServer) CreateValidator(ctx context.Context, req *proto.CreateValidatorRequest) ( - *proto.CreateValidatorResponse, error) { - - commissionRate, err := math.LegacyNewDecFromStr(req.Commission) - if err != nil { - return nil, err - } - result, err := r.app.CreateValidator(req.KeyName, req.Description, &commissionRate) - - if err != nil { - return nil, err - } - - btcPk := bbntypes.BIP340PubKey(schnorr.SerializePubKey(&result.BtcValidatorPk)) - - return &proto.CreateValidatorResponse{ - BtcPk: btcPk.MarshalHex(), - BabylonPk: hex.EncodeToString(result.BabylonValidatorPk.Key), - }, nil - -} - -// RegisterValidator sends a transactions to Babylon to register a BTC validator -func (r *rpcServer) RegisterValidator(ctx context.Context, req *proto.RegisterValidatorRequest) ( - *proto.RegisterValidatorResponse, error) { - - txRes, bbnPk, err := r.app.RegisterValidator(req.KeyName) - if err != nil { - return nil, fmt.Errorf("failed to register the validator to Babylon: %w", err) - } - - // the validator instance should be started right after registration - if err := r.app.StartHandlingValidator(bbnPk); err != nil { - return nil, fmt.Errorf("failed to start the registered validator %s: %w", hex.EncodeToString(bbnPk.Key), err) - } - - return &proto.RegisterValidatorResponse{TxHash: txRes.TxHash}, nil -} - -// AddFinalitySignature adds a manually constructed finality signature to Babylon -// NOTE: this is only used for presentation/testing purposes -func (r *rpcServer) AddFinalitySignature(ctx context.Context, req *proto.AddFinalitySignatureRequest) ( - *proto.AddFinalitySignatureResponse, error) { - - bbnPk := &secp256k1.PubKey{Key: req.BabylonPk} - v, err := r.app.GetValidatorInstance(bbnPk) - if err != nil { - return nil, err - } - - b := &types.BlockInfo{ - Height: req.Height, - LastCommitHash: req.LastCommitHash, - } - - txRes, privKey, err := v.TestSubmitFinalitySignatureAndExtractPrivKey(b) - if err != nil { - return nil, err - } - - res := &proto.AddFinalitySignatureResponse{TxHash: txRes.TxHash} - - // if privKey is not empty, then this BTC validator - // has voted for a fork and will be slashed - if privKey != nil { - localPrivKey, err := r.app.getBtcPrivKey(v.GetStoreValidator().KeyName) - res.ExtractedSkHex = privKey.Key.String() - if err != nil { - return nil, err - } - localSkHex := localPrivKey.Key.String() - localSkNegateHex := localPrivKey.Key.Negate().String() - if res.ExtractedSkHex == localSkHex { - res.LocalSkHex = localSkHex - } else if res.ExtractedSkHex == localSkNegateHex { - res.LocalSkHex = localSkNegateHex - } else { - return nil, fmt.Errorf("the validator's BTC private key is extracted but does not match the local key,"+ - "extrated: %s, local: %s, local-negated: %s", - res.ExtractedSkHex, localSkHex, localSkNegateHex) - } - } - - return res, nil -} - -// QueryValidator queries the information of the validator -func (r *rpcServer) QueryValidator(ctx context.Context, req *proto.QueryValidatorRequest) ( - *proto.QueryValidatorResponse, error) { - - bbnPk := &secp256k1.PubKey{Key: req.BabylonPk} - val, err := r.app.GetValidatorInstance(bbnPk) - if err != nil { - return nil, err - } - - valInfo := proto.NewValidatorInfo(val.GetStoreValidator()) - - return &proto.QueryValidatorResponse{Validator: valInfo}, nil -} - -// QueryValidatorList queries the information of a list of validators -func (r *rpcServer) QueryValidatorList(ctx context.Context, req *proto.QueryValidatorListRequest) ( - *proto.QueryValidatorListResponse, error) { - - vals := r.app.ListValidatorInstances() - - valsInfo := make([]*proto.ValidatorInfo, len(vals)) - for i, v := range vals { - valInfo := proto.NewValidatorInfo(v.GetStoreValidator()) - valsInfo[i] = valInfo - } - - return &proto.QueryValidatorListResponse{Validators: valsInfo}, nil -} diff --git a/service/server.go b/service/server.go deleted file mode 100644 index 49b4182e..00000000 --- a/service/server.go +++ /dev/null @@ -1,207 +0,0 @@ -package service - -import ( - "fmt" - "net" - "strings" - "sync" - "sync/atomic" - - "github.com/lightningnetwork/lnd/build" - "github.com/lightningnetwork/lnd/signal" - "github.com/sirupsen/logrus" - "google.golang.org/grpc" - - "github.com/babylonchain/btc-validator/valcfg" - "github.com/babylonchain/btc-validator/version" -) - -// Server is the main daemon construct for the BTC-Validator server. It handles -// spinning up the RPC sever, the database, and any other components that the -// Taproot Asset server needs to function. -type Server struct { - started int32 - - cfg *valcfg.Config - logger *logrus.Logger - - valApp *ValidatorApp - rpcServer *rpcServer - interceptor signal.Interceptor - - quit chan struct{} -} - -// NewValidatorServer creates a new server with the given config. -func NewValidatorServer(cfg *valcfg.Config, l *logrus.Logger, v *ValidatorApp, sig signal.Interceptor) *Server { - return &Server{ - cfg: cfg, - logger: l, - valApp: v, - interceptor: sig, - quit: make(chan struct{}, 1), - } -} - -// RunUntilShutdown runs the main BTC-Validator server loop until a signal is -// received to shut down the process. -func (s *Server) RunUntilShutdown() error { - if atomic.AddInt32(&s.started, 1) != 1 { - return nil - } - - defer func() { - s.logger.Info("Shutdown complete") - }() - - mkErr := func(format string, args ...interface{}) error { - logFormat := strings.ReplaceAll(format, "%w", "%v") - s.logger.Errorf("Shutting down because error in main "+ - "method: "+logFormat, args...) - return fmt.Errorf(format, args...) - } - - // we create listeners from the RPCListeners defined - // in the config. - grpcListeners := make([]net.Listener, 0) - for _, grpcEndpoint := range s.cfg.RpcListeners { - // Start a gRPC server listening for HTTP/2 - // connections. - lis, err := net.Listen(parseNetwork(grpcEndpoint), grpcEndpoint.String()) - if err != nil { - return mkErr("unable to listen on %s: %v", - grpcEndpoint, err) - } - defer lis.Close() - - grpcListeners = append(grpcListeners, lis) - } - - err := s.initialize() - if err != nil { - return mkErr("unable to initialize RPC server: %v", err) - } - - grpcServer := grpc.NewServer() - defer grpcServer.Stop() - - err = s.rpcServer.RegisterWithGrpcServer(grpcServer) - if err != nil { - return mkErr("error registering gRPC server: %v", err) - } - - // All the necessary components have been registered, so we can - // actually start listening for requests. - err = s.startGrpcListen(grpcServer, grpcListeners) - if err != nil { - return mkErr("error starting gRPC listener: %v", err) - } - - defer func() { - _ = s.rpcServer.Stop() - }() - - s.logger.Infof("BTC Validator Daemon is fully active!") - - // Wait for shutdown signal from either a graceful server stop or from - // the interrupt handler. - <-s.interceptor.ShutdownChannel() - - return nil -} - -// initialize creates and initializes an instance rpc server based on the server -// configuration. This method ensures that everything is cleaned up in case there -// is an error while initializing any of the components. -// -// NOTE: the rpc server is not registered with any grpc server in this function. -func (s *Server) initialize() error { - // Show version at startup. - s.logger.Infof("Version: %s, build=%s, logging=%s, "+ - "debuglevel=%s", version.Version(), build.Deployment, - build.LoggingType, s.cfg.DebugLevel) - - // Depending on how far we got in initializing the server, we might need - // to clean up certain services that were already started. Keep track of - // them with this map of service name to shut down function. - shutdownFuncs := make(map[string]func() error) - defer func() { - for serviceName, shutdownFn := range shutdownFuncs { - if err := shutdownFn(); err != nil { - s.logger.Errorf("Error shutting down %s service: %s", serviceName, err.Error()) - } - } - }() - - // Initialize, and register our implementation of the gRPC interface - // exported by the rpcServer. - var err error - s.rpcServer, err = newRPCServer( - s.interceptor, s.logger, s.cfg, s.valApp, - ) - if err != nil { - return fmt.Errorf("failed to create rpc server: %v", err) - } - - // Now we have created all dependencies necessary to populate and - // start the RPC server. - if err := s.rpcServer.Start(); err != nil { - return fmt.Errorf("failed to start RPC server: %v", err) - } - - // This does have no effect if starting the rpc server is the last step - // in this function, but its better to have it here in case we add more - // steps in the future. - // - // NOTE: if this is not the last step in the function, feel free to - // delete this comment. - shutdownFuncs["rpcServer"] = s.rpcServer.Stop - - shutdownFuncs = nil - - return nil -} - -// startGrpcListen starts the GRPC server on the passed listeners. -func (s *Server) startGrpcListen(grpcServer *grpc.Server, listeners []net.Listener) error { - - // Use a WaitGroup so we can be sure the instructions on how to input the - // password is the last thing to be printed to the console. - var wg sync.WaitGroup - - for _, lis := range listeners { - wg.Add(1) - go func(lis net.Listener) { - s.logger.Infof("RPC server listening on %s", lis.Addr()) - - // Close the ready chan to indicate we are listening. - defer lis.Close() - - wg.Done() - _ = grpcServer.Serve(lis) - }(lis) - } - - // Wait for gRPC servers to be up running. - wg.Wait() - - return nil -} - -// parseNetwork parses the network type of the given address. -func parseNetwork(addr net.Addr) string { - switch addr := addr.(type) { - // TCP addresses resolved through net.ResolveTCPAddr give a default - // network of "tcp", so we'll map back the correct network for the given - // address. This ensures that we can listen on the correct interface - // (IPv4 vs IPv6). - case *net.TCPAddr: - if addr.IP.To4() != nil { - return "tcp4" - } - return "tcp6" - - default: - return addr.Network() - } -} diff --git a/service/types.go b/service/types.go deleted file mode 100644 index ad61dd7f..00000000 --- a/service/types.go +++ /dev/null @@ -1,63 +0,0 @@ -package service - -import ( - "github.com/babylonchain/babylon/types" - btcstakingtypes "github.com/babylonchain/babylon/x/btcstaking/types" - "github.com/btcsuite/btcd/btcec/v2" - "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - sdktypes "github.com/cosmos/cosmos-sdk/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" -) - -type createValidatorResponse struct { - BtcValidatorPk btcec.PublicKey - BabylonValidatorPk secp256k1.PubKey -} -type createValidatorRequest struct { - keyName string - description *stakingtypes.Description - commission *sdktypes.Dec - errResponse chan error - successResponse chan *createValidatorResponse -} - -type registerValidatorRequest struct { - bbnPubKey *secp256k1.PubKey - btcPubKey *types.BIP340PubKey - // TODO we should have our own representation of PoP - pop *btcstakingtypes.ProofOfPossession - description *stakingtypes.Description - commission *sdktypes.Dec - errResponse chan error - successResponse chan *RegisterValidatorResponse -} - -type validatorRegisteredEvent struct { - bbnPubKey *secp256k1.PubKey - txHash string - successResponse chan *RegisterValidatorResponse -} - -type RegisterValidatorResponse struct { - TxHash string -} - -type AddJurySigResponse struct { - TxHash string -} - -type CreateValidatorResult struct { - BtcValidatorPk btcec.PublicKey - BabylonValidatorPk secp256k1.PubKey -} - -type unbondingTxSigData struct { - stakerPk *types.BIP340PubKey - stakingTxHash string - signature *types.BIP340Signature -} - -type unbondingTxSigSendResult struct { - err error - stakingTxHash string -} diff --git a/service/utils.go b/service/utils.go deleted file mode 100644 index e9fa6a3b..00000000 --- a/service/utils.go +++ /dev/null @@ -1,27 +0,0 @@ -package service - -import ( - "math/rand" - "time" - - "github.com/babylonchain/babylon/crypto/eots" - "github.com/babylonchain/babylon/types" -) - -func GenerateRandPairList(num uint64) ([]*eots.PrivateRand, []types.SchnorrPubRand, error) { - srList := make([]*eots.PrivateRand, num) - prList := make([]types.SchnorrPubRand, num) - - r := rand.New(rand.NewSource(time.Now().UnixNano())) - - for i := uint64(0); i < num; i++ { - eotsSR, eotsPR, err := eots.RandGen(r) - if err != nil { - return nil, nil, err - } - pr := types.NewSchnorrPubRandFromFieldVal(eotsPR) - srList[i] = eotsSR - prList[i] = *pr - } - return srList, prList, nil -} diff --git a/service/validator_instance.go b/service/validator_instance.go deleted file mode 100644 index 624030a8..00000000 --- a/service/validator_instance.go +++ /dev/null @@ -1,1164 +0,0 @@ -package service - -import ( - "encoding/hex" - "errors" - "fmt" - "strings" - "sync" - "time" - - "github.com/avast/retry-go/v4" - "github.com/babylonchain/babylon/crypto/eots" - bbntypes "github.com/babylonchain/babylon/types" - bstypes "github.com/babylonchain/babylon/x/btcstaking/types" - ftypes "github.com/babylonchain/babylon/x/finality/types" - "github.com/btcsuite/btcd/btcec/v2" - "github.com/cosmos/cosmos-sdk/crypto/keyring" - "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - "github.com/cosmos/relayer/v2/relayer/provider" - "github.com/gogo/protobuf/jsonpb" - "github.com/sirupsen/logrus" - "go.uber.org/atomic" - "golang.org/x/sync/errgroup" - - "github.com/babylonchain/btc-validator/clientcontroller" - "github.com/babylonchain/btc-validator/proto" - "github.com/babylonchain/btc-validator/types" - "github.com/babylonchain/btc-validator/val" - "github.com/babylonchain/btc-validator/valcfg" -) - -type state struct { - v *proto.StoreValidator - s *val.ValidatorStore -} - -type ValidatorInstance struct { - bbnPk *secp256k1.PubKey - btcPk *bbntypes.BIP340PubKey - - state *state - cfg *valcfg.Config - - logger *logrus.Logger - kc *val.KeyringController - cc clientcontroller.ClientController - poller *ChainPoller - - laggingTargetChan chan *types.BlockInfo - criticalErrChan chan<- *CriticalError - - isStarted *atomic.Bool - inSync *atomic.Bool - isLagging *atomic.Bool - - wg sync.WaitGroup - quit chan struct{} -} - -// NewValidatorInstance returns a ValidatorInstance instance with the given Babylon public key -// the validator should be registered before -func NewValidatorInstance( - bbnPk *secp256k1.PubKey, - cfg *valcfg.Config, - s *val.ValidatorStore, - kr keyring.Keyring, - cc clientcontroller.ClientController, - errChan chan<- *CriticalError, - logger *logrus.Logger, -) (*ValidatorInstance, error) { - v, err := s.GetStoreValidator(bbnPk.Key) - if err != nil { - return nil, fmt.Errorf("failed to retrive the validator %s from DB: %w", v.GetBabylonPkHexString(), err) - } - - // ensure the validator has been registered - // TODO refactor this by getting the constants from Babylon - if v.Status < proto.ValidatorStatus_REGISTERED { - return nil, fmt.Errorf("the validator %s has not been registered", v.KeyName) - } - - kc, err := val.NewKeyringControllerWithKeyring(kr, v.KeyName) - if err != nil { - return nil, err - } - - return &ValidatorInstance{ - bbnPk: bbnPk, - btcPk: v.MustGetBIP340BTCPK(), - state: &state{ - v: v, - s: s, - }, - cfg: cfg, - logger: logger, - isStarted: atomic.NewBool(false), - inSync: atomic.NewBool(false), - isLagging: atomic.NewBool(false), - criticalErrChan: errChan, - kc: kc, - cc: cc, - }, nil -} - -func (v *ValidatorInstance) GetStoreValidator() *proto.StoreValidator { - return v.state.v -} - -func (v *ValidatorInstance) GetBabylonPk() *secp256k1.PubKey { - return v.state.v.GetBabylonPK() -} - -func (v *ValidatorInstance) GetBabylonPkHex() string { - return hex.EncodeToString(v.state.v.GetBabylonPk()) -} - -func (v *ValidatorInstance) GetBtcPkBIP340() *bbntypes.BIP340PubKey { - return v.state.v.MustGetBIP340BTCPK() -} - -func (v *ValidatorInstance) MustGetBtcPk() *btcec.PublicKey { - return v.state.v.MustGetBTCPK() -} - -// Exposed mostly for testing purposes -func (v *ValidatorInstance) BtcPrivKey() (*btcec.PrivateKey, error) { - return v.kc.GetBtcPrivKey() -} - -func (v *ValidatorInstance) GetBtcPkHex() string { - return v.GetBtcPkBIP340().MarshalHex() -} - -func (v *ValidatorInstance) GetStatus() proto.ValidatorStatus { - return v.state.v.Status -} - -func (v *ValidatorInstance) GetLastVotedHeight() uint64 { - return v.state.v.LastVotedHeight -} - -func (v *ValidatorInstance) GetLastProcessedHeight() uint64 { - return v.state.v.LastProcessedHeight -} - -func (v *ValidatorInstance) GetLastCommittedHeight() uint64 { - return v.state.v.LastCommittedHeight -} - -func (v *ValidatorInstance) GetCommittedPubRandPairList() ([]*proto.SchnorrRandPair, error) { - return v.state.s.GetRandPairList(v.bbnPk.Key) -} - -func (v *ValidatorInstance) GetCommittedPubRandPair(height uint64) (*proto.SchnorrRandPair, error) { - return v.state.s.GetRandPair(v.bbnPk.Key, height) -} - -func (v *ValidatorInstance) GetCommittedPrivPubRand(height uint64) (*eots.PrivateRand, error) { - randPair, err := v.state.s.GetRandPair(v.bbnPk.Key, height) - if err != nil { - return nil, err - } - - if len(randPair.SecRand) != 32 { - return nil, fmt.Errorf("the private randomness should be 32 bytes") - } - - privRand := new(eots.PrivateRand) - privRand.SetByteSlice(randPair.SecRand) - - return privRand, nil -} - -func (v *ValidatorInstance) SetStatus(s proto.ValidatorStatus) error { - v.state.v.Status = s - return v.state.s.UpdateValidator(v.state.v) -} - -func (v *ValidatorInstance) MustSetStatus(s proto.ValidatorStatus) { - if err := v.SetStatus(s); err != nil { - v.logger.WithFields(logrus.Fields{ - "err": err, - "btc_pk_hex": v.GetBtcPkHex(), - "status": s.String(), - }).Fatal("failed to set validator status") - } -} - -func (v *ValidatorInstance) SetLastVotedHeight(height uint64) error { - v.state.v.LastVotedHeight = height - return v.state.s.UpdateValidator(v.state.v) -} - -func (v *ValidatorInstance) MustSetLastVotedHeight(height uint64) { - if err := v.SetLastVotedHeight(height); err != nil { - v.logger.WithFields(logrus.Fields{ - "err": err, - "btc_pk_hex": v.GetBtcPkHex(), - "height": height, - }).Fatal("failed to set last voted height") - } -} - -func (v *ValidatorInstance) SetLastProcessedHeight(height uint64) error { - v.state.v.LastProcessedHeight = height - return v.state.s.UpdateValidator(v.state.v) -} - -func (v *ValidatorInstance) MustSetLastProcessedHeight(height uint64) { - if err := v.SetLastProcessedHeight(height); err != nil { - v.logger.WithFields(logrus.Fields{ - "err": err, - "btc_pk_hex": v.GetBtcPkHex(), - "height": height, - }).Fatal("failed to set last processed height") - } -} - -func (v *ValidatorInstance) SetLastCommittedHeight(height uint64) error { - v.state.v.LastCommittedHeight = height - return v.state.s.UpdateValidator(v.state.v) -} - -func (v *ValidatorInstance) MustSetLastCommittedHeight(height uint64) { - if err := v.SetLastCommittedHeight(height); err != nil { - v.logger.WithFields(logrus.Fields{ - "err": err, - "btc_pk_hex": v.GetBtcPkHex(), - "height": height, - }).Fatal("failed to set last committed height") - } -} - -func (v *ValidatorInstance) updateStateAfterFinalitySigSubmission(height uint64) error { - v.state.v.LastProcessedHeight = height - v.state.v.LastVotedHeight = height - return v.state.s.UpdateValidator(v.state.v) -} - -func (v *ValidatorInstance) MustUpdateStateAfterFinalitySigSubmission(height uint64) { - if err := v.updateStateAfterFinalitySigSubmission(height); err != nil { - v.logger.WithFields(logrus.Fields{ - "err": err, - "btc_pk_hex": v.GetBtcPkHex(), - "height": height, - }).Fatal("failed to update state after finality sig submission") - } -} - -func (v *ValidatorInstance) Start() error { - if v.isStarted.Swap(true) { - return fmt.Errorf("the validator instance %s is already started", v.GetBtcPkHex()) - } - - v.logger.Infof("Starting thread handling validator %s", v.GetBtcPkHex()) - - startHeight, err := v.bootstrap() - if err != nil { - return fmt.Errorf("failed to bootstrap the validator %s: %w", v.GetBtcPkHex(), err) - } - - v.logger.Infof("the validator %s has been bootstrapped to %v", v.GetBtcPkHex(), startHeight) - - poller := NewChainPoller(v.logger, v.cfg.PollerConfig, v.cc) - - if err := poller.Start(startHeight + 1); err != nil { - return fmt.Errorf("failed to start the poller: %w", err) - } - - v.poller = poller - - v.laggingTargetChan = make(chan *types.BlockInfo) - - v.quit = make(chan struct{}) - - v.wg.Add(1) - go v.finalitySigSubmissionLoop() - v.wg.Add(1) - go v.randomnessCommitmentLoop() - v.wg.Add(1) - go v.unbondindSigSubmissionLoop() - v.wg.Add(1) - go v.checkLaggingLoop() - - return nil -} - -func (v *ValidatorInstance) bootstrap() (uint64, error) { - latestBlock, err := v.getLatestBlockWithRetry() - if err != nil { - return 0, err - } - - if v.checkLagging(latestBlock) { - _, err := v.tryFastSync(latestBlock) - if err != nil { - return 0, err - } - } - - startHeight, err := v.getPollerStartingHeight() - if err != nil { - return 0, err - } - - return startHeight, nil -} - -func (v *ValidatorInstance) Stop() error { - if !v.isStarted.Swap(false) { - return fmt.Errorf("the validator %s has already stopped", v.GetBtcPkHex()) - } - - if err := v.poller.Stop(); err != nil { - return fmt.Errorf("failed to stop the poller: %w", err) - } - - v.logger.Infof("stopping thread handling validator %s", v.GetBtcPkHex()) - - close(v.quit) - v.wg.Wait() - - v.logger.Debugf("The thread handling validator %s is successfully stopped", v.GetBtcPkHex()) - - return nil -} - -func (v *ValidatorInstance) IsRunning() bool { - return v.isStarted.Load() -} - -func (v *ValidatorInstance) signUnbondingTransactions( - privKey *btcec.PrivateKey, - toSign []*bstypes.BTCDelegation) ([]unbondingTxSigData, error) { - - var dataWithSignatures []unbondingTxSigData - for _, delegation := range toSign { - fundingTx, err := delegation.StakingTx.ToMsgTx() - - if err != nil { - return nil, fmt.Errorf("failed to deserialize staking tx: %w", err) - } - - fundingTxHash := fundingTx.TxHash().String() - - txToSign := delegation.BtcUndelegation.UnbondingTx - - sig, err := txToSign.Sign( - fundingTx, - delegation.StakingTx.Script, - privKey, - &v.cfg.ActiveNetParams, - ) - - if err != nil { - return nil, fmt.Errorf("failed to sign unbonding tx: %w", err) - } - - utd := unbondingTxSigData{ - stakerPk: delegation.BtcPk, - stakingTxHash: fundingTxHash, - signature: sig, - } - - dataWithSignatures = append(dataWithSignatures, utd) - } - - return dataWithSignatures, nil -} - -func (v *ValidatorInstance) sendSignaturesForUnbondingTransactions(sigsToSend []unbondingTxSigData) []unbondingTxSigSendResult { - var eg errgroup.Group - var mu sync.Mutex - var res []unbondingTxSigSendResult - - for _, sigData := range sigsToSend { - sd := sigData - eg.Go(func() error { - _, err := v.cc.SubmitValidatorUnbondingSig( - v.GetBtcPkBIP340(), - sd.stakerPk, - sd.stakingTxHash, - sd.signature, - ) - - mu.Lock() - defer mu.Unlock() - - if err != nil { - res = append(res, unbondingTxSigSendResult{ - err: err, - stakingTxHash: sd.stakingTxHash, - }) - } else { - res = append(res, unbondingTxSigSendResult{ - err: nil, - stakingTxHash: sd.stakingTxHash, - }) - } - - return nil - }) - } - - if err := eg.Wait(); err != nil { - // this should not happen as we do not return errors from our sending - v.logger.Fatalf("Failed to wait for signatures send") - } - - return res -} - -func (v *ValidatorInstance) unbondindSigSubmissionLoop() { - defer v.wg.Done() - - sendUnbondingSigTicker := time.NewTicker(v.cfg.UnbondingSigSubmissionInterval) - defer sendUnbondingSigTicker.Stop() - - for { - select { - case <-sendUnbondingSigTicker.C: - delegationsNeedingSignatures, err := v.cc.QueryBTCValidatorUnbondingDelegations( - v.GetBtcPkBIP340(), - // TODO: parameterize the max number of delegations to be queried - // it should not be to high to not take too long time to sign them - 10, - ) - - if err != nil { - v.logger.WithFields(logrus.Fields{ - "err": err, - "babylon_pk_hex": v.GetBabylonPkHex(), - }).Error("failed to query Babylon for BTC validator unbonding delegations") - continue - } - - if len(delegationsNeedingSignatures) == 0 { - continue - } - - v.logger.WithFields(logrus.Fields{ - "num_delegations": len(delegationsNeedingSignatures), - "btc_pk_hex": v.GetBtcPkHex(), - }).Debug("Retrieved delegations which need unbonding signatures") - - validatorPrivKey, err := v.kc.GetBtcPrivKey() - - if err != nil { - // Kill the app, if we can't recover our private key, then we have some bug - v.logger.WithFields(logrus.Fields{ - "err": err, - "babylon_pk_hex": v.GetBabylonPkHex(), - }).Fatalf("failed to get validator private key") - } - - signed, err := v.signUnbondingTransactions(validatorPrivKey, delegationsNeedingSignatures) - - if err != nil { - // We received some malformed data from Babylon either there is some bug in babylon code - // or we are on some malcious fork. Log it as error and continue. - v.logger.WithFields(logrus.Fields{ - "err": err, - "babylon_pk_hex": v.GetBabylonPkHex(), - }).Errorf("failed to sign unbonding transactions") - continue - } - - sendResult := v.sendSignaturesForUnbondingTransactions(signed) - - for _, res := range sendResult { - if res.err != nil { - // Just log send errors, as if we failed to submit signaute, we will retry in next tick - v.logger.WithFields(logrus.Fields{ - "err": res.err, - "babylon_pk_hex": v.GetBabylonPkHex(), - "staking_tx": res.stakingTxHash, - }).Errorf("failed to send signature for unbonding transaction") - } else { - v.logger.WithFields(logrus.Fields{ - "babylon_pk_hex": v.GetBabylonPkHex(), - "staking_tx": res.stakingTxHash, - }).Infof("successfully sent signature for unbonding transaction") - } - } - - case <-v.quit: - v.logger.Debug("the unbonding sig submission loop is closing") - return - } - } -} - -func (v *ValidatorInstance) finalitySigSubmissionLoop() { - defer v.wg.Done() - - for { - select { - case b := <-v.poller.GetBlockInfoChan(): - v.logger.WithFields(logrus.Fields{ - "btc_pk_hex": v.GetBtcPkHex(), - "block_height": b.Height, - }).Debug("the validator received a new block, start processing") - if b.Height <= v.GetLastProcessedHeight() { - v.logger.WithFields(logrus.Fields{ - "btc_pk_hex": v.GetBtcPkHex(), - "block_height": b.Height, - "last_processed_height": v.GetLastProcessedHeight(), - "last_voted_height": v.GetLastVotedHeight(), - }).Debug("the block has been processed before, skip processing") - continue - } - // use the copy of the block to avoid the impact to other receivers - nextBlock := *b - should, err := v.shouldSubmitFinalitySignature(&nextBlock) - - if err != nil { - v.reportCriticalErr(err) - continue - } - - if !should { - v.MustSetLastProcessedHeight(nextBlock.Height) - continue - } - - res, err := v.retrySubmitFinalitySignatureUntilBlockFinalized(&nextBlock) - if err != nil { - v.reportCriticalErr(err) - continue - } - if res != nil { - v.logger.WithFields(logrus.Fields{ - "btc_pk_hex": v.GetBtcPkHex(), - "block_height": b.Height, - "tx_hash": res.TxHash, - }).Info("successfully submitted a finality signature to the consumer chain") - } - case targetBlock := <-v.laggingTargetChan: - res, err := v.tryFastSync(targetBlock) - v.isLagging.Store(false) - if err != nil { - if errors.Is(err, types.ErrValidatorSlashed) { - v.reportCriticalErr(err) - continue - } - v.logger.WithFields(logrus.Fields{ - "err": err, - "btc_pk_hex": v.GetBtcPkHex(), - }).Error("failed to sync up, will try again later") - continue - } - // response might be nil if sync is not needed - if res != nil { - v.logger.WithFields(logrus.Fields{ - "btc_pk_hex": v.GetBtcPkHex(), - "tx_hashes": res.Responses, - "synced_height": res.SyncedHeight, - "last_processed_height": res.LastProcessedHeight, - }).Info("successfully synced to the latest block") - - // set the poller to fetch blocks that have not been processed - v.poller.SetNextHeightAndClearBuffer(v.GetLastProcessedHeight() + 1) - } - case <-v.quit: - v.logger.Info("the finality signature submission loop is closing") - return - } - } -} - -func (v *ValidatorInstance) randomnessCommitmentLoop() { - defer v.wg.Done() - - commitRandTicker := time.NewTicker(v.cfg.RandomnessCommitInterval) - defer commitRandTicker.Stop() - - for { - select { - case <-commitRandTicker.C: - tipBlock, err := v.getLatestBlockWithRetry() - if err != nil { - v.reportCriticalErr(err) - continue - } - txRes, err := v.retryCommitPubRandUntilBlockFinalized(tipBlock) - if err != nil { - v.reportCriticalErr(err) - continue - } - if txRes != nil { - v.logger.WithFields(logrus.Fields{ - "btc_pk_hex": v.GetBtcPkHex(), - "last_committed_height": v.GetLastCommittedHeight(), - "tx_hash": txRes.TxHash, - }).Info("successfully committed public randomness to the consumer chain") - } - - case <-v.quit: - v.logger.Info("the randomness commitment loop is closing") - return - } - } -} - -func (v *ValidatorInstance) checkLaggingLoop() { - defer v.wg.Done() - - if v.cfg.FastSyncInterval == 0 { - v.logger.Info("the fast sync is disabled") - return - } - - fastSyncTicker := time.NewTicker(v.cfg.FastSyncInterval) - defer fastSyncTicker.Stop() - - for { - select { - case <-fastSyncTicker.C: - if v.isLagging.Load() { - // we are in fast sync mode, skip do not do checks - continue - } - - latestBlock, err := v.getLatestBlockWithRetry() - if err != nil { - v.logger.WithFields(logrus.Fields{ - "err": err, - "btc_pk_hex": v.GetBtcPkHex(), - }).Error("failed to get the latest block of the consumer chain") - continue - } - - if v.checkLagging(latestBlock) { - v.isLagging.Store(true) - v.laggingTargetChan <- latestBlock - } - - case <-v.quit: - v.logger.Debug("the fast sync loop is closing") - return - } - } -} - -func (v *ValidatorInstance) tryFastSync(targetBlock *types.BlockInfo) (*FastSyncResult, error) { - if v.inSync.Load() { - return nil, fmt.Errorf("the validator %s is already in sync", v.GetBtcPkHex()) - } - - if v.GetLastCommittedHeight() <= v.GetLastVotedHeight() { - if err := v.SetLastProcessedHeight(targetBlock.Height); err != nil { - return nil, err - } - v.logger.WithFields(logrus.Fields{ - "btc_pk_hex": v.GetBtcPkHex(), - "block_height": targetBlock.Height, - }).Debug("insufficient public randomness, jumping to the latest block") - return nil, nil - } - - // get the last finalized height - lastFinalizedBlocks, err := v.cc.QueryLatestFinalizedBlocks(1) - if err != nil { - return nil, err - } - if lastFinalizedBlocks == nil { - v.logger.WithFields(logrus.Fields{ - "btc_pk_hex": v.GetBtcPkHex(), - "block_height": targetBlock.Height, - }).Debug("no finalized blocks yet, no need to catch up") - return nil, nil - } - - lastFinalizedHeight := lastFinalizedBlocks[0].Height - lastProcessedHeight := v.GetLastProcessedHeight() - - // get the startHeight from the maximum of the lastVotedHeight and - // the lastFinalizedHeight plus 1 - var startHeight uint64 - if lastFinalizedHeight < lastProcessedHeight { - startHeight = lastProcessedHeight + 1 - } else { - startHeight = lastFinalizedHeight + 1 - } - - if startHeight > targetBlock.Height { - return nil, fmt.Errorf("the start height %v should not be higher than the current block %v", startHeight, targetBlock.Height) - } - - return v.FastSync(startHeight, targetBlock.Height) -} - -// shouldSubmitFinalitySignature checks all the conditions that a finality should not be sent: -// 1. the validator does not have voting power on the given block -// 2. the last committed height is lower than the block height as this indicates the validator -// does not have the corresponding public randomness -// 3. the block height is lower than the last voted height as this indicates that the validator -// does not need to send finality signature over this block -func (v *ValidatorInstance) shouldSubmitFinalitySignature(b *types.BlockInfo) (bool, error) { - // check last voted height - if v.GetLastVotedHeight() >= b.Height { - v.logger.WithFields(logrus.Fields{ - "btc_pk_hex": v.GetBtcPkHex(), - "block_height": b.Height, - "last_voted_height": v.GetLastVotedHeight(), - }).Debug("the block has been voted before, skip voting") - return false, nil - } - - // check last committed height - if v.GetLastCommittedHeight() < b.Height { - v.logger.WithFields(logrus.Fields{ - "btc_pk_hex": v.GetBtcPkHex(), - "last_committed_height": v.GetLastCommittedHeight(), - "block_height": b.Height, - }).Debug("public rand is not committed, skip voting") - return false, nil - } - - // TODO: add retry here or within the query - power, err := v.cc.QueryValidatorVotingPower(v.GetBtcPkBIP340(), b.Height) - if err != nil { - return false, err - } - - v.updateStatusWithPower(power) - - if power == 0 { - v.logger.WithFields(logrus.Fields{ - "btc_pk_hex": v.GetBtcPkHex(), - "block_height": b.Height, - }).Debug("the validator does not have voting power, skip voting") - return false, nil - } - - return true, nil -} - -func (v *ValidatorInstance) reportCriticalErr(err error) { - v.criticalErrChan <- &CriticalError{ - err: err, - valBtcPk: v.GetBtcPkBIP340(), - bbnPk: v.GetBabylonPk(), - } -} - -// checkLagging returns true if the lasted voted height is behind by a configured gap -func (v *ValidatorInstance) checkLagging(currentBlock *types.BlockInfo) bool { - return currentBlock.Height >= v.GetLastProcessedHeight()+v.cfg.FastSyncGap -} - -// retrySubmitFinalitySignatureUntilBlockFinalized periodically tries to submit finality signature until success or the block is finalized -// error will be returned if maximum retries have been reached or the query to the consumer chain fails -func (v *ValidatorInstance) retrySubmitFinalitySignatureUntilBlockFinalized(targetBlock *types.BlockInfo) (*provider.RelayerTxResponse, error) { - var failedCycles uint64 - - // we break the for loop if the block is finalized or the signature is successfully submitted - // error will be returned if maximum retries have been reached or the query to the consumer chain fails - for { - // error will be returned if max retries have been reached - res, err := v.SubmitFinalitySignature(targetBlock) - if err != nil { - if clientcontroller.IsUnrecoverable(err) { - return nil, err - } - v.logger.WithFields(logrus.Fields{ - "currFailures": failedCycles, - "target_block_height": targetBlock.Height, - "error": err, - }).Error("err submitting finality signature to the consumer chain") - - failedCycles += 1 - if failedCycles > v.cfg.MaxSubmissionRetries { - return nil, fmt.Errorf("reached max failed cycles with err: %w", err) - } - } else { - // the signature has been successfully submitted - return res, nil - } - select { - case <-time.After(v.cfg.SubmissionRetryInterval): - // periodically query the index block to be later checked whether it is Finalized - finalized, err := v.cc.QueryBlockFinalization(targetBlock.Height) - if err != nil { - return nil, fmt.Errorf("failed to query block finalization at height %v: %w", targetBlock.Height, err) - } - if finalized { - v.logger.WithFields(logrus.Fields{ - "btc_val_pk": v.GetBtcPkHex(), - "block_height": targetBlock.Height, - }).Debug("the block is already finalized, skip submission") - return nil, nil - } - - case <-v.quit: - v.logger.Debugf("the validator instance %s is closing", v.GetBtcPkHex()) - return nil, nil - } - } -} - -// retryCommitPubRandUntilBlockFinalized periodically tries to commit public rand until success or the block is finalized -// error will be returned if maximum retries have been reached or the query to the consumer chain fails -func (v *ValidatorInstance) retryCommitPubRandUntilBlockFinalized(targetBlock *types.BlockInfo) (*provider.RelayerTxResponse, error) { - var failedCycles uint64 - - // we break the for loop if the block is finalized or the public rand is successfully committed - // error will be returned if maximum retries have been reached or the query to the consumer chain fails - for { - // error will be returned if max retries have been reached - res, err := v.CommitPubRand(targetBlock) - if err != nil { - if clientcontroller.IsUnrecoverable(err) { - return nil, err - } - v.logger.WithFields(logrus.Fields{ - "btc_val_pk": v.GetBtcPkHex(), - "currFailures": failedCycles, - "target_block_height": targetBlock.Height, - "error": err, - }).Error("err committing public randomness to the consumer chain") - - failedCycles += 1 - if failedCycles > v.cfg.MaxSubmissionRetries { - return nil, fmt.Errorf("reached max failed cycles with err: %w", err) - } - } else { - // the public randomness has been successfully submitted - return res, nil - } - select { - case <-time.After(v.cfg.SubmissionRetryInterval): - // periodically query the index block to be later checked whether it is Finalized - finalized, err := v.cc.QueryBlockFinalization(targetBlock.Height) - if err != nil { - return nil, fmt.Errorf("failed to query block finalization at height %v: %w", targetBlock.Height, err) - } - if finalized { - v.logger.WithFields(logrus.Fields{ - "btc_val_pk": v.GetBtcPkHex(), - "block_height": targetBlock.Height, - }).Debug("the block is already finalized, skip submission") - return nil, nil - } - - case <-v.quit: - v.logger.Debugf("the validator instance %s is closing", v.GetBtcPkHex()) - return nil, nil - } - } -} - -// CommitPubRand generates a list of Schnorr rand pairs, -// commits the public randomness for the managed validators, -// and save the randomness pair to DB -func (v *ValidatorInstance) CommitPubRand(tipBlock *types.BlockInfo) (*provider.RelayerTxResponse, error) { - lastCommittedHeight, err := v.cc.QueryHeightWithLastPubRand(v.btcPk) - if err != nil { - return nil, fmt.Errorf("failed to query the consumer chain for the last committed height: %w", err) - } - - if v.GetLastCommittedHeight() != lastCommittedHeight { - // for some reason number of random numbers locally does not match the chain node - // log it and try to recover somehow - return nil, fmt.Errorf("the local last committed height %v does not match the remote last committed height %v", - v.GetLastCommittedHeight(), lastCommittedHeight) - } - - var startHeight uint64 - if lastCommittedHeight == uint64(0) { - // the validator has never submitted public rand before - startHeight = tipBlock.Height + 1 - // should not use subtraction because they are in the type of uint64 - } else if lastCommittedHeight < v.cfg.MinRandHeightGap+tipBlock.Height { - // we are running out of the randomness - startHeight = lastCommittedHeight + 1 - } else { - v.logger.WithFields(logrus.Fields{ - "btc_pk_hex": v.btcPk.MarshalHex(), - "last_committed_height": v.GetLastCommittedHeight(), - "current_block_height": tipBlock.Height, - }).Debug("the validator has sufficient public randomness, skip committing more") - return nil, nil - } - - // generate a list of Schnorr randomness pairs - privRandList, pubRandList, err := GenerateRandPairList(v.cfg.NumPubRand) - if err != nil { - return nil, fmt.Errorf("failed to generate randomness: %w", err) - } - - // get the message hash for signing - msg := &ftypes.MsgCommitPubRandList{ - ValBtcPk: v.btcPk, - StartHeight: startHeight, - PubRandList: pubRandList, - } - hash, err := msg.HashToSign() - if err != nil { - return nil, fmt.Errorf("failed to sign the commit public randomness message: %w", err) - } - - // sign the message hash using the validator's BTC private key - schnorrSig, err := v.kc.SchnorrSign(hash) - if err != nil { - return nil, fmt.Errorf("failed to sign the Schnorr signature: %w", err) - } - sig := bbntypes.NewBIP340SignatureFromBTCSig(schnorrSig) - - res, err := v.cc.CommitPubRandList(v.btcPk, startHeight, pubRandList, &sig) - if err != nil { - // TODO Add retry. check issue: https://github.com/babylonchain/btc-validator/issues/34 - return nil, fmt.Errorf("failed to commit public randomness to the consumer chain: %w", err) - } - - // save the committed random list to DB - // TODO 1: Optimize the db interface to batch the saving operations - // TODO 2: Consider safety after recovery - for i, pr := range privRandList { - height := startHeight + uint64(i) - privRand := pr.Bytes() - randPair := &proto.SchnorrRandPair{ - SecRand: privRand[:], - PubRand: pubRandList[i].MustMarshal(), - } - err = v.state.s.SaveRandPair(v.GetBabylonPk().Key, height, randPair) - if err != nil { - v.logger.WithFields(logrus.Fields{ - "err": err, - "btc_pk_hex": v.GetBtcPkHex(), - }).Fatal("err while saving committed random pair to DB") - } - } - - newLastCommittedHeight := startHeight + uint64(len(pubRandList)-1) - - v.MustSetLastCommittedHeight(newLastCommittedHeight) - - return res, nil -} - -func (v *ValidatorInstance) updateStatusWithPower(power uint64) { - if power == 0 { - if v.GetStatus() == proto.ValidatorStatus_ACTIVE { - // the validator is slashed or unbonded from the consumer chain - v.MustSetStatus(proto.ValidatorStatus_INACTIVE) - } - return - } - - // update the status - if v.GetStatus() == proto.ValidatorStatus_REGISTERED || v.GetStatus() == proto.ValidatorStatus_INACTIVE { - v.MustSetStatus(proto.ValidatorStatus_ACTIVE) - } -} - -// SubmitFinalitySignature builds and sends a finality signature over the given block to the consumer chain -func (v *ValidatorInstance) SubmitFinalitySignature(b *types.BlockInfo) (*provider.RelayerTxResponse, error) { - eotsSig, err := v.signEotsSig(b) - if err != nil { - return nil, err - } - - // send finality signature to the consumer chain - res, err := v.cc.SubmitFinalitySig(v.GetBtcPkBIP340(), b.Height, b.LastCommitHash, eotsSig) - if err != nil { - return nil, fmt.Errorf("failed to send finality signature to the consumer chain: %w", err) - } - - // update DB - v.MustUpdateStateAfterFinalitySigSubmission(b.Height) - - return res, nil -} - -// SubmitBatchFinalitySignatures builds and sends a finality signature over the given block to the consumer chain -// NOTE: the input blocks should be in the ascending order of height -func (v *ValidatorInstance) SubmitBatchFinalitySignatures(blocks []*types.BlockInfo) (*provider.RelayerTxResponse, error) { - if len(blocks) == 0 { - return nil, fmt.Errorf("should not submit batch finality signature with zero block") - } - - sigs := make([]*bbntypes.SchnorrEOTSSig, 0, len(blocks)) - for _, b := range blocks { - eotsSig, err := v.signEotsSig(b) - if err != nil { - return nil, err - } - sigs = append(sigs, eotsSig) - } - - // send finality signature to the consumer chain - res, err := v.cc.SubmitBatchFinalitySigs(v.GetBtcPkBIP340(), blocks, sigs) - if err != nil { - return nil, fmt.Errorf("failed to send a batch of finality signatures to the consumer chain: %w", err) - } - - // update DB - highBlock := blocks[len(blocks)-1] - v.MustUpdateStateAfterFinalitySigSubmission(highBlock.Height) - - return res, nil -} - -func (v *ValidatorInstance) signEotsSig(b *types.BlockInfo) (*bbntypes.SchnorrEOTSSig, error) { - // build proper finality signature request - privRand, err := v.getCommittedPrivPubRand(b.Height) - if err != nil { - return nil, fmt.Errorf("failed to get the randomness pair from DB: %w", err) - } - btcPrivKey, err := v.kc.GetBtcPrivKey() - if err != nil { - return nil, fmt.Errorf("failed to get BTC private key from the keyring: %w", err) - } - msg := &ftypes.MsgAddFinalitySig{ - ValBtcPk: v.btcPk, - BlockHeight: b.Height, - BlockLastCommitHash: b.LastCommitHash, - } - msgToSign := msg.MsgToSign() - sig, err := eots.Sign(btcPrivKey, privRand, msgToSign) - if err != nil { - return nil, fmt.Errorf("failed to sign EOTS: %w", err) - } - - return bbntypes.NewSchnorrEOTSSigFromModNScalar(sig), nil -} - -// TestSubmitFinalitySignatureAndExtractPrivKey is exposed for presentation/testing purpose to allow manual sending finality signature -// this API is the same as SubmitFinalitySignature except that we don't constraint the voting height and update status -// Note: this should not be used in the submission loop -func (v *ValidatorInstance) TestSubmitFinalitySignatureAndExtractPrivKey(b *types.BlockInfo) (*provider.RelayerTxResponse, *btcec.PrivateKey, error) { - // check last committed height - if v.GetLastCommittedHeight() < b.Height { - return nil, nil, fmt.Errorf("the validator's last committed height %v is lower than the current block height %v", - v.GetLastCommittedHeight(), b.Height) - } - - eotsSig, err := v.signEotsSig(b) - if err != nil { - return nil, nil, err - } - - // send finality signature to the consumer chain - res, err := v.cc.SubmitFinalitySig(v.GetBtcPkBIP340(), b.Height, b.LastCommitHash, eotsSig) - if err != nil { - return nil, nil, fmt.Errorf("failed to send finality signature to the consumer chain: %w", err) - } - - // try to extract the private key - var privKey *btcec.PrivateKey - for _, ev := range res.Events { - if strings.Contains(ev.EventType, "EventSlashedBTCValidator") { - evidenceStr := ev.Attributes["evidence"] - v.logger.Debugf("found slashing evidence %s", evidenceStr) - var evidence ftypes.Evidence - if err := jsonpb.UnmarshalString(evidenceStr, &evidence); err != nil { - return nil, nil, fmt.Errorf("failed to decode evidence bytes to evidence: %s", err.Error()) - } - privKey, err = evidence.ExtractBTCSK() - if err != nil { - return nil, nil, fmt.Errorf("failed to extract private key: %s", err.Error()) - } - break - } - } - - return res, privKey, nil -} - -func (v *ValidatorInstance) getPollerStartingHeight() (uint64, error) { - if !v.cfg.ValidatorModeConfig.AutoChainScanningMode { - return v.cfg.ValidatorModeConfig.StaticChainScanningStartHeight, nil - } - - // Set initial block to the maximum of - // - last processed height - // - the latest Babylon finalised height - // The above is to ensure that: - // - // (1) Any validator that is eligible to vote for a block, - // doesn't miss submitting a vote for it. - // (2) The validators do not submit signatures for any already - // finalised blocks. - initialBlockToGet := v.GetLastProcessedHeight() - latestFinalisedBlock, err := v.latestFinalizedBlocksWithRetry(1) - if err != nil { - return 0, err - } - if len(latestFinalisedBlock) != 0 { - if latestFinalisedBlock[0].Height > initialBlockToGet { - initialBlockToGet = latestFinalisedBlock[0].Height - } - } - - // ensure that initialBlockToGet is at least 1 - if initialBlockToGet == 0 { - initialBlockToGet = 1 - } - return initialBlockToGet, nil -} - -func (v *ValidatorInstance) latestFinalizedBlocksWithRetry(count uint64) ([]*types.BlockInfo, error) { - var response []*types.BlockInfo - if err := retry.Do(func() error { - latestFinalisedBlock, err := v.cc.QueryLatestFinalizedBlocks(count) - if err != nil { - return err - } - response = latestFinalisedBlock - return nil - }, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { - v.logger.WithFields(logrus.Fields{ - "attempt": n + 1, - "max_attempts": RtyAttNum, - "error": err, - }).Debug("Failed to query babylon for the latest finalised blocks") - })); err != nil { - return nil, err - } - return response, nil -} - -func (v *ValidatorInstance) getCommittedPrivPubRand(height uint64) (*eots.PrivateRand, error) { - randPair, err := v.state.s.GetRandPair(v.bbnPk.Key, height) - if err != nil { - return nil, err - } - - if len(randPair.SecRand) != 32 { - return nil, fmt.Errorf("the private randomness should be 32 bytes") - } - - privRand := new(eots.PrivateRand) - privRand.SetByteSlice(randPair.SecRand) - - return privRand, nil -} - -func (v *ValidatorInstance) getLatestBlockWithRetry() (*types.BlockInfo, error) { - var latestBlock *types.BlockInfo - - if err := retry.Do(func() error { - headerResult, err := v.cc.QueryBestHeader() - if err != nil { - return err - } - latestBlock = &types.BlockInfo{ - Height: uint64(headerResult.Header.Height), - LastCommitHash: headerResult.Header.LastCommitHash, - } - return nil - }, RtyAtt, RtyDel, RtyErr, retry.OnRetry(func(n uint, err error) { - v.logger.WithFields(logrus.Fields{ - "attempt": n + 1, - "max_attempts": RtyAttNum, - "error": err, - }).Debug("failed to query the consumer chain for the latest block") - })); err != nil { - return nil, err - } - - return latestBlock, nil -} diff --git a/service/validator_instance_test.go b/service/validator_instance_test.go deleted file mode 100644 index f4c28b5a..00000000 --- a/service/validator_instance_test.go +++ /dev/null @@ -1,140 +0,0 @@ -package service_test - -import ( - "math/rand" - "os" - "testing" - - "github.com/cosmos/relayer/v2/relayer/provider" - "github.com/golang/mock/gomock" - "github.com/sirupsen/logrus" - "github.com/stretchr/testify/require" - - "github.com/babylonchain/btc-validator/clientcontroller" - "github.com/babylonchain/btc-validator/proto" - "github.com/babylonchain/btc-validator/service" - "github.com/babylonchain/btc-validator/testutil" - "github.com/babylonchain/btc-validator/types" - "github.com/babylonchain/btc-validator/valcfg" -) - -func FuzzCommitPubRandList(f *testing.F) { - testutil.AddRandomSeedsToFuzzer(f, 10) - f.Fuzz(func(t *testing.T, seed int64) { - r := rand.New(rand.NewSource(seed)) - - randomStartingHeight := uint64(r.Int63n(100) + 1) - currentHeight := randomStartingHeight + uint64(r.Int63n(10)+2) - startingBlock := &types.BlockInfo{Height: randomStartingHeight, LastCommitHash: testutil.GenRandomByteArray(r, 32)} - mockClientController := testutil.PrepareMockedClientController(t, r, randomStartingHeight, currentHeight) - mockClientController.EXPECT().QueryLatestFinalizedBlocks(gomock.Any()).Return(nil, nil).AnyTimes() - app, storeValidator, cleanUp := newValidatorAppWithRegisteredValidator(t, r, mockClientController, randomStartingHeight) - defer cleanUp() - mockClientController.EXPECT().QueryValidatorVotingPower(storeValidator.MustGetBIP340BTCPK(), gomock.Any()). - Return(uint64(0), nil).AnyTimes() - err := app.Start() - require.NoError(t, err) - - valIns, err := app.GetValidatorInstance(storeValidator.GetBabylonPK()) - require.NoError(t, err) - expectedTxHash := testutil.GenRandomHexStr(r, 32) - mockClientController.EXPECT(). - CommitPubRandList(valIns.GetBtcPkBIP340(), startingBlock.Height+1, gomock.Any(), gomock.Any()). - Return(&provider.RelayerTxResponse{TxHash: expectedTxHash}, nil).AnyTimes() - mockClientController.EXPECT().QueryHeightWithLastPubRand(valIns.GetBtcPkBIP340()). - Return(uint64(0), nil).AnyTimes() - res, err := valIns.CommitPubRand(startingBlock) - require.NoError(t, err) - require.Equal(t, expectedTxHash, res.TxHash) - - // check the last_committed_height - numPubRand := app.GetConfig().NumPubRand - require.Equal(t, startingBlock.Height+numPubRand, valIns.GetStoreValidator().LastCommittedHeight) - - // check the committed pub rand - randPairs, err := valIns.GetCommittedPubRandPairList() - require.NoError(t, err) - require.Equal(t, int(numPubRand), len(randPairs)) - }) -} - -func FuzzSubmitFinalitySig(f *testing.F) { - testutil.AddRandomSeedsToFuzzer(f, 10) - f.Fuzz(func(t *testing.T, seed int64) { - r := rand.New(rand.NewSource(seed)) - - randomStartingHeight := uint64(r.Int63n(100) + 1) - currentHeight := randomStartingHeight + uint64(r.Int63n(10)+1) - startingBlock := &types.BlockInfo{Height: randomStartingHeight, LastCommitHash: testutil.GenRandomByteArray(r, 32)} - mockClientController := testutil.PrepareMockedClientController(t, r, randomStartingHeight, currentHeight) - mockClientController.EXPECT().QueryLatestFinalizedBlocks(gomock.Any()).Return(nil, nil).AnyTimes() - app, storeValidator, cleanUp := newValidatorAppWithRegisteredValidator(t, r, mockClientController, randomStartingHeight) - defer cleanUp() - mockClientController.EXPECT().QueryValidatorVotingPower(storeValidator.MustGetBIP340BTCPK(), gomock.Any()). - Return(uint64(0), nil).AnyTimes() - err := app.Start() - require.NoError(t, err) - valIns, err := app.GetValidatorInstance(storeValidator.GetBabylonPK()) - require.NoError(t, err) - - // commit public randomness - expectedTxHash := testutil.GenRandomHexStr(r, 32) - mockClientController.EXPECT(). - CommitPubRandList(valIns.GetBtcPkBIP340(), startingBlock.Height+1, gomock.Any(), gomock.Any()). - Return(&provider.RelayerTxResponse{TxHash: expectedTxHash}, nil).AnyTimes() - mockClientController.EXPECT().QueryHeightWithLastPubRand(valIns.GetBtcPkBIP340()). - Return(uint64(0), nil).AnyTimes() - res, err := valIns.CommitPubRand(startingBlock) - require.NoError(t, err) - require.Equal(t, expectedTxHash, res.TxHash) - mockClientController.EXPECT().QueryValidatorVotingPower(storeValidator.MustGetBIP340BTCPK(), gomock.Any()). - Return(uint64(1), nil).AnyTimes() - - // submit finality sig - nextBlock := &types.BlockInfo{ - Height: startingBlock.Height + 1, - LastCommitHash: testutil.GenRandomByteArray(r, 32), - } - expectedTxHash = testutil.GenRandomHexStr(r, 32) - mockClientController.EXPECT(). - SubmitFinalitySig(valIns.GetBtcPkBIP340(), nextBlock.Height, nextBlock.LastCommitHash, gomock.Any()). - Return(&provider.RelayerTxResponse{TxHash: expectedTxHash}, nil).AnyTimes() - res, err = valIns.SubmitFinalitySignature(nextBlock) - require.NoError(t, err) - require.Equal(t, expectedTxHash, res.TxHash) - - // check the last_voted_height - require.Equal(t, nextBlock.Height, valIns.GetLastVotedHeight()) - require.Equal(t, nextBlock.Height, valIns.GetLastProcessedHeight()) - }) -} - -func newValidatorAppWithRegisteredValidator(t *testing.T, r *rand.Rand, cc clientcontroller.ClientController, startingHeight uint64) (*service.ValidatorApp, *proto.StoreValidator, func()) { - // create validator app with config - cfg := valcfg.DefaultConfig() - cfg.DatabaseConfig = testutil.GenDBConfig(r, t) - cfg.BabylonConfig.KeyDirectory = t.TempDir() - cfg.NumPubRand = uint64(25) - cfg.ValidatorModeConfig.AutoChainScanningMode = false - cfg.ValidatorModeConfig.StaticChainScanningStartHeight = startingHeight - logger := logrus.New() - app, err := service.NewValidatorAppFromConfig(&cfg, logger, cc) - require.NoError(t, err) - - // create registered validator - validator := testutil.GenStoredValidator(r, t, app) - err = app.GetValidatorStore().SetValidatorStatus(validator, proto.ValidatorStatus_REGISTERED) - require.NoError(t, err) - config := app.GetConfig() - - cleanUp := func() { - err = app.Stop() - require.NoError(t, err) - err := os.RemoveAll(config.DatabaseConfig.Path) - require.NoError(t, err) - err = os.RemoveAll(config.BabylonConfig.KeyDirectory) - require.NoError(t, err) - } - - return app, validator, cleanUp -} diff --git a/service/validator_manager.go b/service/validator_manager.go deleted file mode 100644 index 91ff32f1..00000000 --- a/service/validator_manager.go +++ /dev/null @@ -1,215 +0,0 @@ -package service - -import ( - "encoding/hex" - "errors" - "fmt" - "sync" - - bbntypes "github.com/babylonchain/babylon/types" - "github.com/cosmos/cosmos-sdk/crypto/keyring" - "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - "github.com/sirupsen/logrus" - "go.uber.org/atomic" - - "github.com/babylonchain/btc-validator/clientcontroller" - "github.com/babylonchain/btc-validator/proto" - "github.com/babylonchain/btc-validator/types" - "github.com/babylonchain/btc-validator/val" - "github.com/babylonchain/btc-validator/valcfg" -) - -const instanceTerminatingMsg = "terminating the validator instance due to critical error" - -type CriticalError struct { - err error - // TODO use validator BTC key as the unique id of - // the validator; currently, the storage is keyed - // the babylon public key - valBtcPk *bbntypes.BIP340PubKey - bbnPk *secp256k1.PubKey -} - -type ValidatorManager struct { - isStarted *atomic.Bool - - mu sync.Mutex - wg sync.WaitGroup - - // running validator instances map keyed by the hex string of the BTC public key - vals map[string]*ValidatorInstance - - // needed for initiating validator instances - vs *val.ValidatorStore - config *valcfg.Config - kr keyring.Keyring - cc clientcontroller.ClientController - logger *logrus.Logger - - criticalErrChan chan *CriticalError - - quit chan struct{} -} - -func NewValidatorManager(vs *val.ValidatorStore, - config *valcfg.Config, - kr keyring.Keyring, - cc clientcontroller.ClientController, - logger *logrus.Logger, -) (*ValidatorManager, error) { - return &ValidatorManager{ - vals: make(map[string]*ValidatorInstance), - criticalErrChan: make(chan *CriticalError), - isStarted: atomic.NewBool(false), - vs: vs, - config: config, - kr: kr, - cc: cc, - logger: logger, - quit: make(chan struct{}), - }, nil -} - -// monitorCriticalErr takes actions when it receives critical errors from a validator instance -// if the validator is slashed, it will be terminated and the program keeps running in case -// new validators join -// otherwise, the program will panic -func (vm *ValidatorManager) monitorCriticalErr() { - defer vm.wg.Done() - - var criticalErr *CriticalError - for { - select { - case criticalErr = <-vm.criticalErrChan: - vi, err := vm.getValidatorInstance(criticalErr.bbnPk) - if err != nil { - panic(fmt.Errorf("failed to get the validator instance: %w", err)) - } - if errors.Is(criticalErr.err, types.ErrValidatorSlashed) { - vi.MustSetStatus(proto.ValidatorStatus_SLASHED) - if err := vm.removeValidatorInstance(vi.GetBabylonPk()); err != nil { - panic(fmt.Errorf("failed to terminate a slashed validator %s: %w", vi.GetBtcPkHex(), err)) - } - continue - } - vi.logger.WithFields(logrus.Fields{ - "err": criticalErr.err, - "btc_pk_hex": vi.GetBtcPkHex(), - }).Fatal(instanceTerminatingMsg) - case <-vm.quit: - return - } - } -} - -func (vm *ValidatorManager) Start() error { - if vm.isStarted.Swap(true) { - return fmt.Errorf("the validator manager is already started") - } - - storedValidators, err := vm.vs.ListRegisteredValidators() - if err != nil { - return err - } - - vm.wg.Add(1) - go vm.monitorCriticalErr() - - for _, v := range storedValidators { - if err := vm.addValidatorInstance(v.GetBabylonPK()); err != nil { - return err - } - } - - return nil -} - -func (vm *ValidatorManager) Stop() error { - if !vm.isStarted.Swap(false) { - return fmt.Errorf("the validator manager has already stopped") - } - - var stopErr error - - for _, v := range vm.vals { - if err := v.Stop(); err != nil { - stopErr = err - break - } - } - - close(vm.quit) - vm.wg.Wait() - - return stopErr -} - -func (vm *ValidatorManager) listValidatorInstances() []*ValidatorInstance { - vm.mu.Lock() - defer vm.mu.Unlock() - - valsList := make([]*ValidatorInstance, 0, len(vm.vals)) - for _, v := range vm.vals { - valsList = append(valsList, v) - } - - return valsList -} - -func (vm *ValidatorManager) getValidatorInstance(babylonPk *secp256k1.PubKey) (*ValidatorInstance, error) { - vm.mu.Lock() - defer vm.mu.Unlock() - - keyHex := hex.EncodeToString(babylonPk.Key) - v, exists := vm.vals[keyHex] - if !exists { - return nil, fmt.Errorf("cannot find the validator instance with PK: %s", keyHex) - } - - return v, nil -} - -func (vm *ValidatorManager) removeValidatorInstance(babylonPk *secp256k1.PubKey) error { - vm.mu.Lock() - defer vm.mu.Unlock() - - keyHex := hex.EncodeToString(babylonPk.Key) - v, exists := vm.vals[keyHex] - if !exists { - return fmt.Errorf("cannot find the validator instance with PK: %s", keyHex) - } - if v.IsRunning() { - if err := v.Stop(); err != nil { - return fmt.Errorf("failed to stop the validator instance %s", keyHex) - } - } - - delete(vm.vals, keyHex) - return nil -} - -// addValidatorInstance creates a validator instance, starts it and adds it into the validator manager -func (vm *ValidatorManager) addValidatorInstance( - pk *secp256k1.PubKey, -) error { - vm.mu.Lock() - defer vm.mu.Unlock() - - pkHex := hex.EncodeToString(pk.Key) - if _, exists := vm.vals[pkHex]; exists { - return fmt.Errorf("validator instance already exists") - } - - valIns, err := NewValidatorInstance(pk, vm.config, vm.vs, vm.kr, vm.cc, vm.criticalErrChan, vm.logger) - if err != nil { - return fmt.Errorf("failed to create validator %s instance: %w", pkHex, err) - } - - if err := valIns.Start(); err != nil { - return fmt.Errorf("failed to start validator %s instance: %w", pkHex, err) - } - - vm.vals[pkHex] = valIns - - return nil -} diff --git a/store/bbolt.go b/store/bbolt.go index d874dbc2..34acd6ef 100644 --- a/store/bbolt.go +++ b/store/bbolt.go @@ -3,10 +3,9 @@ package store import ( "bytes" "errors" + "fmt" bolt "go.etcd.io/bbolt" - - "github.com/babylonchain/btc-validator/valcfg" ) // BboltStore implements the Store interface @@ -165,10 +164,10 @@ func NewBboltStore(path string, bucketName string) (BboltStore, error) { // Set default values if path == "" { - path = valcfg.DefaultDBPath + return BboltStore{}, fmt.Errorf("db path is empty") } if bucketName == "" { - bucketName = valcfg.DefaultDBName + return BboltStore{}, fmt.Errorf("db bucket name is empty") } // Open DB diff --git a/store/bbolt_test.go b/store/bbolt_test.go index 6ce9f922..7a407cee 100644 --- a/store/bbolt_test.go +++ b/store/bbolt_test.go @@ -6,8 +6,8 @@ import ( "github.com/stretchr/testify/require" - kvstore "github.com/babylonchain/btc-validator/store" - "github.com/babylonchain/btc-validator/testutil" + kvstore "github.com/babylonchain/finality-provider/store" + "github.com/babylonchain/finality-provider/testutil" ) // FuzzBboltStore tests store interfaces works properly. diff --git a/testutil/datagen.go b/testutil/datagen.go index 73808347..64c0ec1b 100644 --- a/testutil/datagen.go +++ b/testutil/datagen.go @@ -3,22 +3,28 @@ package testutil import ( "encoding/hex" "math/rand" - "path/filepath" "testing" "time" + "github.com/babylonchain/babylon/crypto/eots" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + + eotscfg "github.com/babylonchain/finality-provider/eotsmanager/config" + fpcfg "github.com/babylonchain/finality-provider/finality-provider/config" + + sdkmath "cosmossdk.io/math" "github.com/babylonchain/babylon/testutil/datagen" bbn "github.com/babylonchain/babylon/types" bstypes "github.com/babylonchain/babylon/x/btcstaking/types" + "github.com/btcsuite/btcd/chaincfg" "github.com/cosmos/cosmos-sdk/client" "github.com/stretchr/testify/require" - "github.com/babylonchain/btc-validator/codec" - "github.com/babylonchain/btc-validator/proto" - "github.com/babylonchain/btc-validator/service" - "github.com/babylonchain/btc-validator/types" - "github.com/babylonchain/btc-validator/val" - "github.com/babylonchain/btc-validator/valcfg" + "github.com/babylonchain/finality-provider/codec" + "github.com/babylonchain/finality-provider/config" + "github.com/babylonchain/finality-provider/finality-provider/proto" + "github.com/babylonchain/finality-provider/finality-provider/service" + "github.com/babylonchain/finality-provider/types" ) func GenRandomByteArray(r *rand.Rand, length uint64) []byte { @@ -41,7 +47,13 @@ func AddRandomSeedsToFuzzer(f *testing.F, num uint) { } } -func GenRandomValidator(r *rand.Rand, t *testing.T) *proto.StoreValidator { +func GenPublicRand(r *rand.Rand, t *testing.T) *bbn.SchnorrPubRand { + _, eotsPR, err := eots.RandGen(r) + require.NoError(t, err) + return bbn.NewSchnorrPubRandFromFieldVal(eotsPR) +} + +func GenRandomFinalityProvider(r *rand.Rand, t *testing.T) *proto.StoreFinalityProvider { // generate BTC key pair btcSK, btcPK, err := datagen.GenRandomBTCKeyPair(r) require.NoError(t, err) @@ -54,10 +66,10 @@ func GenRandomValidator(r *rand.Rand, t *testing.T) *proto.StoreValidator { // generate and verify PoP, correct case pop, err := bstypes.NewPoP(babylonSK, btcSK) require.NoError(t, err) - err = pop.Verify(babylonPK, bip340PK) + err = pop.Verify(babylonPK, bip340PK, &chaincfg.SimNetParams) require.NoError(t, err) - return &proto.StoreValidator{ + return &proto.StoreFinalityProvider{ KeyName: GenRandomHexStr(r, 4), BabylonPk: babylonPK.Bytes(), BtcPk: bip340PK.MustMarshal(), @@ -68,12 +80,16 @@ func GenRandomValidator(r *rand.Rand, t *testing.T) *proto.StoreValidator { } } +func GenValidSlashingRate(r *rand.Rand) sdkmath.LegacyDec { + return sdkmath.LegacyNewDecWithPrec(int64(datagen.RandomInt(r, 41)+10), 2) +} + func GenBlocks(r *rand.Rand, startHeight, endHeight uint64) []*types.BlockInfo { blocks := make([]*types.BlockInfo, 0) for i := startHeight; i <= endHeight; i++ { b := &types.BlockInfo{ - Height: i, - LastCommitHash: datagen.GenRandomLastCommitHash(r), + Height: i, + Hash: datagen.GenRandomByteArray(r, 32), } blocks = append(blocks, b) } @@ -81,42 +97,50 @@ func GenBlocks(r *rand.Rand, startHeight, endHeight uint64) []*types.BlockInfo { return blocks } -// GenStoredValidator generates a random validator from the keyring and store it in DB -func GenStoredValidator(r *rand.Rand, t *testing.T, app *service.ValidatorApp) *proto.StoreValidator { +// GenStoredFinalityProvider generates a random finality-provider from the keyring and store it in DB +func GenStoredFinalityProvider(r *rand.Rand, t *testing.T, app *service.FinalityProviderApp, passphrase, hdPath string) *proto.StoreFinalityProvider { // generate keyring keyName := GenRandomHexStr(r, 4) - kc, err := val.NewKeyringControllerWithKeyring(app.GetKeyring(), keyName) - require.NoError(t, err) + chainID := GenRandomHexStr(r, 4) - // create validator using the keyring - btcPk, bbnPk, err := kc.CreateValidatorKeys() + cfg := app.GetConfig() + _, err := service.CreateChainKey(cfg.BabylonConfig.KeyDirectory, cfg.BabylonConfig.ChainID, keyName, keyring.BackendTest, passphrase, hdPath) require.NoError(t, err) - pop, err := kc.CreatePop() + res, err := app.CreateFinalityProvider(keyName, chainID, passphrase, hdPath, EmptyDescription(), ZeroCommissionRate()) require.NoError(t, err) - validator := val.NewStoreValidator(bbnPk, btcPk, kc.GetKeyName(), pop, EmptyDescription(), ZeroCommissionRate()) - - // save the validator - s := app.GetValidatorStore() - err = s.SaveValidator(validator) + fpPk := res.StoreFp.BtcPk + storedFp, err := app.GetFinalityProviderStore().GetStoreFinalityProvider(fpPk) require.NoError(t, err) - return validator + return storedFp } -func GenDBConfig(r *rand.Rand, t *testing.T) *valcfg.DatabaseConfig { +func GenDBConfig(r *rand.Rand, t *testing.T) *config.DatabaseConfig { bucketName := GenRandomHexStr(r, 10) + "-bbolt.db" - path := filepath.Join(t.TempDir(), bucketName) - dbcfg, err := valcfg.NewDatabaseConfig( + dbcfg, err := config.NewDatabaseConfig( "bbolt", - path, bucketName, ) require.NoError(t, err) return dbcfg } +func GenEOTSConfig(r *rand.Rand, t *testing.T) *eotscfg.Config { + eotsCfg := eotscfg.DefaultConfig() + eotsCfg.DatabaseConfig = GenDBConfig(r, t) + + return &eotsCfg +} + +func GenFpConfig(r *rand.Rand, t *testing.T, homeDir string) *fpcfg.Config { + fpCfg := fpcfg.DefaultConfigWithHome(homeDir) + fpCfg.DatabaseConfig = GenDBConfig(r, t) + + return &fpCfg +} + func GenSdkContext(r *rand.Rand, t *testing.T) client.Context { chainID := "testchain-" + GenRandomHexStr(r, 4) dir := t.TempDir() diff --git a/testutil/mocks/babylon.go b/testutil/mocks/babylon.go index 41b71dba..ed45056e 100644 --- a/testutil/mocks/babylon.go +++ b/testutil/mocks/babylon.go @@ -7,15 +7,10 @@ package mocks import ( reflect "reflect" - types "github.com/babylonchain/babylon/types" - types0 "github.com/babylonchain/babylon/x/btcstaking/types" - clientcontroller "github.com/babylonchain/btc-validator/clientcontroller" - types1 "github.com/babylonchain/btc-validator/types" - coretypes "github.com/cometbft/cometbft/rpc/core/types" - secp256k1 "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - types2 "github.com/cosmos/cosmos-sdk/types" - types3 "github.com/cosmos/cosmos-sdk/x/staking/types" - provider "github.com/cosmos/relayer/v2/relayer/provider" + math "cosmossdk.io/math" + types "github.com/babylonchain/finality-provider/types" + btcec "github.com/btcsuite/btcd/btcec/v2" + schnorr "github.com/btcsuite/btcd/btcec/v2/schnorr" gomock "github.com/golang/mock/gomock" ) @@ -57,85 +52,70 @@ func (mr *MockClientControllerMockRecorder) Close() *gomock.Call { } // CommitPubRandList mocks base method. -func (m *MockClientController) CommitPubRandList(btcPubKey *types.BIP340PubKey, startHeight uint64, pubRandList []types.SchnorrPubRand, sig *types.BIP340Signature) (*provider.RelayerTxResponse, error) { +func (m *MockClientController) CommitPubRandList(fpPk *btcec.PublicKey, startHeight uint64, pubRandList []*btcec.FieldVal, sig *schnorr.Signature) (*types.TxResponse, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CommitPubRandList", btcPubKey, startHeight, pubRandList, sig) - ret0, _ := ret[0].(*provider.RelayerTxResponse) + ret := m.ctrl.Call(m, "CommitPubRandList", fpPk, startHeight, pubRandList, sig) + ret0, _ := ret[0].(*types.TxResponse) ret1, _ := ret[1].(error) return ret0, ret1 } // CommitPubRandList indicates an expected call of CommitPubRandList. -func (mr *MockClientControllerMockRecorder) CommitPubRandList(btcPubKey, startHeight, pubRandList, sig interface{}) *gomock.Call { +func (mr *MockClientControllerMockRecorder) CommitPubRandList(fpPk, startHeight, pubRandList, sig interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CommitPubRandList", reflect.TypeOf((*MockClientController)(nil).CommitPubRandList), btcPubKey, startHeight, pubRandList, sig) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CommitPubRandList", reflect.TypeOf((*MockClientController)(nil).CommitPubRandList), fpPk, startHeight, pubRandList, sig) } -// GetStakingParams mocks base method. -func (m *MockClientController) GetStakingParams() (*clientcontroller.StakingParams, error) { +// QueryActivatedHeight mocks base method. +func (m *MockClientController) QueryActivatedHeight() (uint64, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetStakingParams") - ret0, _ := ret[0].(*clientcontroller.StakingParams) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetStakingParams indicates an expected call of GetStakingParams. -func (mr *MockClientControllerMockRecorder) GetStakingParams() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStakingParams", reflect.TypeOf((*MockClientController)(nil).GetStakingParams)) -} - -// QueryBTCValidatorUnbondingDelegations mocks base method. -func (m *MockClientController) QueryBTCValidatorUnbondingDelegations(valBtcPk *types.BIP340PubKey, max uint64) ([]*types0.BTCDelegation, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryBTCValidatorUnbondingDelegations", valBtcPk, max) - ret0, _ := ret[0].([]*types0.BTCDelegation) + ret := m.ctrl.Call(m, "QueryActivatedHeight") + ret0, _ := ret[0].(uint64) ret1, _ := ret[1].(error) return ret0, ret1 } -// QueryBTCValidatorUnbondingDelegations indicates an expected call of QueryBTCValidatorUnbondingDelegations. -func (mr *MockClientControllerMockRecorder) QueryBTCValidatorUnbondingDelegations(valBtcPk, max interface{}) *gomock.Call { +// QueryActivatedHeight indicates an expected call of QueryActivatedHeight. +func (mr *MockClientControllerMockRecorder) QueryActivatedHeight() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryBTCValidatorUnbondingDelegations", reflect.TypeOf((*MockClientController)(nil).QueryBTCValidatorUnbondingDelegations), valBtcPk, max) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryActivatedHeight", reflect.TypeOf((*MockClientController)(nil).QueryActivatedHeight)) } -// QueryBestHeader mocks base method. -func (m *MockClientController) QueryBestHeader() (*coretypes.ResultHeader, error) { +// QueryBestBlock mocks base method. +func (m *MockClientController) QueryBestBlock() (*types.BlockInfo, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryBestHeader") - ret0, _ := ret[0].(*coretypes.ResultHeader) + ret := m.ctrl.Call(m, "QueryBestBlock") + ret0, _ := ret[0].(*types.BlockInfo) ret1, _ := ret[1].(error) return ret0, ret1 } -// QueryBestHeader indicates an expected call of QueryBestHeader. -func (mr *MockClientControllerMockRecorder) QueryBestHeader() *gomock.Call { +// QueryBestBlock indicates an expected call of QueryBestBlock. +func (mr *MockClientControllerMockRecorder) QueryBestBlock() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryBestHeader", reflect.TypeOf((*MockClientController)(nil).QueryBestHeader)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryBestBlock", reflect.TypeOf((*MockClientController)(nil).QueryBestBlock)) } -// QueryBlockFinalization mocks base method. -func (m *MockClientController) QueryBlockFinalization(height uint64) (bool, error) { +// QueryBlock mocks base method. +func (m *MockClientController) QueryBlock(height uint64) (*types.BlockInfo, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryBlockFinalization", height) - ret0, _ := ret[0].(bool) + ret := m.ctrl.Call(m, "QueryBlock", height) + ret0, _ := ret[0].(*types.BlockInfo) ret1, _ := ret[1].(error) return ret0, ret1 } -// QueryBlockFinalization indicates an expected call of QueryBlockFinalization. -func (mr *MockClientControllerMockRecorder) QueryBlockFinalization(height interface{}) *gomock.Call { +// QueryBlock indicates an expected call of QueryBlock. +func (mr *MockClientControllerMockRecorder) QueryBlock(height interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryBlockFinalization", reflect.TypeOf((*MockClientController)(nil).QueryBlockFinalization), height) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryBlock", reflect.TypeOf((*MockClientController)(nil).QueryBlock), height) } // QueryBlocks mocks base method. -func (m *MockClientController) QueryBlocks(startHeight, endHeight, limit uint64) ([]*types1.BlockInfo, error) { +func (m *MockClientController) QueryBlocks(startHeight, endHeight, limit uint64) ([]*types.BlockInfo, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "QueryBlocks", startHeight, endHeight, limit) - ret0, _ := ret[0].([]*types1.BlockInfo) + ret0, _ := ret[0].([]*types.BlockInfo) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -146,197 +126,107 @@ func (mr *MockClientControllerMockRecorder) QueryBlocks(startHeight, endHeight, return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryBlocks", reflect.TypeOf((*MockClientController)(nil).QueryBlocks), startHeight, endHeight, limit) } -// QueryHeader mocks base method. -func (m *MockClientController) QueryHeader(height int64) (*coretypes.ResultHeader, error) { +// QueryFinalityProviderSlashed mocks base method. +func (m *MockClientController) QueryFinalityProviderSlashed(fpPk *btcec.PublicKey) (bool, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryHeader", height) - ret0, _ := ret[0].(*coretypes.ResultHeader) + ret := m.ctrl.Call(m, "QueryFinalityProviderSlashed", fpPk) + ret0, _ := ret[0].(bool) ret1, _ := ret[1].(error) return ret0, ret1 } -// QueryHeader indicates an expected call of QueryHeader. -func (mr *MockClientControllerMockRecorder) QueryHeader(height interface{}) *gomock.Call { +// QueryFinalityProviderSlashed indicates an expected call of QueryFinalityProviderSlashed. +func (mr *MockClientControllerMockRecorder) QueryFinalityProviderSlashed(fpPk interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryHeader", reflect.TypeOf((*MockClientController)(nil).QueryHeader), height) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryFinalityProviderSlashed", reflect.TypeOf((*MockClientController)(nil).QueryFinalityProviderSlashed), fpPk) } -// QueryHeightWithLastPubRand mocks base method. -func (m *MockClientController) QueryHeightWithLastPubRand(btcPubKey *types.BIP340PubKey) (uint64, error) { +// QueryFinalityProviderVotingPower mocks base method. +func (m *MockClientController) QueryFinalityProviderVotingPower(fpPk *btcec.PublicKey, blockHeight uint64) (uint64, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryHeightWithLastPubRand", btcPubKey) + ret := m.ctrl.Call(m, "QueryFinalityProviderVotingPower", fpPk, blockHeight) ret0, _ := ret[0].(uint64) ret1, _ := ret[1].(error) return ret0, ret1 } -// QueryHeightWithLastPubRand indicates an expected call of QueryHeightWithLastPubRand. -func (mr *MockClientControllerMockRecorder) QueryHeightWithLastPubRand(btcPubKey interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryHeightWithLastPubRand", reflect.TypeOf((*MockClientController)(nil).QueryHeightWithLastPubRand), btcPubKey) -} - -// QueryLatestFinalizedBlocks mocks base method. -func (m *MockClientController) QueryLatestFinalizedBlocks(count uint64) ([]*types1.BlockInfo, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryLatestFinalizedBlocks", count) - ret0, _ := ret[0].([]*types1.BlockInfo) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// QueryLatestFinalizedBlocks indicates an expected call of QueryLatestFinalizedBlocks. -func (mr *MockClientControllerMockRecorder) QueryLatestFinalizedBlocks(count interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryLatestFinalizedBlocks", reflect.TypeOf((*MockClientController)(nil).QueryLatestFinalizedBlocks), count) -} - -// QueryNodeStatus mocks base method. -func (m *MockClientController) QueryNodeStatus() (*coretypes.ResultStatus, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryNodeStatus") - ret0, _ := ret[0].(*coretypes.ResultStatus) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// QueryNodeStatus indicates an expected call of QueryNodeStatus. -func (mr *MockClientControllerMockRecorder) QueryNodeStatus() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryNodeStatus", reflect.TypeOf((*MockClientController)(nil).QueryNodeStatus)) -} - -// QueryPendingBTCDelegations mocks base method. -func (m *MockClientController) QueryPendingBTCDelegations() ([]*types0.BTCDelegation, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryPendingBTCDelegations") - ret0, _ := ret[0].([]*types0.BTCDelegation) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// QueryPendingBTCDelegations indicates an expected call of QueryPendingBTCDelegations. -func (mr *MockClientControllerMockRecorder) QueryPendingBTCDelegations() *gomock.Call { +// QueryFinalityProviderVotingPower indicates an expected call of QueryFinalityProviderVotingPower. +func (mr *MockClientControllerMockRecorder) QueryFinalityProviderVotingPower(fpPk, blockHeight interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryPendingBTCDelegations", reflect.TypeOf((*MockClientController)(nil).QueryPendingBTCDelegations)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryFinalityProviderVotingPower", reflect.TypeOf((*MockClientController)(nil).QueryFinalityProviderVotingPower), fpPk, blockHeight) } -// QueryUnbondindBTCDelegations mocks base method. -func (m *MockClientController) QueryUnbondindBTCDelegations() ([]*types0.BTCDelegation, error) { +// QueryLastCommittedPublicRand mocks base method. +func (m *MockClientController) QueryLastCommittedPublicRand(fpPk *btcec.PublicKey, count uint64) (map[uint64]*btcec.FieldVal, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryUnbondindBTCDelegations") - ret0, _ := ret[0].([]*types0.BTCDelegation) + ret := m.ctrl.Call(m, "QueryLastCommittedPublicRand", fpPk, count) + ret0, _ := ret[0].(map[uint64]*btcec.FieldVal) ret1, _ := ret[1].(error) return ret0, ret1 } -// QueryUnbondindBTCDelegations indicates an expected call of QueryUnbondindBTCDelegations. -func (mr *MockClientControllerMockRecorder) QueryUnbondindBTCDelegations() *gomock.Call { +// QueryLastCommittedPublicRand indicates an expected call of QueryLastCommittedPublicRand. +func (mr *MockClientControllerMockRecorder) QueryLastCommittedPublicRand(fpPk, count interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryUnbondindBTCDelegations", reflect.TypeOf((*MockClientController)(nil).QueryUnbondindBTCDelegations)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryLastCommittedPublicRand", reflect.TypeOf((*MockClientController)(nil).QueryLastCommittedPublicRand), fpPk, count) } -// QueryValidatorVotingPower mocks base method. -func (m *MockClientController) QueryValidatorVotingPower(btcPubKey *types.BIP340PubKey, blockHeight uint64) (uint64, error) { +// QueryLatestFinalizedBlocks mocks base method. +func (m *MockClientController) QueryLatestFinalizedBlocks(count uint64) ([]*types.BlockInfo, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "QueryValidatorVotingPower", btcPubKey, blockHeight) - ret0, _ := ret[0].(uint64) + ret := m.ctrl.Call(m, "QueryLatestFinalizedBlocks", count) + ret0, _ := ret[0].([]*types.BlockInfo) ret1, _ := ret[1].(error) return ret0, ret1 } -// QueryValidatorVotingPower indicates an expected call of QueryValidatorVotingPower. -func (mr *MockClientControllerMockRecorder) QueryValidatorVotingPower(btcPubKey, blockHeight interface{}) *gomock.Call { +// QueryLatestFinalizedBlocks indicates an expected call of QueryLatestFinalizedBlocks. +func (mr *MockClientControllerMockRecorder) QueryLatestFinalizedBlocks(count interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryValidatorVotingPower", reflect.TypeOf((*MockClientController)(nil).QueryValidatorVotingPower), btcPubKey, blockHeight) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryLatestFinalizedBlocks", reflect.TypeOf((*MockClientController)(nil).QueryLatestFinalizedBlocks), count) } -// RegisterValidator mocks base method. -func (m *MockClientController) RegisterValidator(bbnPubKey *secp256k1.PubKey, btcPubKey *types.BIP340PubKey, pop *types0.ProofOfPossession, commission *types2.Dec, description *types3.Description) (*provider.RelayerTxResponse, error) { +// RegisterFinalityProvider mocks base method. +func (m *MockClientController) RegisterFinalityProvider(chainPk []byte, fpPk *btcec.PublicKey, pop []byte, commission *math.LegacyDec, description []byte) (*types.TxResponse, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RegisterValidator", bbnPubKey, btcPubKey, pop, commission, description) - ret0, _ := ret[0].(*provider.RelayerTxResponse) + ret := m.ctrl.Call(m, "RegisterFinalityProvider", chainPk, fpPk, pop, commission, description) + ret0, _ := ret[0].(*types.TxResponse) ret1, _ := ret[1].(error) return ret0, ret1 } -// RegisterValidator indicates an expected call of RegisterValidator. -func (mr *MockClientControllerMockRecorder) RegisterValidator(bbnPubKey, btcPubKey, pop, commission, description interface{}) *gomock.Call { +// RegisterFinalityProvider indicates an expected call of RegisterFinalityProvider. +func (mr *MockClientControllerMockRecorder) RegisterFinalityProvider(chainPk, fpPk, pop, commission, description interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterValidator", reflect.TypeOf((*MockClientController)(nil).RegisterValidator), bbnPubKey, btcPubKey, pop, commission, description) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterFinalityProvider", reflect.TypeOf((*MockClientController)(nil).RegisterFinalityProvider), chainPk, fpPk, pop, commission, description) } // SubmitBatchFinalitySigs mocks base method. -func (m *MockClientController) SubmitBatchFinalitySigs(btcPubKey *types.BIP340PubKey, blocks []*types1.BlockInfo, sigs []*types.SchnorrEOTSSig) (*provider.RelayerTxResponse, error) { +func (m *MockClientController) SubmitBatchFinalitySigs(fpPk *btcec.PublicKey, blocks []*types.BlockInfo, sigs []*btcec.ModNScalar) (*types.TxResponse, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitBatchFinalitySigs", btcPubKey, blocks, sigs) - ret0, _ := ret[0].(*provider.RelayerTxResponse) + ret := m.ctrl.Call(m, "SubmitBatchFinalitySigs", fpPk, blocks, sigs) + ret0, _ := ret[0].(*types.TxResponse) ret1, _ := ret[1].(error) return ret0, ret1 } // SubmitBatchFinalitySigs indicates an expected call of SubmitBatchFinalitySigs. -func (mr *MockClientControllerMockRecorder) SubmitBatchFinalitySigs(btcPubKey, blocks, sigs interface{}) *gomock.Call { +func (mr *MockClientControllerMockRecorder) SubmitBatchFinalitySigs(fpPk, blocks, sigs interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitBatchFinalitySigs", reflect.TypeOf((*MockClientController)(nil).SubmitBatchFinalitySigs), btcPubKey, blocks, sigs) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitBatchFinalitySigs", reflect.TypeOf((*MockClientController)(nil).SubmitBatchFinalitySigs), fpPk, blocks, sigs) } // SubmitFinalitySig mocks base method. -func (m *MockClientController) SubmitFinalitySig(btcPubKey *types.BIP340PubKey, blockHeight uint64, blockHash []byte, sig *types.SchnorrEOTSSig) (*provider.RelayerTxResponse, error) { +func (m *MockClientController) SubmitFinalitySig(fpPk *btcec.PublicKey, blockHeight uint64, blockHash []byte, sig *btcec.ModNScalar) (*types.TxResponse, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitFinalitySig", btcPubKey, blockHeight, blockHash, sig) - ret0, _ := ret[0].(*provider.RelayerTxResponse) + ret := m.ctrl.Call(m, "SubmitFinalitySig", fpPk, blockHeight, blockHash, sig) + ret0, _ := ret[0].(*types.TxResponse) ret1, _ := ret[1].(error) return ret0, ret1 } // SubmitFinalitySig indicates an expected call of SubmitFinalitySig. -func (mr *MockClientControllerMockRecorder) SubmitFinalitySig(btcPubKey, blockHeight, blockHash, sig interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitFinalitySig", reflect.TypeOf((*MockClientController)(nil).SubmitFinalitySig), btcPubKey, blockHeight, blockHash, sig) -} - -// SubmitJurySig mocks base method. -func (m *MockClientController) SubmitJurySig(btcPubKey, delPubKey *types.BIP340PubKey, stakingTxHash string, sig *types.BIP340Signature) (*provider.RelayerTxResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitJurySig", btcPubKey, delPubKey, stakingTxHash, sig) - ret0, _ := ret[0].(*provider.RelayerTxResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// SubmitJurySig indicates an expected call of SubmitJurySig. -func (mr *MockClientControllerMockRecorder) SubmitJurySig(btcPubKey, delPubKey, stakingTxHash, sig interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitJurySig", reflect.TypeOf((*MockClientController)(nil).SubmitJurySig), btcPubKey, delPubKey, stakingTxHash, sig) -} - -// SubmitJuryUnbondingSigs mocks base method. -func (m *MockClientController) SubmitJuryUnbondingSigs(btcPubKey, delPubKey *types.BIP340PubKey, stakingTxHash string, unbondingSig, slashUnbondingSig *types.BIP340Signature) (*provider.RelayerTxResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitJuryUnbondingSigs", btcPubKey, delPubKey, stakingTxHash, unbondingSig, slashUnbondingSig) - ret0, _ := ret[0].(*provider.RelayerTxResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// SubmitJuryUnbondingSigs indicates an expected call of SubmitJuryUnbondingSigs. -func (mr *MockClientControllerMockRecorder) SubmitJuryUnbondingSigs(btcPubKey, delPubKey, stakingTxHash, unbondingSig, slashUnbondingSig interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitJuryUnbondingSigs", reflect.TypeOf((*MockClientController)(nil).SubmitJuryUnbondingSigs), btcPubKey, delPubKey, stakingTxHash, unbondingSig, slashUnbondingSig) -} - -// SubmitValidatorUnbondingSig mocks base method. -func (m *MockClientController) SubmitValidatorUnbondingSig(valPubKey, delPubKey *types.BIP340PubKey, stakingTxHash string, sig *types.BIP340Signature) (*provider.RelayerTxResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubmitValidatorUnbondingSig", valPubKey, delPubKey, stakingTxHash, sig) - ret0, _ := ret[0].(*provider.RelayerTxResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// SubmitValidatorUnbondingSig indicates an expected call of SubmitValidatorUnbondingSig. -func (mr *MockClientControllerMockRecorder) SubmitValidatorUnbondingSig(valPubKey, delPubKey, stakingTxHash, sig interface{}) *gomock.Call { +func (mr *MockClientControllerMockRecorder) SubmitFinalitySig(fpPk, blockHeight, blockHash, sig interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitValidatorUnbondingSig", reflect.TypeOf((*MockClientController)(nil).SubmitValidatorUnbondingSig), valPubKey, delPubKey, stakingTxHash, sig) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitFinalitySig", reflect.TypeOf((*MockClientController)(nil).SubmitFinalitySig), fpPk, blockHeight, blockHash, sig) } diff --git a/testutil/store.go b/testutil/store.go index 67b13631..8232282a 100644 --- a/testutil/store.go +++ b/testutil/store.go @@ -7,7 +7,7 @@ import ( "github.com/stretchr/testify/require" - kvstore "github.com/babylonchain/btc-validator/store" + kvstore "github.com/babylonchain/finality-provider/store" ) func CreateStore(r *rand.Rand, t *testing.T) (kvstore.Store, string) { diff --git a/testutil/utils.go b/testutil/utils.go index 05200486..2fb29c8c 100644 --- a/testutil/utils.go +++ b/testutil/utils.go @@ -4,51 +4,44 @@ import ( "math/rand" "testing" - coretypes "github.com/cometbft/cometbft/rpc/core/types" - cometbfttypes "github.com/cometbft/cometbft/types" - sdktypes "github.com/cosmos/cosmos-sdk/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + sdkmath "cosmossdk.io/math" "github.com/golang/mock/gomock" - "github.com/babylonchain/btc-validator/testutil/mocks" + "github.com/babylonchain/finality-provider/testutil/mocks" + "github.com/babylonchain/finality-provider/types" ) -func EmptyDescription() *stakingtypes.Description { - return &stakingtypes.Description{} +const TestPubRandNum = 25 + +func EmptyDescription() []byte { + return []byte("empty description") } -func ZeroCommissionRate() *sdktypes.Dec { - zeroCom := sdktypes.ZeroDec() +func ZeroCommissionRate() *sdkmath.LegacyDec { + zeroCom := sdkmath.LegacyZeroDec() return &zeroCom } func PrepareMockedClientController(t *testing.T, r *rand.Rand, startHeight, currentHeight uint64) *mocks.MockClientController { ctl := gomock.NewController(t) mockClientController := mocks.NewMockClientController(ctl) - status := &coretypes.ResultStatus{ - SyncInfo: coretypes.SyncInfo{LatestBlockHeight: int64(currentHeight)}, - } for i := startHeight + 1; i <= currentHeight; i++ { - resHeader := &coretypes.ResultHeader{ - Header: &cometbfttypes.Header{ - Height: int64(currentHeight), - LastCommitHash: GenRandomByteArray(r, 32), - }, + resBlock := &types.BlockInfo{ + Height: currentHeight, + Hash: GenRandomByteArray(r, 32), } - mockClientController.EXPECT().QueryHeader(int64(i)).Return(resHeader, nil).AnyTimes() + mockClientController.EXPECT().QueryBlock(i).Return(resBlock, nil).AnyTimes() } - currentHeaderRes := &coretypes.ResultHeader{ - Header: &cometbfttypes.Header{ - Height: int64(currentHeight), - LastCommitHash: GenRandomByteArray(r, 32), - }, + currentBlockRes := &types.BlockInfo{ + Height: currentHeight, + Hash: GenRandomByteArray(r, 32), } - mockClientController.EXPECT().QueryNodeStatus().Return(status, nil).AnyTimes() mockClientController.EXPECT().Close().Return(nil).AnyTimes() - mockClientController.EXPECT().QueryBestHeader().Return(currentHeaderRes, nil).AnyTimes() + mockClientController.EXPECT().QueryBestBlock().Return(currentBlockRes, nil).AnyTimes() + mockClientController.EXPECT().QueryActivatedHeight().Return(uint64(1), nil).AnyTimes() return mockClientController } diff --git a/tools/go.mod b/tools/go.mod index c7194f76..c5e1d2f4 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -1,187 +1,221 @@ -module github.com/babylonchain/btc-validator/tools +module github.com/babylonchain/finality-provider/tools -go 1.20 +go 1.21 -require github.com/babylonchain/babylon v0.7.1 +toolchain go1.21.4 + +require github.com/babylonchain/babylon v0.8.0 require ( - cloud.google.com/go v0.110.0 // indirect - cloud.google.com/go/compute v1.19.0 // indirect + cloud.google.com/go v0.110.10 // indirect + cloud.google.com/go/compute v1.23.3 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect - cloud.google.com/go/iam v0.13.0 // indirect - cloud.google.com/go/storage v1.29.0 // indirect - cosmossdk.io/api v0.3.1 // indirect - cosmossdk.io/core v0.5.1 // indirect - cosmossdk.io/depinject v1.0.0-alpha.3 // indirect - cosmossdk.io/errors v1.0.0-beta.7 // indirect - cosmossdk.io/log v1.1.0 // indirect - cosmossdk.io/math v1.0.1 // indirect - cosmossdk.io/tools/rosetta v0.2.1 // indirect + cloud.google.com/go/iam v1.1.5 // indirect + cloud.google.com/go/storage v1.35.1 // indirect + cosmossdk.io/api v0.7.2 // indirect + cosmossdk.io/client/v2 v2.0.0-beta.1 // indirect + cosmossdk.io/collections v0.4.0 // indirect + cosmossdk.io/core v0.11.0 // indirect + cosmossdk.io/depinject v1.0.0-alpha.4 // indirect + cosmossdk.io/errors v1.0.1 // indirect + cosmossdk.io/log v1.3.0 // indirect + cosmossdk.io/math v1.2.0 // indirect + cosmossdk.io/store v1.0.2 // indirect + cosmossdk.io/tools/confix v0.1.0 // indirect + cosmossdk.io/x/circuit v0.1.0 // indirect + cosmossdk.io/x/evidence v0.1.0 // indirect + cosmossdk.io/x/feegrant v0.1.0 // indirect + cosmossdk.io/x/nft v0.1.0 // indirect + cosmossdk.io/x/tx v0.13.0 // indirect + cosmossdk.io/x/upgrade v0.1.0 // indirect filippo.io/edwards25519 v1.0.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/keyring v1.2.1 // indirect - github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect - github.com/CosmWasm/wasmd v0.40.0 // indirect - github.com/CosmWasm/wasmvm v1.2.3 // indirect - github.com/armon/go-metrics v0.4.1 // indirect - github.com/aws/aws-sdk-go v1.44.203 // indirect + github.com/CosmWasm/wasmd v0.50.0 // indirect + github.com/CosmWasm/wasmvm v1.5.2 // indirect + github.com/DataDog/datadog-go v3.2.0+incompatible // indirect + github.com/DataDog/zstd v1.5.5 // indirect + github.com/aead/siphash v1.0.1 // indirect + github.com/aws/aws-sdk-go v1.44.224 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect + github.com/bits-and-blooms/bitset v1.8.0 // indirect github.com/boljen/go-bitmap v0.0.0-20151001105940-23cd2fb0ce7d // indirect - github.com/btcsuite/btcd v0.23.4 // indirect + github.com/btcsuite/btcd v0.24.0 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect - github.com/btcsuite/btcd/btcutil v1.1.3 // indirect - github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 // indirect + github.com/btcsuite/btcd/btcutil v1.1.5 // indirect + github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect github.com/cenkalti/backoff/v4 v4.2.0 // indirect github.com/cespare/xxhash v1.1.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/chzyer/readline v1.5.1 // indirect github.com/cockroachdb/apd/v2 v2.0.2 // indirect - github.com/coinbase/rosetta-sdk-go/types v1.0.0 // indirect - github.com/cometbft/cometbft v0.37.2 // indirect - github.com/cometbft/cometbft-db v0.8.0 // indirect - github.com/confio/ics23/go v0.9.0 // indirect + github.com/cockroachdb/errors v1.11.1 // indirect + github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect + github.com/cockroachdb/pebble v0.0.0-20231102162011-844f0582c2eb // indirect + github.com/cockroachdb/redact v1.1.5 // indirect + github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect + github.com/cometbft/cometbft v0.38.5 // indirect + github.com/cometbft/cometbft-db v0.9.1 // indirect github.com/cosmos/btcutil v1.0.5 // indirect - github.com/cosmos/cosmos-proto v1.0.0-beta.2 // indirect - github.com/cosmos/cosmos-sdk v0.47.3 // indirect + github.com/cosmos/cosmos-db v1.0.0 // indirect + github.com/cosmos/cosmos-proto v1.0.0-beta.3 // indirect + github.com/cosmos/cosmos-sdk v0.50.4-0.20240126152601-c4a2fe2b8987 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect - github.com/cosmos/gogoproto v1.4.10 // indirect - github.com/cosmos/iavl v0.20.0 // indirect - github.com/cosmos/ibc-go/v7 v7.0.1 // indirect + github.com/cosmos/gogoproto v1.4.11 // indirect + github.com/cosmos/iavl v1.0.0 // indirect + github.com/cosmos/ibc-go/modules/capability v1.0.0 // indirect + github.com/cosmos/ibc-go/v8 v8.0.0 // indirect github.com/cosmos/ics23/go v0.10.0 // indirect - github.com/cosmos/ledger-cosmos-go v0.12.1 // indirect - github.com/cosmos/rosetta-sdk-go v0.10.0 // indirect - github.com/creachadair/taskgroup v0.4.2 // indirect + github.com/cosmos/ledger-cosmos-go v0.13.3 // indirect + github.com/creachadair/atomicfile v0.3.1 // indirect + github.com/creachadair/tomledit v0.0.24 // indirect github.com/danieljoos/wincred v1.1.2 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/decred/dcrd/crypto/blake256 v1.0.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect github.com/dgraph-io/badger/v2 v2.2007.4 // indirect github.com/dgraph-io/ristretto v0.1.1 // indirect github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect - github.com/docker/distribution v2.8.2+incompatible // indirect + github.com/distribution/reference v0.5.0 // indirect + github.com/docker/docker v23.0.8+incompatible // indirect github.com/dustin/go-humanize v1.0.1 // indirect - github.com/dvsekhvalnov/jose2go v1.5.0 // indirect - github.com/felixge/httpsnoop v1.0.2 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/dvsekhvalnov/jose2go v1.6.0 // indirect + github.com/emicklei/dot v1.6.0 // indirect + github.com/fatih/color v1.15.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/getsentry/sentry-go v0.25.0 // indirect github.com/go-kit/kit v0.12.0 // indirect github.com/go-kit/log v0.2.1 // indirect github.com/go-logfmt/logfmt v0.6.0 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gogo/googleapis v1.4.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/glog v1.1.0 // indirect + github.com/golang/glog v1.2.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/mock v1.6.0 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/btree v1.1.2 // indirect - github.com/google/go-cmp v0.5.9 // indirect + github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/orderedcode v0.0.1 // indirect - github.com/google/s2a-go v0.1.3 // indirect - github.com/google/uuid v1.3.0 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect - github.com/googleapis/gax-go/v2 v2.8.0 // indirect - github.com/gorilla/handlers v1.5.1 // indirect - github.com/gorilla/mux v1.8.0 // indirect + github.com/google/s2a-go v0.1.7 // indirect + github.com/google/uuid v1.4.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect + github.com/googleapis/gax-go/v2 v2.12.0 // indirect + github.com/gorilla/handlers v1.5.2 // indirect + github.com/gorilla/mux v1.8.1 // indirect github.com/gorilla/websocket v1.5.0 // indirect - github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect + github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect - github.com/gtank/merlin v0.1.1 // indirect - github.com/gtank/ristretto255 v0.1.2 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-getter v1.7.1 // indirect + github.com/hashicorp/go-hclog v1.5.0 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect + github.com/hashicorp/go-metrics v0.5.1 // indirect + github.com/hashicorp/go-plugin v1.5.2 // indirect github.com/hashicorp/go-safetemp v1.0.0 // indirect github.com/hashicorp/go-version v1.6.0 // indirect - github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect + github.com/hashicorp/golang-lru v1.0.2 // indirect github.com/hashicorp/hcl v1.0.0 // indirect + github.com/hashicorp/yamux v0.1.1 // indirect github.com/hdevalence/ed25519consensus v0.1.0 // indirect github.com/huandu/skiplist v1.2.0 // indirect + github.com/iancoleman/strcase v0.3.0 // indirect github.com/improbable-eng/grpc-web v0.15.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jinzhu/copier v0.3.5 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect - github.com/klauspost/compress v1.16.3 // indirect + github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 // indirect + github.com/klauspost/compress v1.17.4 // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/kr/text v0.2.0 // indirect github.com/lib/pq v1.10.7 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect - github.com/linxGnu/grocksdb v1.7.16 // indirect + github.com/linxGnu/grocksdb v1.8.6 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/manifoldco/promptui v0.9.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.18 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect - github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/minio/highwayhash v1.0.2 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mtibben/percent v0.2.1 // indirect + github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a // indirect + github.com/oklog/run v1.1.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/pelletier/go-toml/v2 v2.0.8 // indirect - github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect + github.com/pelletier/go-toml/v2 v2.1.0 // indirect + github.com/petermattis/goid v0.0.0-20230904192822-1876fd5063bc // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_golang v1.15.0 // indirect - github.com/prometheus/client_model v0.3.0 // indirect - github.com/prometheus/common v0.42.0 // indirect - github.com/prometheus/procfs v0.9.0 // indirect - github.com/rakyll/statik v0.1.7 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/client_golang v1.17.0 // indirect + github.com/prometheus/client_model v0.5.0 // indirect + github.com/prometheus/common v0.45.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect + github.com/rogpeppe/go-internal v1.11.0 // indirect github.com/rs/cors v1.8.3 // indirect - github.com/rs/zerolog v1.29.1 // indirect + github.com/rs/zerolog v1.31.0 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sasha-s/go-deadlock v0.3.1 // indirect - github.com/spf13/afero v1.9.5 // indirect - github.com/spf13/cast v1.5.1 // indirect - github.com/spf13/cobra v1.7.0 // indirect - github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.11.0 // indirect + github.com/spf13/cast v1.6.0 // indirect + github.com/spf13/cobra v1.8.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/spf13/viper v1.16.0 // indirect + github.com/spf13/viper v1.18.2 // indirect github.com/stretchr/testify v1.8.4 // indirect - github.com/subosito/gotenv v1.4.2 // indirect - github.com/supranational/blst v0.3.8 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + github.com/supranational/blst v0.3.11 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect github.com/tendermint/go-amino v0.16.0 // indirect - github.com/tidwall/btree v1.6.0 // indirect + github.com/tidwall/btree v1.7.0 // indirect github.com/ulikunitz/xz v0.5.11 // indirect - github.com/zondax/hid v0.9.1 // indirect - github.com/zondax/ledger-go v0.14.1 // indirect - go.etcd.io/bbolt v1.3.7 // indirect + github.com/zondax/hid v0.9.2 // indirect + github.com/zondax/ledger-go v0.14.3 // indirect + go.etcd.io/bbolt v1.3.8 // indirect go.opencensus.io v0.24.0 // indirect - golang.org/x/crypto v0.9.0 // indirect - golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc // indirect - golang.org/x/net v0.10.0 // indirect - golang.org/x/oauth2 v0.8.0 // indirect - golang.org/x/sys v0.8.0 // indirect - golang.org/x/term v0.8.0 // indirect - golang.org/x/text v0.9.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/crypto v0.18.0 // indirect + golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect + golang.org/x/net v0.20.0 // indirect + golang.org/x/oauth2 v0.15.0 // indirect + golang.org/x/sync v0.5.0 // indirect + golang.org/x/sys v0.16.0 // indirect + golang.org/x/term v0.16.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect - google.golang.org/api v0.122.0 // indirect - google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect - google.golang.org/grpc v1.55.0 // indirect - google.golang.org/protobuf v1.30.0 // indirect + google.golang.org/api v0.153.0 // indirect + google.golang.org/appengine v1.6.8 // indirect + google.golang.org/genproto v0.0.0-20231211222908-989df2bf70f3 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20231120223509-83a465c0220f // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0 // indirect + google.golang.org/grpc v1.60.1 // indirect + google.golang.org/protobuf v1.32.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + gotest.tools/v3 v3.5.1 // indirect nhooyr.io/websocket v1.8.6 // indirect - pgregory.net/rapid v0.5.5 // indirect - sigs.k8s.io/yaml v1.3.0 // indirect + pgregory.net/rapid v1.1.0 // indirect + sigs.k8s.io/yaml v1.4.0 // indirect ) +// Downgraded to stable version see: https://github.com/cosmos/cosmos-sdk/pull/14952 replace ( - github.com/babylonchain/babylon => github.com/babylonchain/babylon-private v0.0.0-20230914082434-aece8a12b91c - github.com/cosmos/ibc-go/v7 => github.com/babylonchain/ibc-go/v7 v7.0.0-20230324085744-4d6a0d2c0fcf - - // Downgraded to stable version see: https://github.com/cosmos/cosmos-sdk/pull/14952 + // use cosmos fork of keyring + github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0 github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 ) diff --git a/tools/go.sum b/tools/go.sum index 3dab178b..0a2974f1 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -3,7 +3,6 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= @@ -16,7 +15,6 @@ cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOY cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= @@ -32,8 +30,8 @@ cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w9 cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU= cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA= -cloud.google.com/go v0.110.0 h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys= -cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= +cloud.google.com/go v0.110.10 h1:LXy9GEO+timppncPIAZoOj3l58LIU9k+kn48AN7IO3Y= +cloud.google.com/go v0.110.10/go.mod h1:v1OoFqYxiBkUrruItNM3eT4lLByNjxmJSV/xDKJNnic= cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI= @@ -70,8 +68,8 @@ cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= -cloud.google.com/go/compute v1.19.0 h1:+9zda3WGgW1ZSTlVppLCYFIr48Pa35q1uG2N1itbCEQ= -cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU= +cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= +cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= @@ -111,13 +109,12 @@ cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y97 cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc= cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc= -cloud.google.com/go/iam v0.13.0 h1:+CmB+K0J/33d0zSQ9SlFWUeCCEn5XJA0ZMZ3pHE9u8k= -cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0= +cloud.google.com/go/iam v1.1.5 h1:1jTsCu4bcsNsE4iiqNT5SHwrDRCfRmIaaaVFhRveTJI= +cloud.google.com/go/iam v1.1.5/go.mod h1:rB6P/Ic3mykPbFio+vo7403drjlgvoWfYpJhMXEbzv8= cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic= cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI= cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8= cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08= -cloud.google.com/go/longrunning v0.4.1 h1:v+yFJOfKC3yZdY6ZUI933pIYdhyhV8S3NpWrXWmg7jM= cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4= cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w= cloud.google.com/go/memcache v1.4.0/go.mod h1:rTOfiGZtJX1AaFUrOgsMHX5kAzaTQ8azHiuDoTPzNsE= @@ -171,12 +168,11 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo 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= -cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= -cloud.google.com/go/storage v1.29.0 h1:6weCgzRvMg7lzuUurI4697AqIRPU1SvzHhynwpW31jI= -cloud.google.com/go/storage v1.29.0/go.mod h1:4puEjyTKnku6gfKoTfNOU/W+a9JyuVNxjpS5GBrB8h4= +cloud.google.com/go/storage v1.35.1 h1:B59ahL//eDfx2IIKFBeT5Atm9wnNmj3+8xG/W4WB//w= +cloud.google.com/go/storage v1.35.1/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8= cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw= cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g= cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU= @@ -188,40 +184,60 @@ cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xX cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= -cosmossdk.io/api v0.3.1 h1:NNiOclKRR0AOlO4KIqeaG6PS6kswOMhHD0ir0SscNXE= -cosmossdk.io/api v0.3.1/go.mod h1:DfHfMkiNA2Uhy8fj0JJlOCYOBp4eWUUJ1te5zBGNyIw= -cosmossdk.io/core v0.5.1 h1:vQVtFrIYOQJDV3f7rw4pjjVqc1id4+mE0L9hHP66pyI= -cosmossdk.io/core v0.5.1/go.mod h1:KZtwHCLjcFuo0nmDc24Xy6CRNEL9Vl/MeimQ2aC7NLE= -cosmossdk.io/depinject v1.0.0-alpha.3 h1:6evFIgj//Y3w09bqOUOzEpFj5tsxBqdc5CfkO7z+zfw= -cosmossdk.io/depinject v1.0.0-alpha.3/go.mod h1:eRbcdQ7MRpIPEM5YUJh8k97nxHpYbc3sMUnEtt8HPWU= -cosmossdk.io/errors v1.0.0-beta.7 h1:gypHW76pTQGVnHKo6QBkb4yFOJjC+sUGRc5Al3Odj1w= -cosmossdk.io/errors v1.0.0-beta.7/go.mod h1:mz6FQMJRku4bY7aqS/Gwfcmr/ue91roMEKAmDUDpBfE= -cosmossdk.io/log v1.1.0 h1:v0ogPHYeTzPcBTcPR1A3j1hkei4pZama8kz8LKlCMv0= -cosmossdk.io/log v1.1.0/go.mod h1:6zjroETlcDs+mm62gd8Ig7mZ+N+fVOZS91V17H+M4N4= -cosmossdk.io/math v1.0.1 h1:Qx3ifyOPaMLNH/89WeZFH268yCvU4xEcnPLu3sJqPPg= -cosmossdk.io/math v1.0.1/go.mod h1:Ygz4wBHrgc7g0N+8+MrnTfS9LLn9aaTGa9hKopuym5k= -cosmossdk.io/tools/rosetta v0.2.1 h1:ddOMatOH+pbxWbrGJKRAawdBkPYLfKXutK9IETnjYxw= -cosmossdk.io/tools/rosetta v0.2.1/go.mod h1:Pqdc1FdvkNV3LcNIkYWt2RQY6IP1ge6YWZk8MhhO9Hw= +cosmossdk.io/api v0.7.2 h1:BO3i5fvKMKvfaUiMkCznxViuBEfyWA/k6w2eAF6q1C4= +cosmossdk.io/api v0.7.2/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= +cosmossdk.io/client/v2 v2.0.0-beta.1 h1:XkHh1lhrLYIT9zKl7cIOXUXg2hdhtjTPBUfqERNA1/Q= +cosmossdk.io/client/v2 v2.0.0-beta.1/go.mod h1:JEUSu9moNZQ4kU3ir1DKD5eU4bllmAexrGWjmb9k8qU= +cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= +cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= +cosmossdk.io/core v0.11.0 h1:vtIafqUi+1ZNAE/oxLOQQ7Oek2n4S48SWLG8h/+wdbo= +cosmossdk.io/core v0.11.0/go.mod h1:LaTtayWBSoacF5xNzoF8tmLhehqlA9z1SWiPuNC6X1w= +cosmossdk.io/depinject v1.0.0-alpha.4 h1:PLNp8ZYAMPTUKyG9IK2hsbciDWqna2z1Wsl98okJopc= +cosmossdk.io/depinject v1.0.0-alpha.4/go.mod h1:HeDk7IkR5ckZ3lMGs/o91AVUc7E596vMaOmslGFM3yU= +cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= +cosmossdk.io/errors v1.0.1/go.mod h1:MeelVSZThMi4bEakzhhhE/CKqVv3nOJDA25bIqRDu/U= +cosmossdk.io/log v1.3.0 h1:L0Z0XstClo2kOU4h3V1iDoE5Ji64sg5HLOogzGg67Oo= +cosmossdk.io/log v1.3.0/go.mod h1:HIDyvWLqZe2ovlWabsDN4aPMpY/nUEquAhgfTf2ZzB8= +cosmossdk.io/math v1.2.0 h1:8gudhTkkD3NxOP2YyyJIYYmt6dQ55ZfJkDOaxXpy7Ig= +cosmossdk.io/math v1.2.0/go.mod h1:l2Gnda87F0su8a/7FEKJfFdJrM0JZRXQaohlgJeyQh0= +cosmossdk.io/store v1.0.2 h1:lSg5BTvJBHUDwswNNyeh4K/CbqiHER73VU4nDNb8uk0= +cosmossdk.io/store v1.0.2/go.mod h1:EFtENTqVTuWwitGW1VwaBct+yDagk7oG/axBMPH+FXs= +cosmossdk.io/tools/confix v0.1.0 h1:2OOZTtQsDT5e7P3FM5xqM0bPfluAxZlAwxqaDmYBE+E= +cosmossdk.io/tools/confix v0.1.0/go.mod h1:TdXKVYs4gEayav5wM+JHT+kTU2J7fozFNqoVaN+8CdY= +cosmossdk.io/x/circuit v0.1.0 h1:IAej8aRYeuOMritczqTlljbUVHq1E85CpBqaCTwYgXs= +cosmossdk.io/x/circuit v0.1.0/go.mod h1:YDzblVE8+E+urPYQq5kq5foRY/IzhXovSYXb4nwd39w= +cosmossdk.io/x/evidence v0.1.0 h1:J6OEyDl1rbykksdGynzPKG5R/zm6TacwW2fbLTW4nCk= +cosmossdk.io/x/evidence v0.1.0/go.mod h1:hTaiiXsoiJ3InMz1uptgF0BnGqROllAN8mwisOMMsfw= +cosmossdk.io/x/feegrant v0.1.0 h1:c7s3oAq/8/UO0EiN1H5BIjwVntujVTkYs35YPvvrdQk= +cosmossdk.io/x/feegrant v0.1.0/go.mod h1:4r+FsViJRpcZif/yhTn+E0E6OFfg4n0Lx+6cCtnZElU= +cosmossdk.io/x/nft v0.1.0 h1:VhcsFiEK33ODN27kxKLa0r/CeFd8laBfbDBwYqCyYCM= +cosmossdk.io/x/nft v0.1.0/go.mod h1:ec4j4QAO4mJZ+45jeYRnW7awLHby1JZANqe1hNZ4S3g= +cosmossdk.io/x/tx v0.13.0 h1:8lzyOh3zONPpZv2uTcUmsv0WTXy6T1/aCVDCqShmpzU= +cosmossdk.io/x/tx v0.13.0/go.mod h1:CpNQtmoqbXa33/DVxWQNx5Dcnbkv2xGUhL7tYQ5wUsY= +cosmossdk.io/x/upgrade v0.1.0 h1:z1ZZG4UL9ICTNbJDYZ6jOnF9GdEK9wyoEFi4BUScHXE= +cosmossdk.io/x/upgrade v0.1.0/go.mod h1:/6jjNGbiPCNtmA1N+rBtP601sr0g4ZXuj3yC6ClPCGY= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek= filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= -github.com/99designs/keyring v1.2.1 h1:tYLp1ULvO7i3fI5vE21ReQuj99QFSs7lGm0xWyJo87o= -github.com/99designs/keyring v1.2.1/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= -github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= -github.com/CosmWasm/wasmd v0.40.0 h1:3Vvq1m8dPQdvZR+QJc86VIx6QoWAEVnuHxqBPshJvyo= -github.com/CosmWasm/wasmd v0.40.0/go.mod h1:SuxskRBB7+bpwXGhUXaEfdpjg5WKpdxBy7Tm36VRMUU= -github.com/CosmWasm/wasmvm v1.2.3 h1:OKYlobwmVGbl0eSn0mXoAAjE5hIuXnQCLPjbNd91sVY= -github.com/CosmWasm/wasmvm v1.2.3/go.mod h1:vW/E3h8j9xBQs9bCoijDuawKo9kCtxOaS8N8J7KFtkc= +github.com/CosmWasm/wasmd v0.50.0 h1:NVaGqCSTRfb9UTDHJwT6nQIWcb6VjlQl88iI+u1+qjE= +github.com/CosmWasm/wasmd v0.50.0/go.mod h1:UjmShW4l9YxaMytwJZ7IB7MWzHiynSZP3DdWrG0FRtk= +github.com/CosmWasm/wasmvm v1.5.2 h1:+pKB1Mz9GZVt1vadxB+EDdD1FOz3dMNjIKq/58/lrag= +github.com/CosmWasm/wasmvm v1.5.2/go.mod h1:Q0bSEtlktzh7W2hhEaifrFp1Erx11ckQZmjq8FLCyys= +github.com/DataDog/datadog-go v3.2.0+incompatible h1:qSG2N4FghB1He/r2mFrWKCaL7dXCilEuNEeAn20fdD4= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= +github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= @@ -229,9 +245,10 @@ github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMx github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/adlio/schema v1.3.3 h1:oBJn8I02PyTB466pZO1UZEn1TV5XLlifBSyMrmHl/1I= +github.com/adlio/schema v1.3.3/go.mod h1:1EsRssiv9/Ce2CMzq5DoL7RiMshhuigQxrR4DMV9fHg= +github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= -github.com/alecthomas/participle/v2 v2.0.0-alpha7 h1:cK4vjj0VSgb3lN1nuKA5F7dw+1s1pWBe5bx7nNCnN+c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 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= @@ -243,20 +260,17 @@ github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= -github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= -github.com/aws/aws-sdk-go v1.44.203 h1:pcsP805b9acL3wUqa4JR2vg1k2wnItkDYNvfmcy6F+U= -github.com/aws/aws-sdk-go v1.44.203/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go v1.44.224 h1:09CiaaF35nRmxrzWZ2uRq5v6Ghg/d2RiPjZnSgtt+RQ= +github.com/aws/aws-sdk-go v1.44.224/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= -github.com/babylonchain/babylon-private v0.0.0-20230914082434-aece8a12b91c h1:n4XLSd0DZapEdoiekdwlDvhjknaSG/7AOLhg8eW53Wg= -github.com/babylonchain/babylon-private v0.0.0-20230914082434-aece8a12b91c/go.mod h1:zQsbXiE3LBanEB0kZ8LfiVoP7TMzfVlPrSP3cyEHako= -github.com/babylonchain/ibc-go/v7 v7.0.0-20230324085744-4d6a0d2c0fcf h1:NJU3YuruPqV8w6/y45Zsb8FudcWSkTBugdpTT7kJmjw= -github.com/babylonchain/ibc-go/v7 v7.0.0-20230324085744-4d6a0d2c0fcf/go.mod h1:BFh8nKWjr5zeR2OZfhkzdgDzj1+KjRn3aJLpwapStj8= +github.com/babylonchain/babylon v0.8.0 h1:QC04LPCFBD0MZyiM3cAjVBlr3CXEZPdhORWPBlO2gaQ= +github.com/babylonchain/babylon v0.8.0/go.mod h1:jR1b+5mA7BkRrXfd/PMHwk7W/RpoeQtunvjal+tKeHY= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= 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= @@ -266,25 +280,27 @@ github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 h1:41iFGWnSlI2gVpmOtVTJZNodLdLQLn/KsJqFvXwnd/s= github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bits-and-blooms/bitset v1.8.0 h1:FD+XqgOZDUxxZ8hzoBFuV9+cGWY9CslN6d5MS5JVb4c= +github.com/bits-and-blooms/bitset v1.8.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/boljen/go-bitmap v0.0.0-20151001105940-23cd2fb0ce7d h1:zsO4lp+bjv5XvPTF58Vq+qgmZEYZttJK+CWtSZhKenI= github.com/boljen/go-bitmap v0.0.0-20151001105940-23cd2fb0ce7d/go.mod h1:f1iKL6ZhUWvbk7PdWVmOaak10o86cqMUYEmn1CZNGEI= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= -github.com/btcsuite/btcd v0.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= -github.com/btcsuite/btcd v0.23.4 h1:IzV6qqkfwbItOS/sg/aDfPDsjPP8twrCOE2R93hxMlQ= -github.com/btcsuite/btcd v0.23.4/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= +github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= +github.com/btcsuite/btcd v0.24.0 h1:gL3uHE/IaFj6fcZSu03SvqPMSx7s/dPzfpG/atRwWdo= +github.com/btcsuite/btcd v0.24.0/go.mod h1:K4IDc1593s8jKXIF7yS7yCTSxrknB9z0STzc2j6XgE4= github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= -github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= -github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= +github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8= +github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 h1:KdUfX2zKommPRa+PD0sWZUyXe9w277ABlgELO7H04IM= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= @@ -295,7 +311,8 @@ github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= -github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= +github.com/bufbuild/protocompile v0.6.0 h1:Uu7WiSQ6Yj9DbkdnOe7U4mNKp58y9WDMKDn28/ZlunY= +github.com/bufbuild/protocompile v0.6.0/go.mod h1:YNP35qEYoYGme7QMtz5SBCoN4kL4g12jTtjuzRNdjpE= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= @@ -333,18 +350,26 @@ github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/apd/v2 v2.0.2 h1:weh8u7Cneje73dDh+2tEVLUvyBc89iwepWCD8b8034E= github.com/cockroachdb/apd/v2 v2.0.2/go.mod h1:DDxRlzC2lo3/vSlmSoS7JkqbbrARPuFOGr0B9pvN3Gw= -github.com/cockroachdb/apd/v3 v3.1.0 h1:MK3Ow7LH0W8zkd5GMKA1PvS9qG3bWFI95WaVNfyZJ/w= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= +github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= +github.com/cockroachdb/errors v1.11.1 h1:xSEW75zKaKCWzR3OfxXUxgrk/NtT4G1MiOv5lWZazG8= +github.com/cockroachdb/errors v1.11.1/go.mod h1:8MUxA3Gi6b25tYlFEBGLf+D8aISL+M4MIpiWMSNRfxw= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/pebble v0.0.0-20231102162011-844f0582c2eb h1:6Po+YYKT5B5ZXN0wd2rwFBaebM0LufPf8p4zxOd48Kg= +github.com/cockroachdb/pebble v0.0.0-20231102162011-844f0582c2eb/go.mod h1:acMRUGd/BK8AUmQNK3spUCCGzFLZU2bSST3NMXSq2Kc= +github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= +github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/coinbase/rosetta-sdk-go/types v1.0.0 h1:jpVIwLcPoOeCR6o1tU+Xv7r5bMONNbHU7MuEHboiFuA= -github.com/coinbase/rosetta-sdk-go/types v1.0.0/go.mod h1:eq7W2TMRH22GTW0N0beDnN931DW0/WOI1R2sdHNHG4c= -github.com/cometbft/cometbft v0.37.2 h1:XB0yyHGT0lwmJlFmM4+rsRnczPlHoAKFX6K8Zgc2/Jc= -github.com/cometbft/cometbft v0.37.2/go.mod h1:Y2MMMN//O5K4YKd8ze4r9jmk4Y7h0ajqILXbH5JQFVs= -github.com/cometbft/cometbft-db v0.8.0 h1:vUMDaH3ApkX8m0KZvOFFy9b5DZHBAjsnEuo9AKVZpjo= -github.com/cometbft/cometbft-db v0.8.0/go.mod h1:6ASCP4pfhmrCBpfk01/9E1SI29nD3HfVHrY4PG8x5c0= -github.com/confio/ics23/go v0.9.0 h1:cWs+wdbS2KRPZezoaaj+qBleXgUk5WOQFMP3CQFGTr4= -github.com/confio/ics23/go v0.9.0/go.mod h1:4LPZ2NYqnYIVRklaozjNR1FScgDJ2s5Xrp+e/mYVRak= +github.com/cometbft/cometbft v0.38.5 h1:4lOcK5VTPrfbLOhNHmPYe6c7eDXHtBdMCQuKbAfFJdU= +github.com/cometbft/cometbft v0.38.5/go.mod h1:0tqKin+KQs8zDwzYD8rPHzSBIDNPuB4NrwwGDNb/hUg= +github.com/cometbft/cometbft-db v0.9.1 h1:MIhVX5ja5bXNHF8EYrThkG9F7r9kSfv8BX4LWaxWJ4M= +github.com/cometbft/cometbft-db v0.9.1/go.mod h1:iliyWaoV0mRwBJoizElCwwRA9Tf7jZJOURcRZF9m60U= github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= +github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -353,40 +378,47 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= -github.com/cosmos/cosmos-proto v1.0.0-beta.2 h1:X3OKvWgK9Gsejo0F1qs5l8Qn6xJV/AzgIWR2wZ8Nua8= -github.com/cosmos/cosmos-proto v1.0.0-beta.2/go.mod h1:+XRCLJ14pr5HFEHIUcn51IKXD1Fy3rkEQqt4WqmN4V0= -github.com/cosmos/cosmos-sdk v0.47.3 h1:r0hGmZoAzP2D+MaPaFGHwAaTdFQq3pNpHaUp1BsffbM= -github.com/cosmos/cosmos-sdk v0.47.3/go.mod h1:c4OfLdAykA9zsj1CqrxBRqXzVz48I++JSvIMPSPcEmk= -github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= +github.com/cosmos/cosmos-db v1.0.0 h1:EVcQZ+qYag7W6uorBKFPvX6gRjw6Uq2hIh4hCWjuQ0E= +github.com/cosmos/cosmos-db v1.0.0/go.mod h1:iBvi1TtqaedwLdcrZVYRSSCb6eSy61NLj4UNmdIgs0U= +github.com/cosmos/cosmos-proto v1.0.0-beta.3 h1:VitvZ1lPORTVxkmF2fAp3IiA61xVwArQYKXTdEcpW6o= +github.com/cosmos/cosmos-proto v1.0.0-beta.3/go.mod h1:t8IASdLaAq+bbHbjq4p960BvcTqtwuAxid3b/2rOD6I= +github.com/cosmos/cosmos-sdk v0.50.4-0.20240126152601-c4a2fe2b8987 h1:Pjvcy7wHUoYh253LvNv5Dyx+d3SNkRPsDZH+FytqZ3w= +github.com/cosmos/cosmos-sdk v0.50.4-0.20240126152601-c4a2fe2b8987/go.mod h1:0D9mrUy1eAUMQuvYzf2xvhEPk2ta9w7XH1zcYvyFiuM= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= github.com/cosmos/gogogateway v1.2.0 h1:Ae/OivNhp8DqBi/sh2A8a1D0y638GpL3tkmLQAiKxTE= github.com/cosmos/gogogateway v1.2.0/go.mod h1:iQpLkGWxYcnCdz5iAdLcRBSw3h7NXeOkZ4GUkT+tbFI= github.com/cosmos/gogoproto v1.4.2/go.mod h1:cLxOsn1ljAHSV527CHOtaIP91kK6cCrZETRBrkzItWU= -github.com/cosmos/gogoproto v1.4.10 h1:QH/yT8X+c0F4ZDacDv3z+xE3WU1P1Z3wQoLMBRJoKuI= -github.com/cosmos/gogoproto v1.4.10/go.mod h1:3aAZzeRWpAwr+SS/LLkICX2/kDFyaYVzckBDzygIxek= -github.com/cosmos/iavl v0.20.0 h1:fTVznVlepH0KK8NyKq8w+U7c2L6jofa27aFX6YGlm38= -github.com/cosmos/iavl v0.20.0/go.mod h1:WO7FyvaZJoH65+HFOsDir7xU9FWk2w9cHXNW1XHcl7A= +github.com/cosmos/gogoproto v1.4.11 h1:LZcMHrx4FjUgrqQSWeaGC1v/TeuVFqSLa43CC6aWR2g= +github.com/cosmos/gogoproto v1.4.11/go.mod h1:/g39Mh8m17X8Q/GDEs5zYTSNaNnInBSohtaxzQnYq1Y= +github.com/cosmos/iavl v1.0.0 h1:bw6t0Mv/mVCJvlMTOPHWLs5uUE3BRBfVWCRelOzl+so= +github.com/cosmos/iavl v1.0.0/go.mod h1:CmTGqMnRnucjxbjduneZXT+0vPgNElYvdefjX2q9tYc= +github.com/cosmos/ibc-go/modules/capability v1.0.0 h1:r/l++byFtn7jHYa09zlAdSeevo8ci1mVZNO9+V0xsLE= +github.com/cosmos/ibc-go/modules/capability v1.0.0/go.mod h1:D81ZxzjZAe0ZO5ambnvn1qedsFQ8lOwtqicG6liLBco= +github.com/cosmos/ibc-go/v8 v8.0.0 h1:QKipnr/NGwc+9L7NZipURvmSIu+nw9jOIWTJuDBqOhg= +github.com/cosmos/ibc-go/v8 v8.0.0/go.mod h1:C6IiJom0F3cIQCD5fKwVPDrDK9j/xTu563AWuOmXois= github.com/cosmos/ics23/go v0.10.0 h1:iXqLLgp2Lp+EdpIuwXTYIQU+AiHj9mOC2X9ab++bZDM= github.com/cosmos/ics23/go v0.10.0/go.mod h1:ZfJSmng/TBNTBkFemHHHj5YY7VAU/MBU980F4VU1NG0= -github.com/cosmos/ledger-cosmos-go v0.12.1 h1:sMBxza5p/rNK/06nBSNmsI/WDqI0pVJFVNihy1Y984w= -github.com/cosmos/ledger-cosmos-go v0.12.1/go.mod h1:dhO6kj+Y+AHIOgAe4L9HL/6NDdyyth4q238I9yFpD2g= -github.com/cosmos/rosetta-sdk-go v0.10.0 h1:E5RhTruuoA7KTIXUcMicL76cffyeoyvNybzUGSKFTcM= -github.com/cosmos/rosetta-sdk-go v0.10.0/go.mod h1:SImAZkb96YbwvoRkzSMQB6noNJXFgWl/ENIznEoYQI4= +github.com/cosmos/keyring v1.2.0 h1:8C1lBP9xhImmIabyXW4c3vFjjLiBdGCmfLUfeZlV1Yo= +github.com/cosmos/keyring v1.2.0/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA= +github.com/cosmos/ledger-cosmos-go v0.13.3 h1:7ehuBGuyIytsXbd4MP43mLeoN2LTOEnk5nvue4rK+yM= +github.com/cosmos/ledger-cosmos-go v0.13.3/go.mod h1:HENcEP+VtahZFw38HZ3+LS3Iv5XV6svsnkk9vdJtLr8= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creachadair/taskgroup v0.4.2 h1:jsBLdAJE42asreGss2xZGZ8fJra7WtwnHWeJFxv2Li8= -github.com/creachadair/taskgroup v0.4.2/go.mod h1:qiXUOSrbwAY3u0JPGTzObbE3yf9hcXHDKBZ2ZjpCbgM= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creachadair/atomicfile v0.3.1 h1:yQORkHjSYySh/tv5th1dkKcn02NEW5JleB84sjt+W4Q= +github.com/creachadair/atomicfile v0.3.1/go.mod h1:mwfrkRxFKwpNAflYZzytbSwxvbK6fdGRRlp0KEQc0qU= +github.com/creachadair/tomledit v0.0.24 h1:5Xjr25R2esu1rKCbQEmjZYlrhFkDspoAbAKb6QKQDhQ= +github.com/creachadair/tomledit v0.0.24/go.mod h1:9qHbShRWQzSCcn617cMzg4eab1vbLCOjOshAWSzWr8U= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= -github.com/cucumber/common/gherkin/go/v22 v22.0.0 h1:4K8NqptbvdOrjL9DEea6HFjSpbdT9+Q5kgLpmmsHYl0= -github.com/cucumber/common/messages/go/v17 v17.1.1 h1:RNqopvIFyLWnKv0LfATh34SWBhXeoFTJnSrgm9cT/Ts= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0= github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= @@ -405,20 +437,26 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= -github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= +github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/docker v23.0.8+incompatible h1:z4ZCIwfqHgOEwhxmAWugSL1PFtPQmLP60EVhJYJPaX8= +github.com/docker/docker v23.0.8+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= -github.com/dvsekhvalnov/jose2go v1.5.0 h1:3j8ya4Z4kMCwT5nXIKFSV84YS+HdqSSO0VsTQxaLAeM= -github.com/dvsekhvalnov/jose2go v1.5.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= +github.com/dvsekhvalnov/jose2go v1.6.0 h1:Y9gnSnP4qEI0+/uQkHvFXeD2PLPJeXEL+ySMEA2EjTY= +github.com/dvsekhvalnov/jose2go v1.6.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/emicklei/dot v1.6.0 h1:vUzuoVE8ipzS7QkES4UfxdpCwdU2U97m2Pb2tQCoYRY= +github.com/emicklei/dot v1.6.0/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -431,22 +469,31 @@ github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go. github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/felixge/httpsnoop v1.0.2 h1:+nS9g82KMXccJ/wp0zyRW9ZBHFETmMGtkk+2CTTrW4o= -github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= -github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/getsentry/sentry-go v0.25.0 h1:q6Eo+hS+yoJlTO3uu/azhQadsD8V+jQn2D8VvX1eOyI= +github.com/getsentry/sentry-go v0.25.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/gin-gonic/gin v1.8.1 h1:4+fr/el88TOO3ewCmQr8cx/CtZ/umlIRIs5M4NTNjf8= +github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk= +github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= +github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -455,6 +502,7 @@ github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2 github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= github.com/go-kit/kit v0.12.0 h1:e4o3o3IsBfAKQh5Qbbiqyfu97Ku7jrO/JbohvztANh4= github.com/go-kit/kit v0.12.0/go.mod h1:lHd+EkCZPIwYItmGDDRdhinkzX2A1sj+M9biaEaizzs= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= @@ -463,25 +511,30 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= -github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= +github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= +github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= +github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= +github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ= +github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= -github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= +github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= +github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= +github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk= +github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gofrs/uuid v4.3.0+incompatible h1:CaSVZxm5B+7o45rtab4jC2G37WGYX1zQfuU2i6DSvnc= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/googleapis v1.4.1-0.20201022092350-68b0159b7869/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0= @@ -493,8 +546,8 @@ github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= -github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= +github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68= +github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -553,8 +606,9 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= @@ -565,6 +619,7 @@ github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIG github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw= +github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us= github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -576,24 +631,24 @@ github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/s2a-go v0.1.3 h1:FAgZmpLl/SXurPEZyCMPBIiiYeTbqfjlbdnCNTAkbGE= -github.com/google/s2a-go v0.1.3/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= +github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= +github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= -github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k= -github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= +github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= +github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= @@ -603,37 +658,31 @@ github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99 github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo= github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= -github.com/googleapis/gax-go/v2 v2.8.0 h1:UBtEZqx1bjXtOQ5BVTkuYghXrr3N4V123VKJK67vJZc= -github.com/googleapis/gax-go/v2 v2.8.0/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= +github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= +github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= -github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= -github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= +github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE= +github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= +github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= +github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= +github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= -github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= -github.com/gtank/merlin v0.1.1 h1:eQ90iG7K9pOhtereWsmyRJ6RAwcP4tHTDBHXNg+u5is= -github.com/gtank/merlin v0.1.1/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= -github.com/gtank/ristretto255 v0.1.2 h1:JEqUCPA1NvLq5DwYtuzigd7ss8fwbYay9fi4/5uMzcc= -github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIvY4OmlYW69o= github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -643,11 +692,17 @@ github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9n github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-getter v1.7.1 h1:SWiSWN/42qdpR0MdhaOc/bLR48PLuP1ZQtYLRlM69uY= github.com/hashicorp/go-getter v1.7.1/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744= +github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= +github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-metrics v0.5.1 h1:rfPwUqFU6uZXNvGl4hzjY8LEBsqFVU4si1H9/Hqck/U= +github.com/hashicorp/go-metrics v0.5.1/go.mod h1:KEjodfebIOuBYSAe/bHTm+HChmKSxAOXPBieMLYozDE= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-plugin v1.5.2 h1:aWv8eimFqWlsEiMrYZdPYl+FdHaBJSN4AWwGWfT1G2Y= +github.com/hashicorp/go-plugin v1.5.2/go.mod h1:w1sAEES3g3PuV/RzUrgow20W2uErMly84hhD3um1WL4= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo= @@ -655,22 +710,25 @@ github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoD github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE= +github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= -github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= +github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= +github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/hdevalence/ed25519consensus v0.1.0 h1:jtBwzzcHuTmFrQN6xQZn6CQEO/V9f7HsjsjeEZ6auqU= github.com/hdevalence/ed25519consensus v0.1.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3sus+7FctEyM4RqDxYNzo= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= @@ -679,6 +737,8 @@ github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0Jr github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= +github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2tzCixLaUPQ= @@ -689,7 +749,8 @@ github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLf github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= +github.com/jhump/protoreflect v1.15.3 h1:6SFRuqU45u9hIZPJAoZ8c28T3nK64BNdp9w6jFonzls= +github.com/jhump/protoreflect v1.15.3/go.mod h1:4ORHmSBmlCW8fh3xHmJMGyul1zNqZK4Elxc8qKP+p1k= github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg= github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= @@ -708,6 +769,7 @@ github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u github.com/json-iterator/go v1.1.9/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.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +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= @@ -717,32 +779,35 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 h1:FOOIBWrEkLgmlgGfMuZT83xIwfPDxEI2OHu6xUmJMFE= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= -github.com/klauspost/compress v1.16.3 h1:XuJt9zzcnaz6a16/OU53ZjWp/v7/42WcR5t2a0PcNQY= -github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= +github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= +github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= +github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= -github.com/linxGnu/grocksdb v1.7.16 h1:Q2co1xrpdkr5Hx3Fp+f+f7fRGhQFQhvi/+226dtLmA8= -github.com/linxGnu/grocksdb v1.7.16/go.mod h1:JkS7pl5qWpGpuVb3bPqTz8nC12X3YtPZT+Xq7+QfQo4= +github.com/linxGnu/grocksdb v1.8.6 h1:O7I6SIGPrypf3f/gmrrLUBQDKfO8uOoYdWf4gLS06tc= +github.com/linxGnu/grocksdb v1.8.6/go.mod h1:xZCIb5Muw+nhbDK4Y5UJuOrin5MceOuiXkVUR7vp4WY= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -750,6 +815,7 @@ github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3v github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= @@ -758,17 +824,15 @@ github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= -github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= -github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 h1:QRUSJEgZn2Snx0EmT/QLXibWjSUDjKWvXIT19NBVp94= -github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g= github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= @@ -790,6 +854,7 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ 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 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs= github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -806,24 +871,33 @@ github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OS github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a h1:dlRvE5fWabOchtH7znfiFCcOvmIYgOeAS5ifBXBlh9Q= +github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= +github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.20.0 h1:8W0cWlwFkflGPLltQvLRB7ZVD5HuP6ng320w2IS245Q= +github.com/onsi/gomega v1.26.0 h1:03cDLK28U6hWvCAns6NeydX3zIm4SF3ci69ulidS32Q= +github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034= +github.com/opencontainers/image-spec v1.1.0-rc2/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= github.com/opencontainers/runc v1.1.5 h1:L44KXEpKmfWDcS02aeGm8QNTFXTo2D+8MYGDIJ/GDEs= +github.com/opencontainers/runc v1.1.5/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg= github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= @@ -833,28 +907,32 @@ github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJ github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA= +github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= -github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= +github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= +github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= -github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 h1:hDSdbBuw3Lefr6R18ax0tZ2BJeNB3NehB3trOwYBsdU= -github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/petermattis/goid v0.0.0-20230904192822-1876fd5063bc h1:8bQZVK1X6BJR/6nYUPxQEP+ReTsceJTKizeuwjWOPUA= +github.com/petermattis/goid v0.0.0-20230904192822-1876fd5063bc/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= +github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= -github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= @@ -862,52 +940,55 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.15.0 h1:5fCgGYogn0hFdhyhLbw7hEsWxufKtY9klyvdNfFlFhM= -github.com/prometheus/client_golang v1.15.0/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk= +github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= +github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 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.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= -github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= -github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= +github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= +github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= -github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= -github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= -github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/regen-network/gocuke v0.6.2 h1:pHviZ0kKAq2U2hN2q3smKNxct6hS0mGByFMHGnWA97M= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.8.3 h1:O+qNyWn7Z+F9M0ILBHgMVPuB1xTOucVd5gtaYyXBpRo= github.com/rs/cors v1.8.3/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= -github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.29.1 h1:cO+d60CHkknCbvzEWxP0S9K6KqyTjrCNUy1LdQLCGPc= -github.com/rs/zerolog v1.29.1/go.mod h1:Le6ESbR7hc+DP6Lt1THiV8CQSdkkNrd3R0XbEgp3ZBU= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A= +github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0= github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= @@ -918,33 +999,34 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= -github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= -github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= -github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/spf13/viper v1.16.0 h1:rGGH0XDZhdUOryiDWjmIvUSWpbNqisK8Wk0Vyefw8hc= -github.com/spf13/viper v1.16.0/go.mod h1:yg78JgCJcbrQOvV9YLXgkLaZqUidkY9K+Dd1FofRzQg= +github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= +github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= @@ -960,34 +1042,36 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= -github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= -github.com/supranational/blst v0.3.8 h1:glwLF4oBRSJOTr05lRBgNwGQST0ndP2wg29fSeTRKCY= -github.com/supranational/blst v0.3.8/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= +github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= -github.com/tidwall/btree v1.6.0 h1:LDZfKfQIBHGHWSwckhXI0RPSXzlo+KYdjK7FWSqOzzg= -github.com/tidwall/btree v1.6.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= +github.com/tidwall/btree v1.7.0 h1:L1fkJH/AuEh5zBnnBbmTwQ5Lt+bRJ5A8EWecslvo9iI= +github.com/tidwall/btree v1.7.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/vulpine-io/io-test v1.0.0 h1:Ot8vMh+ssm1VWDAwJ3U4C5qG9aRnr5YfQFZPNZBAUGI= +github.com/vulpine-io/io-test v1.0.0/go.mod h1:X1I+p5GCxVX9m4nFd1HBtr2bVX9v1ZE6x8w+Obt36AU= 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/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -996,13 +1080,13 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de 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/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/zondax/hid v0.9.1 h1:gQe66rtmyZ8VeGFcOpbuH3r7erYtNEAezCAYu8LdkJo= -github.com/zondax/hid v0.9.1/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= -github.com/zondax/ledger-go v0.14.1 h1:Pip65OOl4iJ84WTpA4BKChvOufMhhbxED3BaihoZN4c= -github.com/zondax/ledger-go v0.14.1/go.mod h1:fZ3Dqg6qcdXWSOJFKMG8GCTnD7slO/RL2feOQv8K320= +github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= +github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= +github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw= +github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= -go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= +go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA= +go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= @@ -1019,11 +1103,17 @@ go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqe go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1033,15 +1123,11 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= -golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1053,8 +1139,8 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= -golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc h1:mCRnTeVUjcrhlRmO0VK8a6k6Rrf6TF9htwo2pJVSjIU= -golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1081,7 +1167,8 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= +golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= +golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1124,14 +1211,12 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/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-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= @@ -1144,8 +1229,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1171,8 +1256,8 @@ golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= -golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= -golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= +golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ= +golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= 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= @@ -1187,7 +1272,8 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1244,13 +1330,11 @@ golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/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-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1263,6 +1347,7 @@ golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/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-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1282,17 +1367,17 @@ golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= 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= @@ -1304,12 +1389,14 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1331,6 +1418,7 @@ golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1364,7 +1452,6 @@ golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= @@ -1372,7 +1459,8 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= +golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= +golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1431,8 +1519,8 @@ google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= -google.golang.org/api v0.122.0 h1:zDobeejm3E7pEG1mNHvdxvjs5XJoCMzyNH+CmwL94Es= -google.golang.org/api v0.122.0/go.mod h1:gcitW0lvnyWjSp9nKxAbdHKIZ6vF4aajGueeslZOyms= +google.golang.org/api v0.153.0 h1:N1AwGhielyKFaUqH07/ZSIQR3uNPcV7NVw0vj+j4iR4= +google.golang.org/api v0.153.0/go.mod h1:3qNJX5eOmhiWYc67jRA/3GsDw97UFb5ivv7Y2PrriAY= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1440,8 +1528,9 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -1480,10 +1569,8 @@ google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -1550,12 +1637,12 @@ google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqw google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= -google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e h1:Ao9GzfUMPH3zjVfzXG5rlWlk+Q8MXWKwWpwVQE1MXfw= -google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:zqTuNwFlFRsw5zIts5VnzLQxSRqh+CGOTVMlYbY0Eyk= -google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc h1:kVKPf/IiYSBWEWtkIn6wZXwWGCnLKcC8oWfZvXjsGnM= -google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc h1:XSJ8Vk1SWuNr8S18z1NZSziL0CPIXLCCMDOEFtHBOFc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= +google.golang.org/genproto v0.0.0-20231211222908-989df2bf70f3 h1:1hfbdAfFbkmpg41000wDVqr7jUpK/Yo+LPnIxxGzmkg= +google.golang.org/genproto v0.0.0-20231211222908-989df2bf70f3/go.mod h1:5RBcpGRxr25RbDzY5w+dmaqpSEvl8Gwl1x2CICf60ic= +google.golang.org/genproto/googleapis/api v0.0.0-20231120223509-83a465c0220f h1:2yNACc1O40tTnrsbk9Cv6oxiW8pxI/pXj0wRtdlYmgY= +google.golang.org/genproto/googleapis/api v0.0.0-20231120223509-83a465c0220f/go.mod h1:Uy9bTZJqmfrw2rIBxgGLnamc78euZULUBrLZ9XTITKI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0 h1:/jFB8jK5R3Sq3i/lmeZO0cATSzFfZaJq1J2Euan3XKU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0/go.mod h1:FUoWkonphQm3RhTS+kOEhF8h0iDpm4tdXolVCeZ9KKA= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= @@ -1597,8 +1684,8 @@ google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACu google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag= -google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= +google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= +google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -1615,14 +1702,15 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= @@ -1648,8 +1736,8 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= -gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o= +gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= +gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1660,12 +1748,12 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= nhooyr.io/websocket v1.8.6 h1:s+C3xAMLwGmlI31Nyn/eAehUlZPwfYZu2JXM621Q5/k= nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= -pgregory.net/rapid v0.5.5 h1:jkgx1TjbQPD/feRoK+S/mXw9e1uj6WilpHrXJowi6oA= -pgregory.net/rapid v0.5.5/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= +pgregory.net/rapid v1.1.0 h1:CMa0sjHSru3puNx+J0MIAuiiEV4N0qj8/cMWGBBCsjw= +pgregory.net/rapid v1.1.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/tools/tools.go b/tools/tools.go index 213715c3..752851fa 100644 --- a/tools/tools.go +++ b/tools/tools.go @@ -1,7 +1,7 @@ //go:build tools // +build tools -package btcvalidator +package finalityprovider import ( _ "github.com/babylonchain/babylon/cmd/babylond" diff --git a/types/blockinfo.go b/types/blockinfo.go index 99b750df..4fbc3708 100644 --- a/types/blockinfo.go +++ b/types/blockinfo.go @@ -1,6 +1,7 @@ package types type BlockInfo struct { - Height uint64 - LastCommitHash []byte + Height uint64 + Hash []byte + Finalized bool } diff --git a/types/chainkey.go b/types/chainkey.go new file mode 100644 index 00000000..6d5df870 --- /dev/null +++ b/types/chainkey.go @@ -0,0 +1,14 @@ +package types + +import ( + "github.com/btcsuite/btcd/btcec/v2" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type ChainKeyInfo struct { + Name string + Mnemonic string + AccAddress sdk.AccAddress + PublicKey *btcec.PublicKey + PrivateKey *btcec.PrivateKey +} diff --git a/types/errors.go b/types/errors.go deleted file mode 100644 index c950bfd5..00000000 --- a/types/errors.go +++ /dev/null @@ -1,17 +0,0 @@ -package types - -import ( - "errors" -) - -var ( - ErrValidatorSlashed = errors.New("the validator has been slashed") - ErrTooFewPubRand = errors.New("the request contains too few public randomness") - ErrBlockNotFound = errors.New("the block is not found") - ErrHeightTooHigh = errors.New("the chain has not reached the given height yet") - ErrInvalidPubRand = errors.New("the public randomness list is invalid") - ErrNoPubRandYet = errors.New("the BTC validator has not committed any public randomness yet") - ErrPubRandNotFound = errors.New("public randomness is not found") - ErrInvalidFinalitySig = errors.New("finality signature is not valid") - ErrDuplicatedFinalitySig = errors.New("the finality signature has been casted before") -) diff --git a/types/stakingparams.go b/types/stakingparams.go new file mode 100644 index 00000000..4c71c227 --- /dev/null +++ b/types/stakingparams.go @@ -0,0 +1,42 @@ +package types + +import ( + sdkmath "cosmossdk.io/math" + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcutil" +) + +type StakingParams struct { + // K-deep + ComfirmationTimeBlocks uint64 + // W-deep + FinalizationTimeoutBlocks uint64 + + // Minimum amount of tx fee (quantified in Satoshi) needed for the pre-signed slashing tx + MinSlashingTxFeeSat btcutil.Amount + + // Bitcoin public keys of the covenant committee + CovenantPks []*btcec.PublicKey + + // Address to which slashing transactions are sent + SlashingAddress btcutil.Address + + // Minimum number of signatures needed for the covenant multisignature + CovenantQuorum uint32 + + // The staked amount to be slashed, expressed as a decimal (e.g., 0.5 for 50%). + SlashingRate sdkmath.LegacyDec + + // The minimum time for unbonding transaction timelock in BTC blocks + MinUnbondingTime uint32 +} + +// MinimumUnbondingTime returns the minimum unbonding time. It is the bigger value from: +// - MinUnbondingTime +// - CheckpointFinalizationTimeout +func (p *StakingParams) MinimumUnbondingTime() uint64 { + return sdkmath.Max[uint64]( + uint64(p.MinUnbondingTime), + p.FinalizationTimeoutBlocks, + ) +} diff --git a/types/txresponse.go b/types/txresponse.go new file mode 100644 index 00000000..bd8cdfb6 --- /dev/null +++ b/types/txresponse.go @@ -0,0 +1,10 @@ +package types + +import ( + "github.com/cosmos/relayer/v2/relayer/provider" +) + +type TxResponse struct { + TxHash string + Events []provider.RelayerEvent +} diff --git a/util/path.go b/util/path.go new file mode 100644 index 00000000..ec7e497f --- /dev/null +++ b/util/path.go @@ -0,0 +1,64 @@ +package util + +import ( + "fmt" + "os" + "os/user" + "path/filepath" + "strings" +) + +// FileExists reports whether the named file or directory exists. +// This function is taken from https://github.com/btcsuite/btcd +func FileExists(name string) bool { + if _, err := os.Stat(name); err != nil { + if os.IsNotExist(err) { + return false + } + } + return true +} + +func MakeDirectory(dir string) error { + err := os.MkdirAll(dir, 0700) + if err != nil { + // Show a nicer error message if it's because a symlink + // is linked to a directory that does not exist + // (probably because it's not mounted). + if e, ok := err.(*os.PathError); ok && os.IsExist(err) { + link, lerr := os.Readlink(e.Path) + if lerr == nil { + str := "is symlink %s -> %s mounted?" + err = fmt.Errorf(str, e.Path, link) + } + } + return fmt.Errorf("failed to create dir %s: %w", dir, err) + } + return nil +} + +// CleanAndExpandPath expands environment variables and leading ~ in the +// passed path, cleans the result, and returns it. +// This function is taken from https://github.com/btcsuite/btcd +func CleanAndExpandPath(path string) string { + if path == "" { + return "" + } + + // Expand initial ~ to OS specific home directory. + if strings.HasPrefix(path, "~") { + var homeDir string + u, err := user.Current() + if err == nil { + homeDir = u.HomeDir + } else { + homeDir = os.Getenv("HOME") + } + + path = strings.Replace(path, "~", homeDir, 1) + } + + // NOTE: The os.ExpandEnv doesn't work with Windows-style %VARIABLE%, + // but the variables can still be expanded via POSIX-style $VARIABLE. + return filepath.Clean(os.ExpandEnv(path)) +} diff --git a/val/keyringcontroller.go b/val/keyringcontroller.go deleted file mode 100644 index e2a71341..00000000 --- a/val/keyringcontroller.go +++ /dev/null @@ -1,264 +0,0 @@ -package val - -import ( - "fmt" - - "github.com/babylonchain/babylon/types" - bstypes "github.com/babylonchain/babylon/x/btcstaking/types" - "github.com/btcsuite/btcd/btcec/v2" - "github.com/btcsuite/btcd/btcec/v2/schnorr" - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/crypto/keyring" - "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - "github.com/cosmos/go-bip39" -) - -const ( - btcPrefix = "btc-" - bbnPrefix = "bbn-" - secp256k1Type = "secp256k1" - mnemonicEntropySize = 256 -) - -type KeyName string - -func (kn KeyName) GetBabylonKeyName() string { - return bbnPrefix + string(kn) -} - -func (kn KeyName) GetBtcKeyName() string { - return btcPrefix + string(kn) -} - -type KeyringController struct { - kr keyring.Keyring - name KeyName -} - -func NewKeyringController(ctx client.Context, name string, keyringBackend string) (*KeyringController, error) { - if name == "" { - return nil, fmt.Errorf("the key name should not be empty") - } - if keyringBackend == "" { - return nil, fmt.Errorf("the keyring backend should not be empty") - } - - kr, err := keyring.New( - ctx.ChainID, - keyringBackend, - ctx.KeyringDir, - ctx.Input, - ctx.Codec, - ctx.KeyringOptions...) - if err != nil { - return nil, fmt.Errorf("failed to create keyring: %w", err) - } - - return &KeyringController{ - name: KeyName(name), - kr: kr, - }, nil -} - -func NewKeyringControllerWithKeyring(kr keyring.Keyring, name string) (*KeyringController, error) { - if name == "" { - return nil, fmt.Errorf("the key name should not be empty") - } - return &KeyringController{ - kr: kr, - name: KeyName(name), - }, nil -} - -// CreateValidatorKeys creates a BTC validator object using the keyring -func (kc *KeyringController) CreateValidatorKeys() (*types.BIP340PubKey, *secp256k1.PubKey, error) { - // create babylon key pair stored in the keyring - babylonPubKey, err := kc.createBabylonKeyPair() - if err != nil { - return nil, nil, err - } - - // create BTC key pair stored in the keyring - btcPubKey, err := kc.createBIP340KeyPair() - if err != nil { - return nil, nil, err - } - - return btcPubKey, babylonPubKey, nil -} - -func (kc *KeyringController) GetKeyName() string { - return string(kc.name) -} - -func (kc *KeyringController) GetBabylonPublicKeyBytes() ([]byte, error) { - k, err := kc.kr.Key(kc.name.GetBabylonKeyName()) - if err != nil { - return nil, err - } - pubKey, err := k.GetPubKey() - if err != nil { - return nil, err - } - return pubKey.Bytes(), err -} - -func (kc *KeyringController) ValidatorKeyExists() bool { - return kc.keyExists(kc.name.GetBabylonKeyName()) && kc.keyExists(kc.name.GetBtcKeyName()) -} - -func (kc *KeyringController) ValidatorKeyNameTaken() bool { - return kc.keyExists(kc.name.GetBabylonKeyName()) || kc.keyExists(kc.name.GetBtcKeyName()) -} - -func (kc *KeyringController) JuryKeyTaken() bool { - return kc.keyExists(kc.GetKeyName()) -} - -func (kc *KeyringController) keyExists(name string) bool { - _, err := kc.kr.Key(name) - return err == nil -} - -func (kc *KeyringController) GetKeyring() keyring.Keyring { - return kc.kr -} - -// createBabylonKeyPair creates a babylon key pair stored in the keyring -func (kc *KeyringController) createBabylonKeyPair() (*secp256k1.PubKey, error) { - return kc.createKey(kc.name.GetBabylonKeyName()) -} - -// createBIP340KeyPair creates a BIP340 key pair stored in the keyring -func (kc *KeyringController) createBIP340KeyPair() (*types.BIP340PubKey, error) { - sdkPk, err := kc.createKey(kc.name.GetBtcKeyName()) - if err != nil { - return nil, err - } - - btcPk, err := btcec.ParsePubKey(sdkPk.Key) - if err != nil { - return nil, err - } - return types.NewBIP340PubKeyFromBTCPK(btcPk), nil -} - -func (kc *KeyringController) CreateJuryKey() (*btcec.PublicKey, error) { - sdkPk, err := kc.createKey(string(kc.name)) - if err != nil { - return nil, err - } - - return btcec.ParsePubKey(sdkPk.Key) -} - -func (kc *KeyringController) createKey(name string) (*secp256k1.PubKey, error) { - keyringAlgos, _ := kc.kr.SupportedAlgorithms() - algo, err := keyring.NewSigningAlgoFromString(secp256k1Type, keyringAlgos) - if err != nil { - return nil, err - } - - // read entropy seed straight from tmcrypto.Rand and convert to mnemonic - entropySeed, err := bip39.NewEntropy(mnemonicEntropySize) - if err != nil { - return nil, err - } - - mnemonic, err := bip39.NewMnemonic(entropySeed) - if err != nil { - return nil, err - } - // TODO use a better way to remind the user to keep it - fmt.Printf("Generated mnemonic for key %s is %s\n", name, mnemonic) - - // TODO for now we leave bip39Passphrase and hdPath empty - record, err := kc.kr.NewAccount(name, mnemonic, "", "", algo) - if err != nil { - return nil, err - } - - pubKey, err := record.GetPubKey() - if err != nil { - return nil, err - } - - switch v := pubKey.(type) { - case *secp256k1.PubKey: - return v, nil - default: - return nil, fmt.Errorf("unsupported key type in keyring") - } -} - -// CreatePop creates proof-of-possession of Babylon and BTC public keys -// the input is the bytes of BTC public key used to sign -// this requires both keys created beforehand -func (kc *KeyringController) CreatePop() (*bstypes.ProofOfPossession, error) { - if !kc.ValidatorKeyExists() { - return nil, fmt.Errorf("the keys do not exist") - } - - btcPrivKey, err := kc.GetBtcPrivKey() - if err != nil { - return nil, err - } - - bbnPrivKey, err := kc.GetBabylonPrivKey() - if err != nil { - return nil, err - } - return bstypes.NewPoP(bbnPrivKey, btcPrivKey) -} - -func (kc *KeyringController) GetBabylonPrivKey() (*secp256k1.PrivKey, error) { - bbnName := kc.name.GetBabylonKeyName() - - bbnPrivKey, _, err := kc.getKey(bbnName) - if err != nil { - return nil, err - } - - sdkPrivKey := &secp256k1.PrivKey{Key: bbnPrivKey.Serialize()} - - return sdkPrivKey, nil -} - -func (kc *KeyringController) GetBtcPrivKey() (*btcec.PrivateKey, error) { - btcName := kc.name.GetBtcKeyName() - - btcPrivKey, _, err := kc.getKey(btcName) - if err != nil { - return nil, err - } - - return btcPrivKey, nil -} - -func (kc *KeyringController) getKey(name string) (*btcec.PrivateKey, *btcec.PublicKey, error) { - k, err := kc.kr.Key(name) - if err != nil { - return nil, nil, fmt.Errorf("failed to get private key by name %s: %w", name, err) - } - - privKeyCached := k.GetLocal().PrivKey.GetCachedValue() - - var privKey *btcec.PrivateKey - var pubKey *btcec.PublicKey - switch v := privKeyCached.(type) { - case *secp256k1.PrivKey: - privKey, pubKey = btcec.PrivKeyFromBytes(v.Key) - return privKey, pubKey, nil - default: - return nil, nil, fmt.Errorf("unsupported key type in keyring") - } -} - -func (kc *KeyringController) SchnorrSign(msg []byte) (*schnorr.Signature, error) { - btcPrivKey, _, err := kc.getKey(kc.name.GetBtcKeyName()) - if err != nil { - return nil, err - } - - return schnorr.Sign(btcPrivKey, msg) -} diff --git a/val/keyringcontroller_test.go b/val/keyringcontroller_test.go deleted file mode 100644 index 424cfb4a..00000000 --- a/val/keyringcontroller_test.go +++ /dev/null @@ -1,46 +0,0 @@ -package val_test - -import ( - "math/rand" - "os" - "testing" - - "github.com/babylonchain/babylon/types" - "github.com/stretchr/testify/require" - - "github.com/babylonchain/btc-validator/testutil" - "github.com/babylonchain/btc-validator/val" -) - -// FuzzCreatePoP tests the creation of PoP -func FuzzCreatePoP(f *testing.F) { - testutil.AddRandomSeedsToFuzzer(f, 10) - f.Fuzz(func(t *testing.T, seed int64) { - r := rand.New(rand.NewSource(seed)) - - keyName := testutil.GenRandomHexStr(r, 4) - sdkCtx := testutil.GenSdkContext(r, t) - defer func() { - err := os.RemoveAll(sdkCtx.KeyringDir) - require.NoError(t, err) - }() - - kc, err := val.NewKeyringController(sdkCtx, keyName, "test") - require.NoError(t, err) - require.False(t, kc.ValidatorKeyExists()) - - btcPk, bbnPk, err := kc.CreateValidatorKeys() - require.NoError(t, err) - require.True(t, kc.ValidatorKeyExists() && kc.ValidatorKeyNameTaken()) - - pop, err := kc.CreatePop() - require.NoError(t, err) - validator := val.NewStoreValidator(bbnPk, btcPk, kc.GetKeyName(), pop, testutil.EmptyDescription(), testutil.ZeroCommissionRate()) - - btcSig := new(types.BIP340Signature) - err = btcSig.Unmarshal(validator.Pop.BtcSig) - require.NoError(t, err) - err = pop.Verify(bbnPk, btcPk) - require.NoError(t, err) - }) -} diff --git a/val/valstore.go b/val/valstore.go deleted file mode 100644 index b81570bb..00000000 --- a/val/valstore.go +++ /dev/null @@ -1,269 +0,0 @@ -package val - -import ( - "fmt" - "math" - - "github.com/babylonchain/babylon/types" - bstypes "github.com/babylonchain/babylon/x/btcstaking/types" - "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - sdktypes "github.com/cosmos/cosmos-sdk/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - gproto "google.golang.org/protobuf/proto" - - "github.com/babylonchain/btc-validator/proto" - "github.com/babylonchain/btc-validator/store" - "github.com/babylonchain/btc-validator/valcfg" -) - -const ( - validatorPrefix = "validator" - randPairPrefix = "rand-pair" -) - -func NewStoreValidator(babylonPk *secp256k1.PubKey, btcPk *types.BIP340PubKey, keyName string, pop *bstypes.ProofOfPossession, des *stakingtypes.Description, com *sdktypes.Dec) *proto.StoreValidator { - return &proto.StoreValidator{ - KeyName: keyName, - BabylonPk: babylonPk.Bytes(), - BtcPk: btcPk.MustMarshal(), - Pop: &proto.ProofOfPossession{ - BabylonSig: pop.BabylonSig, - BtcSig: pop.BtcSig, - }, - Status: proto.ValidatorStatus_CREATED, - Description: des, - Commission: com.String(), - } -} - -type ValidatorStore struct { - s store.Store -} - -func NewValidatorStore(dbcfg *valcfg.DatabaseConfig) (*ValidatorStore, error) { - s, err := openStore(dbcfg) - if err != nil { - return nil, err - } - - return &ValidatorStore{s: s}, nil -} - -func (vs *ValidatorStore) getValidatorKey(pk []byte) []byte { - return append([]byte(validatorPrefix), pk...) -} - -func (vs *ValidatorStore) getValidatorListKey() []byte { - return []byte(validatorPrefix) -} - -func (vs *ValidatorStore) getRandPairKey(pk []byte, height uint64) []byte { - return append(vs.getRandPairListKey(pk), sdktypes.Uint64ToBigEndian(height)...) -} - -func (vs *ValidatorStore) getRandPairListKey(pk []byte) []byte { - return append([]byte(randPairPrefix), pk...) -} - -func (vs *ValidatorStore) SaveValidator(val *proto.StoreValidator) error { - k := vs.getValidatorKey(val.BabylonPk) - v, err := gproto.Marshal(val) - if err != nil { - return fmt.Errorf("failed to marshal the created validator object: %w", err) - } - - if err := vs.s.Put(k, v); err != nil { - return fmt.Errorf("failed to save the created validator object: %w", err) - } - - return nil -} - -func (vs *ValidatorStore) UpdateValidator(val *proto.StoreValidator) error { - k := vs.getValidatorKey(val.BabylonPk) - exists, err := vs.s.Exists(k) - if err != nil { - return err - } - if !exists { - return fmt.Errorf("the validator does not exist") - } - - v, err := gproto.Marshal(val) - if err != nil { - return err - } - - if err := vs.s.Put(k, v); err != nil { - return err - } - - return nil -} - -func (vs *ValidatorStore) SetValidatorStatus(val *proto.StoreValidator, status proto.ValidatorStatus) error { - val.Status = status - return vs.UpdateValidator(val) -} - -func (vs *ValidatorStore) SaveRandPair(pk []byte, height uint64, randPair *proto.SchnorrRandPair) error { - k := vs.getRandPairKey(pk, height) - v, err := gproto.Marshal(randPair) - if err != nil { - return fmt.Errorf("failed to marshal the Schnorr random pair: %w", err) - } - - if err := vs.s.Put(k, v); err != nil { - return fmt.Errorf("failed to save the Schnorr random pair: %w", err) - } - - return nil -} - -func (vs *ValidatorStore) GetRandPairList(pk []byte) ([]*proto.SchnorrRandPair, error) { - k := vs.getRandPairListKey(pk) - pairsBytes, err := vs.s.List(k) - if err != nil { - return nil, err - } - - pairList := make([]*proto.SchnorrRandPair, len(pairsBytes)) - for i := 0; i < len(pairsBytes); i++ { - pair := new(proto.SchnorrRandPair) - err := gproto.Unmarshal(pairsBytes[i].Value, pair) - if err != nil { - panic(fmt.Errorf("failed to unmarshal Schnorr randomness pair from the database: %w", err)) - } - pairList[i] = pair - } - - return pairList, nil -} - -func (vs *ValidatorStore) GetRandPair(pk []byte, height uint64) (*proto.SchnorrRandPair, error) { - k := vs.getRandPairKey(pk, height) - v, err := vs.s.Get(k) - if err != nil { - return nil, fmt.Errorf("failed to get the randomness pair from DB: %w", err) - } - pair := new(proto.SchnorrRandPair) - err = gproto.Unmarshal(v, pair) - if err != nil { - panic(fmt.Errorf("unable to unmarshal Schnorr randomness pair: %w", err)) - } - - return pair, nil -} - -func (vs *ValidatorStore) GetStoreValidator(pk []byte) (*proto.StoreValidator, error) { - k := vs.getValidatorKey(pk) - valsBytes, err := vs.s.Get(k) - if err != nil { - return nil, err - } - - val := new(proto.StoreValidator) - err = gproto.Unmarshal(valsBytes, val) - if err != nil { - panic(fmt.Errorf("unable to unmarshal validator object: %w", err)) - } - - return val, nil -} - -func (vs *ValidatorStore) ListValidators() ([]*proto.StoreValidator, error) { - k := vs.getValidatorListKey() - valsBytes, err := vs.s.List(k) - if err != nil { - return nil, err - } - - valsList := make([]*proto.StoreValidator, len(valsBytes)) - for i := 0; i < len(valsBytes); i++ { - val := new(proto.StoreValidator) - err := gproto.Unmarshal(valsBytes[i].Value, val) - if err != nil { - panic(fmt.Errorf("failed to unmarshal validator from the database: %w", err)) - } - valsList[i] = val - } - - return valsList, nil -} - -// ListRegisteredValidators returns a list of validators whose status is more than CREATED -// but less than SLASHED -func (vs *ValidatorStore) ListRegisteredValidators() ([]*proto.StoreValidator, error) { - k := vs.getValidatorListKey() - valsBytes, err := vs.s.List(k) - if err != nil { - return nil, err - } - - valsList := make([]*proto.StoreValidator, 0) - for i := 0; i < len(valsBytes); i++ { - val := new(proto.StoreValidator) - err := gproto.Unmarshal(valsBytes[i].Value, val) - if err != nil { - panic(fmt.Errorf("failed to unmarshal validator from the database: %w", err)) - } - if val.Status > proto.ValidatorStatus_CREATED && val.Status < proto.ValidatorStatus_SLASHED { - valsList = append(valsList, val) - } - } - - return valsList, nil -} - -func (vs *ValidatorStore) GetEarliestActiveValidatorVotedHeight() (uint64, error) { - registeredValidators, err := vs.ListRegisteredValidators() - if err != nil { - return 0, err - } - - if len(registeredValidators) == 0 { - return 0, nil - } - - earliestHeight := uint64(math.MaxUint64) - activeValsCnt := 0 - for _, val := range registeredValidators { - // Note there might be a delay between the validator being active on Babylon - // and this program capturing that. However, given that we only care - // about the `LastVotedHeight` of the validator, other parts of the program - // ensure that when this value is set, the validator is stored as ACTIVE. - // TODO: Another option would be to query here for the - // active status of each validator although this might prove inefficient. - if val.Status != proto.ValidatorStatus_ACTIVE { - continue - } - activeValsCnt += 1 - if earliestHeight > val.LastVotedHeight { - earliestHeight = val.LastVotedHeight - } - } - // If there are no active validators, return 0 - if activeValsCnt == 0 { - return 0, nil - } - return earliestHeight, nil -} - -func (vs *ValidatorStore) Close() error { - if err := vs.s.Close(); err != nil { - return err - } - - return nil -} - -// openStore returns a Store instance with the given db type, path and name -// currently, we only support bbolt -func openStore(dbcfg *valcfg.DatabaseConfig) (store.Store, error) { - switch dbcfg.Backend { - case "bbolt": - return store.NewBboltStore(dbcfg.Path, dbcfg.Name) - default: - return nil, fmt.Errorf("unsupported database type") - } -} diff --git a/val/valstore_test.go b/val/valstore_test.go deleted file mode 100644 index 33cd0ff1..00000000 --- a/val/valstore_test.go +++ /dev/null @@ -1,43 +0,0 @@ -package val_test - -import ( - "math/rand" - "os" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/babylonchain/btc-validator/testutil" - "github.com/babylonchain/btc-validator/val" -) - -// FuzzValidators tests save and list validators properly -func FuzzValidatorStore(f *testing.F) { - testutil.AddRandomSeedsToFuzzer(f, 10) - f.Fuzz(func(t *testing.T, seed int64) { - r := rand.New(rand.NewSource(seed)) - - dbcfg := testutil.GenDBConfig(r, t) - vs, err := val.NewValidatorStore(dbcfg) - require.NoError(t, err) - - defer func() { - err := os.RemoveAll(dbcfg.Path) - require.NoError(t, err) - }() - - validator := testutil.GenRandomValidator(r, t) - err = vs.SaveValidator(validator) - require.NoError(t, err) - - valList, err := vs.ListValidators() - require.NoError(t, err) - require.Equal(t, validator.BabylonPk, valList[0].BabylonPk) - - actualVal, err := vs.GetStoreValidator(validator.BabylonPk) - require.NoError(t, err) - require.Equal(t, validator.BabylonPk, actualVal.BabylonPk) - require.Equal(t, validator.BtcPk, actualVal.BtcPk) - require.Equal(t, validator.KeyName, actualVal.KeyName) - }) -} diff --git a/valcfg/config.go b/valcfg/config.go deleted file mode 100644 index 7bce8982..00000000 --- a/valcfg/config.go +++ /dev/null @@ -1,399 +0,0 @@ -package valcfg - -import ( - "fmt" - "io" - "net" - "os" - "os/user" - "path/filepath" - "strconv" - "strings" - "time" - - "github.com/btcsuite/btcd/btcutil" - "github.com/btcsuite/btcd/chaincfg" - "github.com/jessevdk/go-flags" - "github.com/lightningnetwork/lnd/lncfg" - "github.com/sirupsen/logrus" -) - -const ( - defaultDataDirname = "data" - defaultChainName = "babylon" - defaultLogLevel = "info" - defaultLogDirname = "logs" - defaultLogFilename = "vald.log" - DefaultRPCPort = 15812 - defaultConfigFileName = "vald.conf" - defaultNumPubRand = 100 - defaultNumPubRandMax = 100 - defaultMinRandHeightGap = 10 - defaultRandomInterval = 5 * time.Second - defautlUnbondingSigSubmissionInterval = 20 * time.Second - defaultSubmitRetryInterval = 1 * time.Second - defaultFastSyncInterval = 20 * time.Second - defaultFastSyncLimit = 10 - defaultFastSyncGap = 6 - defaultMaxSubmissionRetries = 20 - defaultBitcoinNetwork = "simnet" -) - -var ( - // C:\Users\\AppData\Local\ on Windows - // ~/.vald on Linux - // ~/Library/Application Support/Vald on MacOS - DefaultValdDir = btcutil.AppDataDir("vald", false) - - DefaultConfigFile = filepath.Join(DefaultValdDir, defaultConfigFileName) - - defaultDataDir = filepath.Join(DefaultValdDir, defaultDataDirname) - defaultLogDir = filepath.Join(DefaultValdDir, defaultLogDirname) - defaultActiveNetParams = chaincfg.SimNetParams -) - -// Config is the main config for the vald cli command -type Config struct { - DebugLevel string `long:"debuglevel" description:"Logging level for all subsystems" choice:"trace" choice:"debug" choice:"info" choice:"warn" choice:"error" choice:"fatal"` - // ChainName and ChainID (if any) of the chain config identify a consumer chain - ChainName string `long:"chainname" description:"the name of the consumer chain" choice:"babylon"` - ValdDir string `long:"validatorddir" description:"The base directory that contains validator's data, logs, configuration file, etc."` - ConfigFile string `long:"configfile" description:"Path to configuration file"` - DataDir string `long:"datadir" description:"The directory to store validator's data within"` - LogDir string `long:"logdir" description:"Directory to log output."` - DumpCfg bool `long:"dumpcfg" description:"If config file does not exist, create it with current settings"` - NumPubRand uint64 `long:"numPubRand" description:"The number of Schnorr public randomness for each commitment"` - NumPubRandMax uint64 `long:"numpubrandmax" description:"The upper bound of the number of Schnorr public randomness for each commitment"` - MinRandHeightGap uint64 `long:"minrandheightgap" description:"The minimum gap between the last committed rand height and the current Babylon block height"` - RandomnessCommitInterval time.Duration `long:"randomnesscommitinterval" description:"The interval between each attempt to commit public randomness"` - SubmissionRetryInterval time.Duration `long:"submissionretryinterval" description:"The interval between each attempt to submit finality signature or public randomness after a failure"` - UnbondingSigSubmissionInterval time.Duration `long:"unbondingsigsubmissioninterval" description:"The interval between each attempt to check and submit unbonding signature"` - MaxSubmissionRetries uint64 `long:"maxsubmissionretries" description:"The maximum number of retries to submit finality signature or public randomness"` - FastSyncInterval time.Duration `long:"fastsyncinterval" description:"The interval between each try of fast sync, which is disabled if the value is 0"` - FastSyncLimit uint64 `long:"fastsynclimit" description:"The maximum number of blocks to catch up for each fast sync"` - FastSyncGap uint64 `long:"fastsyncgap" description:"The block gap that will trigger the fast sync"` - - BitcoinNetwork string `long:"bitcoinnetwork" description:"Bitcoin network to run on" choice:"regtest" choice:"testnet" choice:"simnet" choice:"signet"` - - ActiveNetParams chaincfg.Params - - JuryMode bool `long:"jurymode" description:"If the program is running in Jury mode"` - - PollerConfig *ChainPollerConfig `group:"chainpollerconfig" namespace:"chainpollerconfig"` - - DatabaseConfig *DatabaseConfig `group:"databaseconfig" namespace:"databaserpcconfig"` - - BabylonConfig *BBNConfig `group:"babylon" namespace:"babylon"` - - ValidatorModeConfig *ValidatorConfig `group:"validator" namespace:"validator"` - - JuryModeConfig *JuryConfig `group:"jury" namespace:"jury"` - - GRpcServerConfig *GRpcServerConfig - - RpcListeners []net.Addr -} - -func DefaultConfig() Config { - bbnCfg := DefaultBBNConfig() - dbCfg := DefaultDatabaseConfig() - juryCfg := DefaultJuryConfig() - pollerCfg := DefaultChainPollerConfig() - valCfg := DefaultValidatorConfig() - return Config{ - ValdDir: DefaultValdDir, - ChainName: defaultChainName, - ConfigFile: DefaultConfigFile, - DataDir: defaultDataDir, - DebugLevel: defaultLogLevel, - LogDir: defaultLogDir, - DatabaseConfig: &dbCfg, - BabylonConfig: &bbnCfg, - ValidatorModeConfig: &valCfg, - JuryModeConfig: &juryCfg, - PollerConfig: &pollerCfg, - NumPubRand: defaultNumPubRand, - NumPubRandMax: defaultNumPubRandMax, - MinRandHeightGap: defaultMinRandHeightGap, - RandomnessCommitInterval: defaultRandomInterval, - SubmissionRetryInterval: defaultSubmitRetryInterval, - UnbondingSigSubmissionInterval: defautlUnbondingSigSubmissionInterval, - FastSyncInterval: defaultFastSyncInterval, - FastSyncLimit: defaultFastSyncLimit, - FastSyncGap: defaultFastSyncGap, - MaxSubmissionRetries: defaultMaxSubmissionRetries, - BitcoinNetwork: defaultBitcoinNetwork, - ActiveNetParams: defaultActiveNetParams, - } -} - -// usageError is an error type that signals a problem with the supplied flags. -type usageError struct { - err error -} - -// Error returns the error string. -// -// NOTE: This is part of the error interface. -func (u *usageError) Error() string { - return u.err.Error() -} - -// LoadConfig initializes and parses the config using a config file and command -// line options. -// -// The configuration proceeds as follows: -// 1. Start with a default config with sane settings -// 2. Pre-parse the command line to check for an alternative config file -// 3. Load configuration file overwriting defaults with any specified options -// 4. Parse CLI options and overwrite/add any specified options -func LoadConfig() (*Config, *logrus.Logger, error) { - // Pre-parse the command line options to pick up an alternative config - // file. - preCfg := DefaultConfig() - if _, err := flags.Parse(&preCfg); err != nil { - return nil, nil, err - } - - // Show the version and exit if the version flag was specified. - appName := filepath.Base(os.Args[0]) - appName = strings.TrimSuffix(appName, filepath.Ext(appName)) - usageMessage := fmt.Sprintf("Use %s -h to show usage", appName) - - // If the config file path has not been modified by the user, then - // we'll use the default config file path. However, if the user has - // modified their default dir, then we should assume they intend to use - // the config file within it. - configFileDir := CleanAndExpandPath(preCfg.ValdDir) - configFilePath := CleanAndExpandPath(preCfg.ConfigFile) - switch { - case configFileDir != DefaultValdDir && - configFilePath == DefaultConfigFile: - - configFilePath = filepath.Join( - configFileDir, defaultConfigFileName, - ) - - // User did specify an explicit --configfile, so we check that it does - // exist under that path to avoid surprises. - case configFilePath != DefaultConfigFile: - if !FileExists(configFilePath) { - return nil, nil, fmt.Errorf("specified config file does "+ - "not exist in %s", configFilePath) - } - } - - // Next, load any additional configuration options from the file. - var configFileError error - cfg := preCfg - fileParser := flags.NewParser(&cfg, flags.Default) - err := flags.NewIniParser(fileParser).ParseFile(configFilePath) - if err != nil { - // If it's a parsing related error, then we'll return - // immediately, otherwise we can proceed as possibly the config - // file doesn't exist which is OK. - if _, ok := err.(*flags.IniError); ok { - return nil, nil, err - } - - configFileError = err - } - - // Finally, parse the remaining command line options again to ensure - // they take precedence. - flagParser := flags.NewParser(&cfg, flags.Default) - if _, err := flagParser.Parse(); err != nil { - return nil, nil, err - } - - cfgLogger := logrus.New() - cfgLogger.Out = os.Stdout - // Make sure everything we just loaded makes sense. - cleanCfg, err := ValidateConfig(cfg) - if err != nil { - // Log help message in case of usage error. - if _, ok := err.(*usageError); ok { - cfgLogger.Warnf("Incorrect usage: %v", usageMessage) - } - - cfgLogger.Warnf("Error validating config: %v", err) - return nil, nil, err - } - - // ignore error here as we already validated the value - logRuslLevel, _ := logrus.ParseLevel(cleanCfg.DebugLevel) - - // TODO: Add log rotation - // At this point we know config is valid, create logger which also log to file - logFilePath := filepath.Join(cleanCfg.LogDir, defaultLogFilename) - f, err := os.OpenFile(logFilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) - if err != nil { - return nil, nil, err - } - mw := io.MultiWriter(os.Stdout, f) - - cfgLogger.Out = mw - cfgLogger.Level = logRuslLevel - - // Warn about missing config file only after all other configuration is - // done. This prevents the warning on help messages and invalid - // options. Note this should go directly before the return. - if configFileError != nil { - cfgLogger.Warnf("%v", configFileError) - if cleanCfg.DumpCfg { - cfgLogger.Infof("Writing configuration file to %s", configFilePath) - fileParser := flags.NewParser(&cfg, flags.Default) - err := flags.NewIniParser(fileParser).WriteFile(configFilePath, flags.IniIncludeComments|flags.IniIncludeDefaults) - if err != nil { - cfgLogger.Warnf("Error writing configuration file: %v", err) - return nil, nil, err - } - } - } - - return cleanCfg, cfgLogger, nil -} - -// ValidateConfig check the given configuration to be sane. This makes sure no -// illegal values or combination of values are set. All file system paths are -// normalized. The cleaned up config is returned on success. -func ValidateConfig(cfg Config) (*Config, error) { - // If the provided stakerd directory is not the default, we'll modify the - // path to all the files and directories that will live within it. - valdDir := CleanAndExpandPath(cfg.ValdDir) - if valdDir != DefaultValdDir { - cfg.DataDir = filepath.Join(valdDir, defaultDataDirname) - cfg.LogDir = filepath.Join(valdDir, defaultLogDirname) - } - - funcName := "ValidateConfig" - mkErr := func(format string, args ...interface{}) error { - return fmt.Errorf(funcName+": "+format, args...) - } - makeDirectory := func(dir string) error { - err := os.MkdirAll(dir, 0700) - if err != nil { - // Show a nicer error message if it's because a symlink - // is linked to a directory that does not exist - // (probably because it's not mounted). - if e, ok := err.(*os.PathError); ok && os.IsExist(err) { - link, lerr := os.Readlink(e.Path) - if lerr == nil { - str := "is symlink %s -> %s mounted?" - err = fmt.Errorf(str, e.Path, link) - } - } - - str := "Failed to create vald directory '%s': %v" - return mkErr(str, dir, err) - } - - return nil - } - - // As soon as we're done parsing configuration options, ensure all - // paths to directories and files are cleaned and expanded before - // attempting to use them later on. - cfg.DataDir = CleanAndExpandPath(cfg.DataDir) - cfg.LogDir = CleanAndExpandPath(cfg.LogDir) - - // Multiple networks can't be selected simultaneously. Count number of - // network flags passed; assign active network params - // while we're at it. - - switch cfg.BitcoinNetwork { - case "testnet": - cfg.ActiveNetParams = chaincfg.TestNet3Params - case "regtest": - cfg.ActiveNetParams = chaincfg.RegressionNetParams - case "simnet": - cfg.ActiveNetParams = chaincfg.SimNetParams - case "signet": - cfg.ActiveNetParams = chaincfg.SigNetParams - default: - return nil, mkErr(fmt.Sprintf("invalid network: %v", - cfg.BitcoinNetwork)) - } - - // Create the vald directory and all other subdirectories if they - // don't already exist. This makes sure that directory trees are also - // created for files that point to outside the vald dir. - dirs := []string{ - valdDir, cfg.DataDir, cfg.LogDir, - } - for _, dir := range dirs { - if err := makeDirectory(dir); err != nil { - return nil, err - } - } - - // At least one RPCListener is required. So listen on localhost per - // default. - if len(cfg.GRpcServerConfig.RawRPCListeners) == 0 { - addr := fmt.Sprintf("localhost:%d", DefaultRPCPort) - cfg.GRpcServerConfig.RawRPCListeners = append( - cfg.GRpcServerConfig.RawRPCListeners, addr, - ) - } - - _, err := logrus.ParseLevel(cfg.DebugLevel) - - if err != nil { - return nil, mkErr("error parsing debuglevel: %v", err) - } - - // Add default port to all RPC listener addresses if needed and remove - // duplicate addresses. - cfg.RpcListeners, err = lncfg.NormalizeAddresses( - cfg.GRpcServerConfig.RawRPCListeners, strconv.Itoa(DefaultRPCPort), - net.ResolveTCPAddr, - ) - - if err != nil { - return nil, mkErr("error normalizing RPC listen addrs: %v", err) - } - - // All good, return the sanitized result. - return &cfg, nil -} - -// FileExists reports whether the named file or directory exists. -// This function is taken from https://github.com/btcsuite/btcd -func FileExists(name string) bool { - if _, err := os.Stat(name); err != nil { - if os.IsNotExist(err) { - return false - } - } - return true -} - -// CleanAndExpandPath expands environment variables and leading ~ in the -// passed path, cleans the result, and returns it. -// This function is taken from https://github.com/btcsuite/btcd -func CleanAndExpandPath(path string) string { - if path == "" { - return "" - } - - // Expand initial ~ to OS specific home directory. - if strings.HasPrefix(path, "~") { - var homeDir string - u, err := user.Current() - if err == nil { - homeDir = u.HomeDir - } else { - homeDir = os.Getenv("HOME") - } - - path = strings.Replace(path, "~", homeDir, 1) - } - - // NOTE: The os.ExpandEnv doesn't work with Windows-style %VARIABLE%, - // but the variables can still be expanded via POSIX-style $VARIABLE. - return filepath.Clean(os.ExpandEnv(path)) -} - -type GRpcServerConfig struct { - RawRPCListeners []string `long:"rpclisten" description:"Add an interface/port/socket to listen for RPC connections"` -} diff --git a/valcfg/jury.go b/valcfg/jury.go deleted file mode 100644 index 462d6605..00000000 --- a/valcfg/jury.go +++ /dev/null @@ -1,22 +0,0 @@ -package valcfg - -import ( - "time" -) - -var ( - defaultJuryKeyName = "jury-key" - defaultQueryInterval = 15 * time.Second -) - -type JuryConfig struct { - JuryKeyName string `long:"jurykeyname" description:"The key name of the Jury if the program is running in Jury mode"` - QueryInterval time.Duration `long:"queryinterval" description:"The interval between each query for pending BTC delegations"` -} - -func DefaultJuryConfig() JuryConfig { - return JuryConfig{ - JuryKeyName: defaultJuryKeyName, - QueryInterval: defaultQueryInterval, - } -} diff --git a/valcfg/poller.go b/valcfg/poller.go deleted file mode 100644 index ecefaf31..00000000 --- a/valcfg/poller.go +++ /dev/null @@ -1,20 +0,0 @@ -package valcfg - -import "time" - -var ( - defaultBufferSize = uint32(1000) - defaultPollingInterval = 5 * time.Second -) - -type ChainPollerConfig struct { - BufferSize uint32 `long:"buffersize" description:"The maximum number of Babylon blocks that can be stored in the buffer"` - PollInterval time.Duration `long:"pollinterval" description:"The interval between each polling of Babylon blocks"` -} - -func DefaultChainPollerConfig() ChainPollerConfig { - return ChainPollerConfig{ - BufferSize: defaultBufferSize, - PollInterval: defaultPollingInterval, - } -} diff --git a/valcfg/validator.go b/valcfg/validator.go deleted file mode 100644 index c9470af7..00000000 --- a/valcfg/validator.go +++ /dev/null @@ -1,13 +0,0 @@ -package valcfg - -type ValidatorConfig struct { - StaticChainScanningStartHeight uint64 `long:"staticchainscanningstartheight" description:"The static height from which we start polling the chain"` - AutoChainScanningMode bool `long:"autochainscanningmode" description:"Automatically discover the height from which to start polling the chain"` -} - -func DefaultValidatorConfig() ValidatorConfig { - return ValidatorConfig{ - StaticChainScanningStartHeight: 1, - AutoChainScanningMode: true, - } -} diff --git a/version/version.go b/version/version.go index ca3888d5..17f641b9 100644 --- a/version/version.go +++ b/version/version.go @@ -52,17 +52,17 @@ const ( // defaultAgentName is the default name of the software that is added as // the first part of the user agent string. - defaultAgentName = "vald" + defaultAgentName = "fpd" ) // agentName stores the name of the software that is added as the first part of -// the user agent string. This defaults to the value "vald" when being run as -// a standalone component but can be overwritten by LiT for example when vald +// the user agent string. This defaults to the value "fpd" when being run as +// a standalone component but can be overwritten by LiT for example when fpd // is integrated into the UI. var agentName = defaultAgentName // SetAgentName overwrites the default agent name which can be used to identify -// the software vald is bundled in (for example LiT). This function panics if +// the software fpd is bundled in (for example LiT). This function panics if // the agent name contains characters outside of the allowed semantic alphabet. func SetAgentName(newAgentName string) { for _, r := range newAgentName {