diff --git a/.github/workflows/check-generated.yml b/.github/workflows/check-generated.yml new file mode 100644 index 000000000..c27e132aa --- /dev/null +++ b/.github/workflows/check-generated.yml @@ -0,0 +1,75 @@ +# Verify that generated code is up-to-date. +# +# Note that we run these checks regardless whether the input files have +# changed, because generated code can change in response to toolchain updates +# even if no files in the repository are modified. +name: Check generated code +on: + pull_request: + branches: + - main + +permissions: + contents: read + +jobs: + check-mocks: + runs-on: ubuntu-latest + steps: + - uses: actions/setup-go@v3 + with: + go-version: '1.18' + + - uses: actions/checkout@v3 + + - name: "Check generated mocks" + run: | + set -euo pipefail + + readonly MOCKERY=2.30.18 # N.B. no leading "v" + curl -sL "https://github.com/vektra/mockery/releases/download/v${MOCKERY}/mockery_${MOCKERY}_Linux_x86_64.tar.gz" | tar -C /usr/local/bin -xzf - + make mockery 2>/dev/null + + if ! git diff --stat --exit-code ; then + echo ">> ERROR:" + echo ">>" + echo ">> Generated mocks require update (either Mockery or source files may have changed)." + echo ">> Ensure your tools are up-to-date, re-run 'make mockery' and update this PR." + echo ">>" + exit 1 + fi + + check-proto: + runs-on: ubuntu-latest + steps: + - uses: actions/setup-go@v3 + with: + go-version: '1.18' + + - uses: actions/checkout@v3 + with: + fetch-depth: 1 # we need a .git directory to run git diff + + - name: "Check protobuf generated code" + run: | + set -euo pipefail + + # Install buf and gogo tools, so that differences that arise from + # toolchain differences are also caught. + readonly tools="$(mktemp -d)" + export PATH="${PATH}:${tools}/bin" + export GOBIN="${tools}/bin" + + go install github.com/bufbuild/buf/cmd/buf + go install github.com/gogo/protobuf/protoc-gen-gogofaster@latest + + make proto-gen + + if ! git diff --stat --exit-code ; then + echo ">> ERROR:" + echo ">>" + echo ">> Protobuf generated code requires update (either tools or .proto files may have changed)." + echo ">> Ensure your tools are up-to-date, re-run 'make proto-gen' and update this PR." + echo ">>" + exit 1 + fi diff --git a/.github/workflows/proto-docker.yml b/.github/workflows/proto-docker.yml deleted file mode 100644 index 59b4a98ac..000000000 --- a/.github/workflows/proto-docker.yml +++ /dev/null @@ -1,58 +0,0 @@ -name: Build & Push OC Proto Builder -on: - pull_request: - paths: - - "tools/proto/*" - push: - branches: - - main - paths: - - "tools/proto/*" - schedule: - # run this job once a month to recieve any go or buf updates - - cron: "* * 1 * *" - -jobs: - build-proto: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Prepare - id: prep - run: | - DOCKER_IMAGE=ostracondev/docker-build-proto - VERSION=noop - if [[ $GITHUB_REF == refs/tags/* ]]; then - VERSION=${GITHUB_REF#refs/tags/} - elif [[ $GITHUB_REF == refs/heads/* ]]; then - VERSION=$(echo ${GITHUB_REF#refs/heads/} | sed -r 's#/+#-#g') - DEFAULT_BRANCH=$(curl -s -H "Accept: application/vnd.github.v3+json" \ - https://api.github.com/repos/Finschia/ostracon | \ - grep default_branch | \ - cut -d"\"" -f4) - if [ "$DEFAULT_BRANCH" = "$VERSION" ]; then - VERSION=latest - fi - fi - TAGS="${DOCKER_IMAGE}:${VERSION}" - if [[ $VERSION =~ ^v[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then - TAGS="$TAGS,${DOCKER_IMAGE}:${VERSION%.*}" - fi - echo "tags=${TAGS}" >> $GITHUB_OUTPUT - -# - name: Set up Docker Buildx -# uses: docker/setup-buildx-action@v1.3.0 - -# - name: Login to DockerHub -# uses: docker/login-action@v1 -# with: -# username: ${{ secrets.DOCKERHUB_USERNAME }} -# password: ${{ secrets.DOCKERHUB_TOKEN }} - -# - name: Publish to Docker Hub -# uses: docker/build-push-action@v2.4.0 -# with: -# context: ./tools/proto -# file: ./tools/proto/Dockerfile -# push: ${{ github.event_name != 'pull_request' }} -# tags: ${{ steps.prep.outputs.tags }} diff --git a/.github/workflows/proto-lint.yml b/.github/workflows/proto-lint.yml new file mode 100644 index 000000000..bab9227fc --- /dev/null +++ b/.github/workflows/proto-lint.yml @@ -0,0 +1,19 @@ +name: Protobuf Lint +on: + pull_request: + paths: + - 'proto/**' + push: + paths: + - 'proto/**' + +jobs: + lint: + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - uses: actions/checkout@v3 + - uses: bufbuild/buf-setup-action@v1.5.0 + - uses: bufbuild/buf-lint-action@v1 + with: + input: 'proto' diff --git a/.github/workflows/proto.yml b/.github/workflows/proto.yml deleted file mode 100644 index f2bcb4c08..000000000 --- a/.github/workflows/proto.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: Protobuf -# Protobuf runs buf (https://buf.build/) lint and check-breakage -# This workflow is only run when a .proto file has been modified -on: - pull_request: - paths: - - "**.proto" -jobs: - proto-lint: - runs-on: ubuntu-latest - timeout-minutes: 4 - steps: - - uses: actions/checkout@v3 - - name: lint - run: make proto-lint -# proto-breakage: -# runs-on: ubuntu-latest -# timeout-minutes: 4 -# steps: -# - uses: actions/checkout@v3 -# - name: check-breakage -# run: make proto-check-breaking-ci diff --git a/Makefile b/Makefile index b4ddd1255..1ac98032b 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,6 @@ VERSION := $(shell git describe --always) LD_FLAGS = -X github.com/Finschia/ostracon/version.OCCoreSemVer=$(VERSION) BUILD_FLAGS = -mod=readonly -ldflags "$(LD_FLAGS)" HTTPS_GIT := https://github.com/Finschia/ostracon.git -DOCKER_BUF := docker run -v $(shell pwd):/workspace --workdir /workspace bufbuild/buf CGO_ENABLED ?= 0 TARGET_OS ?= $(shell go env GOOS) TARGET_ARCH ?= $(shell go env GOARCH) @@ -77,42 +76,48 @@ mockery: ### Protobuf ### ############################################################################### -containerProtoVer=v0.2 -containerProtoImage=tendermintdev/sdk-proto-gen:$(containerProtoVer) - -### -# https://github.com/protocolbuffers/protobuf -# https://developers.google.com/protocol-buffers/docs/gotutorial -# Should install -### go install -# go install google.golang.org/protobuf/cmd/protoc-gen-go -### Docker for Protocol Buffer -# https://hub.docker.com/r/bufbuild/buf +check-proto-deps: +ifeq (,$(shell which protoc-gen-gogofaster)) + @go install github.com/gogo/protobuf/protoc-gen-gogofaster@latest +endif +.PHONY: check-proto-deps -proto-all: proto-gen proto-lint proto-check-breaking -.PHONY: proto-all +check-proto-format-deps: +ifeq (,$(shell which clang-format)) + $(error "clang-format is required for Protobuf formatting. See instructions for your platform on how to install it.") +endif +.PHONY: check-proto-format-deps -proto-gen: - @docker pull -q tendermintdev/docker-build-proto +proto-gen: check-proto-deps @echo "Generating Protobuf files" - @docker run --rm -v $(shell pwd):/workspace --workdir /workspace $(containerProtoImage) sh ./scripts/protocgen.sh + @go run github.com/bufbuild/buf/cmd/buf generate + @mv ./proto/ostracon/abci/types.pb.go ./abci/types/ + @mv ./proto/ostracon/rpc/grpc/types.pb.go ./rpc/grpc/ + @rm -rf ./proto/tendermint .PHONY: proto-gen -proto-lint: - @$(DOCKER_BUF) lint --error-format=json +# These targets are provided for convenience and are intended for local +# execution only. +proto-lint: check-proto-deps + @echo "Linting Protobuf files" + @go run github.com/bufbuild/buf/cmd/buf lint .PHONY: proto-lint -proto-format: +proto-format: check-proto-format-deps @echo "Formatting Protobuf files" - docker run --rm -v $(shell pwd):/workspace --workdir /workspace tendermintdev/docker-build-proto find ./ -not -path "./third_party/*" -name *.proto -exec clang-format -i {} \; + @find . -name '*.proto' -path "./proto/*" -exec clang-format -i {} \; .PHONY: proto-format -proto-check-breaking: - @$(DOCKER_BUF) breaking --against .git#branch=main +proto-check-breaking: check-proto-deps + @echo "Checking for breaking changes in Protobuf files against local branch" + @echo "Note: This is only useful if your changes have not yet been committed." + @echo " Otherwise read up on buf's \"breaking\" command usage:" + @echo " https://docs.buf.build/breaking/usage" + @go run github.com/bufbuild/buf/cmd/buf breaking --against ".git" .PHONY: proto-check-breaking proto-check-breaking-ci: - @$(DOCKER_BUF) breaking --against $(HTTPS_GIT)#branch=main + @go run github.com/bufbuild/buf/cmd/buf breaking --against ".git"#branch=main .PHONY: proto-check-breaking-ci ############################################################################### diff --git a/abci/client/grpc_client.go b/abci/client/grpc_client.go index fca631967..d6f760196 100644 --- a/abci/client/grpc_client.go +++ b/abci/client/grpc_client.go @@ -310,6 +310,7 @@ func (cli *grpcClient) finishAsyncCall(req *ocabci.Request, res *ocabci.Response } // ---------------------------------------- + func (cli *grpcClient) FlushSync() (*types.ResponseFlush, error) { reqres := cli.FlushAsync(nil) reqres.Wait() diff --git a/abci/client/mocks/client.go b/abci/client/mocks/client.go index 80b379c0e..67094538c 100644 --- a/abci/client/mocks/client.go +++ b/abci/client/mocks/client.go @@ -891,13 +891,12 @@ func (_m *Client) String() string { return r0 } -type mockConstructorTestingTNewClient interface { +// NewClient creates a new instance of Client. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewClient(t interface { mock.TestingT Cleanup(func()) -} - -// NewClient creates a new instance of Client. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewClient(t mockConstructorTestingTNewClient) *Client { +}) *Client { mock := &Client{} mock.Mock.Test(t) diff --git a/abci/types/mocks/application.go b/abci/types/mocks/application.go index 155f44eef..462f8ac95 100644 --- a/abci/types/mocks/application.go +++ b/abci/types/mocks/application.go @@ -229,13 +229,12 @@ func (_m *Application) SetOption(_a0 types.RequestSetOption) types.ResponseSetOp return r0 } -type mockConstructorTestingTNewApplication interface { +// NewApplication creates a new instance of Application. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewApplication(t interface { mock.TestingT Cleanup(func()) -} - -// NewApplication creates a new instance of Application. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewApplication(t mockConstructorTestingTNewApplication) *Application { +}) *Application { mock := &Application{} mock.Mock.Test(t) diff --git a/abci/types/types.pb.go b/abci/types/types.pb.go index d6fd799b9..e0b28e831 100644 --- a/abci/types/types.pb.go +++ b/abci/types/types.pb.go @@ -9,9 +9,7 @@ import ( types2 "github.com/Finschia/ostracon/proto/ostracon/types" _ "github.com/gogo/protobuf/gogoproto" proto "github.com/gogo/protobuf/proto" - _ "github.com/gogo/protobuf/types" types "github.com/tendermint/tendermint/abci/types" - _ "github.com/tendermint/tendermint/proto/tendermint/crypto" types1 "github.com/tendermint/tendermint/proto/tendermint/types" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" @@ -998,99 +996,95 @@ func init() { func init() { proto.RegisterFile("ostracon/abci/types.proto", fileDescriptor_addf585b2317eb36) } var fileDescriptor_addf585b2317eb36 = []byte{ - // 1457 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x98, 0x4b, 0x8f, 0xdb, 0x54, - 0x14, 0xc7, 0x33, 0x4d, 0x26, 0x19, 0x9f, 0xc9, 0xa4, 0xd3, 0xd3, 0xa1, 0xb8, 0x66, 0x9a, 0x29, - 0x29, 0x85, 0x52, 0xca, 0x44, 0x9a, 0x8a, 0xaa, 0x08, 0x24, 0x68, 0xc2, 0x8c, 0x32, 0x50, 0x11, - 0xf5, 0x16, 0x81, 0xc4, 0xa3, 0x91, 0x63, 0xdf, 0x24, 0x66, 0x1c, 0x5f, 0xd7, 0xbe, 0x19, 0x1a, - 0xf6, 0xec, 0xf9, 0x26, 0x2c, 0xd9, 0xb1, 0xee, 0xb2, 0x4b, 0x16, 0xa8, 0x42, 0xed, 0x06, 0xf8, - 0x14, 0xe8, 0x5e, 0x3f, 0xea, 0x3c, 0x1c, 0x7b, 0x76, 0xf7, 0x71, 0xce, 0xdf, 0xf7, 0x5c, 0x1f, - 0x9f, 0x5f, 0x4e, 0xe0, 0x32, 0xf3, 0xb9, 0xa7, 0x1b, 0xcc, 0x69, 0xea, 0x7d, 0xc3, 0x6a, 0xf2, - 0xa9, 0x4b, 0xfd, 0x7d, 0xd7, 0x63, 0x9c, 0xe1, 0x56, 0xb4, 0xb5, 0x2f, 0xb6, 0xb4, 0x2b, 0x9c, - 0x3a, 0x26, 0xf5, 0xc6, 0x96, 0xc3, 0x9b, 0x86, 0x37, 0x75, 0x39, 0x6b, 0xba, 0x1e, 0x63, 0x83, - 0xc0, 0x7a, 0x66, 0x5b, 0xaa, 0x34, 0x5d, 0xdd, 0xd3, 0xc7, 0xa1, 0x98, 0xf6, 0x46, 0x62, 0x7b, - 0xfe, 0x49, 0xda, 0xee, 0x82, 0x6f, 0x72, 0x57, 0x8b, 0x8f, 0xb8, 0xb8, 0xb7, 0xbb, 0x78, 0xa8, - 0x13, 0x3a, 0x8d, 0x76, 0xf7, 0x86, 0x8c, 0x0d, 0x6d, 0xda, 0x94, 0xb3, 0xfe, 0x64, 0xd0, 0xe4, - 0xd6, 0x98, 0xfa, 0x5c, 0x1f, 0xbb, 0xa1, 0xc1, 0xce, 0x90, 0x0d, 0x99, 0x1c, 0x36, 0xc5, 0x28, - 0x58, 0x6d, 0xfc, 0xa6, 0x40, 0x85, 0xd0, 0xc7, 0x13, 0xea, 0x73, 0x3c, 0x80, 0x12, 0x35, 0x46, - 0x4c, 0x5d, 0xbb, 0xba, 0x76, 0x63, 0xf3, 0x60, 0x77, 0xff, 0xd5, 0xf3, 0xe4, 0xad, 0xec, 0x87, - 0x76, 0x87, 0xc6, 0x88, 0x75, 0x0a, 0x44, 0xda, 0xe2, 0x07, 0xb0, 0x3e, 0xb0, 0x27, 0xfe, 0x48, - 0x3d, 0x27, 0x9d, 0xae, 0xa4, 0x39, 0x1d, 0x09, 0xa3, 0x4e, 0x81, 0x04, 0xd6, 0xe2, 0x51, 0x96, - 0x33, 0x60, 0x6a, 0x71, 0xf5, 0xa3, 0x8e, 0x9d, 0x81, 0x7c, 0x94, 0xb0, 0xc5, 0x16, 0x80, 0x4f, - 0x79, 0x8f, 0xb9, 0xdc, 0x62, 0x8e, 0x5a, 0x92, 0x9e, 0x6f, 0xa6, 0x79, 0x3e, 0xa4, 0xbc, 0x2b, - 0x0d, 0x3b, 0x05, 0xa2, 0xf8, 0xd1, 0x44, 0x68, 0x58, 0x8e, 0xc5, 0x7b, 0xc6, 0x48, 0xb7, 0x1c, - 0x75, 0x7d, 0xb5, 0xc6, 0xb1, 0x63, 0xf1, 0xb6, 0x30, 0x14, 0x1a, 0x56, 0x34, 0x11, 0x21, 0x3f, - 0x9e, 0x50, 0x6f, 0xaa, 0x96, 0x57, 0x87, 0xfc, 0x40, 0x18, 0x89, 0x90, 0xa5, 0x35, 0xb6, 0x61, - 0xb3, 0x4f, 0x87, 0x96, 0xd3, 0xeb, 0xdb, 0xcc, 0x38, 0x51, 0x2b, 0xd2, 0xf9, 0xea, 0xfe, 0x4c, - 0xe2, 0x45, 0xae, 0x2d, 0x61, 0xd8, 0x12, 0x76, 0x9d, 0x02, 0x81, 0x7e, 0x3c, 0xc3, 0x8f, 0x61, - 0xc3, 0x18, 0x51, 0xe3, 0xa4, 0xc7, 0x9f, 0xa8, 0x1b, 0x52, 0x61, 0x2f, 0xed, 0xf1, 0x6d, 0x61, - 0xf7, 0xd5, 0x93, 0x4e, 0x81, 0x54, 0x8c, 0x60, 0x28, 0xa2, 0x37, 0xa9, 0x6d, 0x9d, 0x52, 0x4f, - 0xf8, 0x2b, 0xab, 0xa3, 0xff, 0x2c, 0xb0, 0x94, 0x0a, 0x8a, 0x19, 0x4d, 0xf0, 0x13, 0x50, 0xa8, - 0x63, 0x86, 0x41, 0x40, 0x18, 0x44, 0x5a, 0xa6, 0x38, 0x66, 0x14, 0xc4, 0x06, 0x0d, 0xc7, 0x78, - 0x17, 0xca, 0x06, 0x1b, 0x8f, 0x2d, 0xae, 0x6e, 0x4a, 0xef, 0x7a, 0x6a, 0x00, 0xd2, 0xaa, 0x53, - 0x20, 0xa1, 0x3d, 0x7e, 0x09, 0x35, 0xdb, 0xf2, 0x79, 0xcf, 0x77, 0x74, 0xd7, 0x1f, 0x31, 0xee, - 0xab, 0x55, 0xa9, 0x70, 0x3d, 0x4d, 0xe1, 0xbe, 0xe5, 0xf3, 0x87, 0x91, 0x71, 0xa7, 0x40, 0xb6, - 0xec, 0xe4, 0x82, 0xd0, 0x63, 0x83, 0x01, 0xf5, 0x62, 0x41, 0x75, 0x6b, 0xb5, 0x5e, 0x57, 0x58, - 0x47, 0xfe, 0x42, 0x8f, 0x25, 0x17, 0xf0, 0x3b, 0xb8, 0x68, 0x33, 0xdd, 0x8c, 0xe5, 0x7a, 0xc6, - 0x68, 0xe2, 0x9c, 0xa8, 0x35, 0x29, 0xfa, 0x6e, 0xea, 0x21, 0x99, 0x6e, 0x46, 0x12, 0x6d, 0xe1, - 0xd0, 0x29, 0x90, 0x0b, 0xf6, 0xfc, 0x22, 0x3e, 0x82, 0x1d, 0xdd, 0x75, 0xed, 0xe9, 0xbc, 0xfa, - 0x79, 0xa9, 0x7e, 0x33, 0x4d, 0xfd, 0x9e, 0xf0, 0x99, 0x97, 0x47, 0x7d, 0x61, 0x15, 0x1f, 0xc0, - 0x76, 0x90, 0x9e, 0x1e, 0x8d, 0x33, 0xec, 0x9f, 0x20, 0x49, 0xdf, 0x5a, 0x91, 0xa4, 0x84, 0x1a, - 0x71, 0x9e, 0xd5, 0xfa, 0x33, 0x2b, 0xf8, 0x05, 0xd4, 0x44, 0xaa, 0x24, 0x04, 0xff, 0x0d, 0x04, - 0x1b, 0xcb, 0x05, 0x0f, 0x1d, 0x33, 0x29, 0x57, 0xa5, 0x89, 0x79, 0xab, 0x02, 0xeb, 0xa7, 0xba, - 0x3d, 0xa1, 0x8d, 0x3f, 0xce, 0xc1, 0x85, 0x85, 0xcf, 0x04, 0x11, 0x4a, 0x23, 0xdd, 0x1f, 0xc9, - 0xda, 0x55, 0x25, 0x72, 0x8c, 0x77, 0xa0, 0x3c, 0xa2, 0xba, 0x49, 0xbd, 0xb0, 0x38, 0xa9, 0xc9, - 0x4b, 0x0a, 0x2a, 0x6b, 0x47, 0xee, 0xb7, 0x4a, 0x4f, 0x9f, 0xef, 0x15, 0x48, 0x68, 0x8d, 0x5d, - 0xd8, 0xb6, 0x75, 0x9f, 0xf7, 0x82, 0xb4, 0xeb, 0x25, 0x0a, 0xd5, 0xe2, 0xc7, 0x76, 0x5f, 0x8f, - 0x12, 0x55, 0xd4, 0xaa, 0x50, 0xa8, 0x66, 0xcf, 0xac, 0x22, 0x81, 0x9d, 0xfe, 0xf4, 0x67, 0xdd, - 0xe1, 0x96, 0x43, 0x7b, 0xa7, 0xba, 0x6d, 0x99, 0x3a, 0x67, 0x9e, 0xaf, 0x96, 0xae, 0x16, 0x6f, - 0x6c, 0x1e, 0x5c, 0x5e, 0x10, 0x3d, 0x3c, 0xb5, 0x4c, 0xea, 0x18, 0x34, 0x94, 0xbb, 0x18, 0x3b, - 0x7f, 0x1d, 0xfb, 0xe2, 0x5d, 0xa8, 0x50, 0x87, 0x7b, 0xcc, 0x9d, 0x46, 0xaf, 0xe9, 0xf5, 0x57, - 0xb7, 0x1a, 0x04, 0x77, 0x18, 0xec, 0x87, 0x2a, 0x91, 0x79, 0xa3, 0x0b, 0xaf, 0x2d, 0x7d, 0x83, - 0x89, 0xfb, 0x5a, 0x3b, 0xcb, 0x7d, 0x35, 0xde, 0x87, 0x8b, 0x4b, 0xde, 0x20, 0x5e, 0x12, 0x72, - 0xd6, 0x70, 0xc4, 0xa5, 0x5c, 0x91, 0x84, 0xb3, 0xc6, 0x2f, 0x00, 0x1b, 0x84, 0xfa, 0x2e, 0x73, - 0x7c, 0x8a, 0x2d, 0x50, 0xe8, 0x13, 0x83, 0x06, 0x35, 0x7d, 0x2d, 0xcc, 0x8e, 0xc5, 0x5c, 0x0e, - 0xac, 0x0f, 0x23, 0x4b, 0x51, 0x92, 0x62, 0x37, 0xbc, 0x1d, 0x72, 0x2b, 0x1d, 0x41, 0xa1, 0x7b, - 0x12, 0x5c, 0x77, 0x22, 0x70, 0x15, 0x53, 0xab, 0x50, 0xe0, 0x35, 0x47, 0xae, 0xdb, 0x21, 0xb9, - 0x4a, 0x19, 0x0f, 0x9b, 0x41, 0x57, 0x7b, 0x06, 0x5d, 0xeb, 0x19, 0x61, 0xa6, 0xb0, 0xab, 0x3d, - 0xc3, 0xae, 0x72, 0x86, 0x48, 0x0a, 0xbc, 0xee, 0x44, 0xf0, 0xaa, 0x64, 0x84, 0x3d, 0x47, 0xaf, - 0xa3, 0x59, 0x7a, 0x05, 0xec, 0xb9, 0x96, 0xea, 0x9d, 0x0a, 0xb0, 0x8f, 0x12, 0x00, 0x53, 0xc2, - 0x23, 0xcc, 0x17, 0x83, 0x40, 0x62, 0x09, 0xbf, 0xda, 0x33, 0xfc, 0x82, 0x8c, 0x1b, 0x48, 0x01, - 0xd8, 0xa7, 0x49, 0x80, 0x6d, 0xa6, 0x32, 0x30, 0x4c, 0x99, 0x65, 0x04, 0xfb, 0x30, 0x26, 0x58, - 0x35, 0x15, 0xc1, 0x61, 0x0c, 0xf3, 0x08, 0xeb, 0x2e, 0x20, 0x2c, 0x40, 0xce, 0xdb, 0xa9, 0x12, - 0x19, 0x0c, 0xeb, 0x2e, 0x30, 0xac, 0x96, 0x21, 0x98, 0x01, 0xb1, 0xef, 0x97, 0x43, 0x2c, 0x1d, - 0x33, 0xe1, 0x31, 0xf3, 0x51, 0xac, 0x97, 0x42, 0xb1, 0x6d, 0x29, 0xff, 0x5e, 0xaa, 0x7c, 0x6e, - 0x8c, 0x91, 0x74, 0x8c, 0x5d, 0x4f, 0x49, 0xb4, 0x4c, 0x8e, 0xdd, 0x4f, 0xe3, 0xd8, 0xb5, 0x14, - 0xc5, 0x7c, 0x20, 0xfb, 0xeb, 0x1c, 0x9c, 0x9f, 0x4b, 0x76, 0x81, 0x31, 0x83, 0x99, 0x54, 0x56, - 0xc2, 0x2d, 0x22, 0xc7, 0x62, 0xcd, 0xd4, 0xb9, 0x2e, 0xcb, 0x5b, 0x95, 0xc8, 0x31, 0x6e, 0x43, - 0xd1, 0x66, 0x43, 0x59, 0xbb, 0x14, 0x22, 0x86, 0xc2, 0x2a, 0xae, 0x4b, 0x4a, 0x58, 0x76, 0xea, - 0x00, 0x43, 0xdd, 0xef, 0xfd, 0xa4, 0x3b, 0x9c, 0x9a, 0xb2, 0xec, 0x14, 0x49, 0x62, 0x05, 0x35, - 0xd8, 0x10, 0xb3, 0x89, 0x4f, 0x4d, 0x59, 0x4f, 0x8a, 0x24, 0x9e, 0x63, 0x07, 0xca, 0xf4, 0x94, - 0x3a, 0xdc, 0x57, 0x2b, 0x92, 0x52, 0x97, 0x96, 0x50, 0x8a, 0x3a, 0xbc, 0xa5, 0x0a, 0x14, 0xfc, - 0xf7, 0x7c, 0x6f, 0x3b, 0xb0, 0xbe, 0xc5, 0xc6, 0x16, 0xa7, 0x63, 0x97, 0x4f, 0x49, 0xe8, 0x8f, - 0xbb, 0xa0, 0x88, 0x38, 0x7c, 0x57, 0x37, 0xa8, 0x2c, 0x1c, 0x0a, 0x79, 0xb5, 0x20, 0x28, 0xe1, - 0x4b, 0x61, 0x59, 0x0e, 0x14, 0x12, 0xce, 0xc4, 0xd9, 0x5c, 0xcf, 0x62, 0x9e, 0xc5, 0xa7, 0xf2, - 0x4b, 0x2f, 0x92, 0x78, 0x8e, 0xd7, 0x60, 0x6b, 0x4c, 0xc7, 0x2e, 0x63, 0x76, 0x8f, 0x7a, 0x1e, - 0xf3, 0xe4, 0x67, 0xac, 0x90, 0x6a, 0xb8, 0x78, 0x28, 0xd6, 0x1a, 0xb7, 0xe0, 0xd2, 0xf2, 0x37, - 0xbc, 0xec, 0x92, 0x1b, 0x37, 0x61, 0x67, 0xd9, 0xdb, 0x5b, 0x66, 0x7b, 0xf0, 0xfb, 0x26, 0x9c, - 0xbf, 0xd7, 0x6a, 0x1f, 0x8b, 0xa4, 0xb4, 0x0c, 0x3d, 0x2c, 0xce, 0x25, 0x81, 0x17, 0x5c, 0xd9, - 0x35, 0x69, 0xab, 0xd9, 0x84, 0x47, 0xb0, 0x2e, 0x69, 0x83, 0xab, 0xdb, 0x28, 0x2d, 0x03, 0x56, - 0xe2, 0x30, 0xf2, 0x77, 0xc7, 0xca, 0xbe, 0x4a, 0x5b, 0xcd, 0x2e, 0x24, 0xa0, 0xc4, 0x20, 0xc2, - 0xec, 0x3e, 0x4b, 0xcb, 0xc1, 0x33, 0xa1, 0x19, 0x57, 0x65, 0xcc, 0xee, 0x3c, 0xb4, 0x1c, 0xc5, - 0x1d, 0x3f, 0x87, 0x4a, 0xf4, 0xf5, 0x64, 0xf5, 0x42, 0x5a, 0x06, 0x6b, 0xc4, 0x0b, 0x90, 0xdc, - 0xc3, 0xd5, 0x4d, 0x9d, 0x96, 0x81, 0x4d, 0x3c, 0x86, 0x72, 0x50, 0xfa, 0x31, 0xa3, 0xbb, 0xd1, - 0xb2, 0xd8, 0x21, 0xae, 0x2c, 0x46, 0x39, 0x66, 0xb7, 0xaa, 0x5a, 0x8e, 0x5f, 0x04, 0xf8, 0x10, - 0x20, 0xf1, 0xd3, 0x39, 0xb3, 0x07, 0xd5, 0xf2, 0x70, 0x1e, 0xbb, 0xb0, 0x11, 0xd1, 0x12, 0x33, - 0x3b, 0x42, 0x2d, 0x1b, 0xb9, 0xf8, 0x08, 0xb6, 0x66, 0xe0, 0x87, 0xf9, 0xfa, 0x3c, 0x2d, 0x27, - 0x4b, 0x85, 0xfe, 0x0c, 0x0b, 0x31, 0x5f, 0xdf, 0xa7, 0xe5, 0x44, 0x2b, 0xfe, 0x08, 0x17, 0x16, - 0xa8, 0x88, 0xf9, 0xdb, 0x40, 0xed, 0x0c, 0xb0, 0xc5, 0x31, 0xe0, 0x22, 0x22, 0xf1, 0x0c, 0x5d, - 0xa1, 0x76, 0x16, 0xf6, 0xe2, 0x0f, 0x50, 0x9b, 0xab, 0xa9, 0xb9, 0x7a, 0x44, 0x2d, 0x1f, 0x82, - 0xf1, 0x1b, 0xa8, 0xce, 0x14, 0xe1, 0x1c, 0xfd, 0xa2, 0x96, 0x87, 0xc5, 0xad, 0x7b, 0x4f, 0x5f, - 0xd4, 0xd7, 0x9e, 0xbd, 0xa8, 0xaf, 0xfd, 0xfd, 0xa2, 0xbe, 0xf6, 0xeb, 0xcb, 0x7a, 0xe1, 0xd9, - 0xcb, 0x7a, 0xe1, 0xcf, 0x97, 0xf5, 0xc2, 0xb7, 0xef, 0x0c, 0x2d, 0x3e, 0x9a, 0xf4, 0xf7, 0x0d, - 0x36, 0x6e, 0x1e, 0x59, 0x8e, 0x6f, 0x8c, 0x2c, 0xbd, 0xb9, 0xe4, 0xff, 0xc2, 0x7e, 0x59, 0xfe, - 0x6f, 0x76, 0xfb, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x38, 0x72, 0x1d, 0x52, 0x4d, 0x14, 0x00, - 0x00, + // 1407 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x98, 0x5d, 0x8f, 0xdb, 0x44, + 0x17, 0xc7, 0xb3, 0x4d, 0x36, 0x59, 0x9f, 0xcd, 0xa6, 0xdb, 0xd3, 0x7d, 0xfa, 0xb8, 0xa6, 0xa4, + 0x25, 0xa5, 0x50, 0x4a, 0xd9, 0x95, 0xb6, 0xa2, 0x2a, 0x02, 0x09, 0x9a, 0xb0, 0xab, 0x2c, 0x54, + 0x44, 0x9d, 0x22, 0x90, 0x78, 0x69, 0xe4, 0xd8, 0xb3, 0xb1, 0xa9, 0xe3, 0x49, 0xed, 0xc9, 0xd2, + 0x70, 0xcf, 0x3d, 0xdf, 0x84, 0x4b, 0xee, 0xb8, 0xee, 0x65, 0x2f, 0xb9, 0x40, 0x15, 0x6a, 0x6f, + 0x80, 0x4f, 0x81, 0x66, 0xfc, 0x52, 0xe7, 0x65, 0x62, 0xef, 0xdd, 0xcc, 0xf8, 0x9c, 0xff, 0xf8, + 0xcc, 0x1c, 0x9f, 0x5f, 0x4e, 0xe0, 0x22, 0x0b, 0x79, 0x60, 0x5a, 0xcc, 0xdf, 0x33, 0x07, 0x96, + 0xbb, 0xc7, 0xa7, 0x63, 0x1a, 0xee, 0x8e, 0x03, 0xc6, 0x19, 0x6e, 0x25, 0x8f, 0x76, 0xc5, 0x23, + 0xe3, 0x35, 0x4e, 0x7d, 0x9b, 0x06, 0x23, 0xd7, 0xe7, 0x0b, 0xb6, 0xc6, 0xa5, 0xcc, 0x43, 0xb9, + 0x3e, 0xf3, 0xd4, 0x48, 0x37, 0x59, 0x7c, 0xb6, 0x33, 0x64, 0x43, 0x26, 0x87, 0x7b, 0x62, 0x14, + 0xad, 0xb6, 0x7e, 0xd5, 0xa0, 0x46, 0xe8, 0xe3, 0x09, 0x0d, 0x39, 0xee, 0x43, 0x85, 0x5a, 0x0e, + 0xd3, 0xd7, 0xae, 0xac, 0x5d, 0xdf, 0xdc, 0xbf, 0xb4, 0xfb, 0x6a, 0x2b, 0xf9, 0x62, 0xbb, 0xb1, + 0xdd, 0x81, 0xe5, 0xb0, 0x6e, 0x89, 0x48, 0x5b, 0x7c, 0x1f, 0xd6, 0x8f, 0xbd, 0x49, 0xe8, 0xe8, + 0x67, 0xa4, 0xd3, 0xeb, 0x2a, 0xa7, 0x43, 0x61, 0xd4, 0x2d, 0x91, 0xc8, 0x5a, 0x6c, 0xe5, 0xfa, + 0xc7, 0x4c, 0x2f, 0xaf, 0xde, 0xea, 0xc8, 0x3f, 0x96, 0x5b, 0x09, 0x5b, 0x6c, 0x03, 0x84, 0x94, + 0xf7, 0xd9, 0x98, 0xbb, 0xcc, 0xd7, 0x2b, 0xd2, 0xf3, 0x0d, 0x95, 0xe7, 0x03, 0xca, 0x7b, 0xd2, + 0xb0, 0x5b, 0x22, 0x5a, 0x98, 0x4c, 0x84, 0x86, 0xeb, 0xbb, 0xbc, 0x6f, 0x39, 0xa6, 0xeb, 0xeb, + 0xeb, 0xab, 0x35, 0x8e, 0x7c, 0x97, 0x77, 0x84, 0xa1, 0xd0, 0x70, 0x93, 0x89, 0x08, 0xf9, 0xf1, + 0x84, 0x06, 0x53, 0xbd, 0xba, 0x3a, 0xe4, 0xfb, 0xc2, 0x48, 0x84, 0x2c, 0xad, 0xb1, 0x03, 0x9b, + 0x03, 0x3a, 0x74, 0xfd, 0xfe, 0xc0, 0x63, 0xd6, 0x23, 0xbd, 0x26, 0x9d, 0xaf, 0xec, 0xce, 0xdc, + 0x7d, 0xe2, 0xda, 0x16, 0x86, 0x6d, 0x61, 0xd7, 0x2d, 0x11, 0x18, 0xa4, 0x33, 0xfc, 0x08, 0x36, + 0x2c, 0x87, 0x5a, 0x8f, 0xfa, 0xfc, 0x89, 0xbe, 0x21, 0x15, 0x2e, 0xab, 0xb6, 0xef, 0x08, 0xbb, + 0x2f, 0x9f, 0x74, 0x4b, 0xa4, 0x66, 0x45, 0x43, 0x11, 0xbd, 0x4d, 0x3d, 0xf7, 0x84, 0x06, 0xc2, + 0x5f, 0x5b, 0x1d, 0xfd, 0xa7, 0x91, 0xa5, 0x54, 0xd0, 0xec, 0x64, 0x82, 0x1f, 0x83, 0x46, 0x7d, + 0x3b, 0x0e, 0x02, 0xe2, 0x20, 0x54, 0x99, 0xe2, 0xdb, 0x49, 0x10, 0x1b, 0x34, 0x1e, 0xe3, 0x1d, + 0xa8, 0x5a, 0x6c, 0x34, 0x72, 0xb9, 0xbe, 0x29, 0xbd, 0x9b, 0xca, 0x00, 0xa4, 0x55, 0xb7, 0x44, + 0x62, 0x7b, 0xfc, 0x02, 0x1a, 0x9e, 0x1b, 0xf2, 0x7e, 0xe8, 0x9b, 0xe3, 0xd0, 0x61, 0x3c, 0xd4, + 0xeb, 0x52, 0xe1, 0x9a, 0x4a, 0xe1, 0x9e, 0x1b, 0xf2, 0x07, 0x89, 0x71, 0xb7, 0x44, 0xb6, 0xbc, + 0xec, 0x82, 0xd0, 0x63, 0xc7, 0xc7, 0x34, 0x48, 0x05, 0xf5, 0xad, 0xd5, 0x7a, 0x3d, 0x61, 0x9d, + 0xf8, 0x0b, 0x3d, 0x96, 0x5d, 0xc0, 0x6f, 0xe1, 0xbc, 0xc7, 0x4c, 0x3b, 0x95, 0xeb, 0x5b, 0xce, + 0xc4, 0x7f, 0xa4, 0x37, 0xa4, 0xe8, 0x3b, 0xca, 0x97, 0x64, 0xa6, 0x9d, 0x48, 0x74, 0x84, 0x43, + 0xb7, 0x44, 0xce, 0x79, 0xf3, 0x8b, 0xf8, 0x10, 0x76, 0xcc, 0xf1, 0xd8, 0x9b, 0xce, 0xab, 0x9f, + 0x95, 0xea, 0x37, 0x54, 0xea, 0x77, 0x85, 0xcf, 0xbc, 0x3c, 0x9a, 0x0b, 0xab, 0x78, 0x1f, 0xb6, + 0xa3, 0xf4, 0x0c, 0x68, 0x9a, 0x61, 0x7f, 0x47, 0x49, 0xfa, 0xe6, 0x8a, 0x24, 0x25, 0xd4, 0x4a, + 0xf3, 0xac, 0x31, 0x98, 0x59, 0xc1, 0xcf, 0xa1, 0x21, 0x52, 0x25, 0x23, 0xf8, 0x4f, 0x24, 0xd8, + 0x5a, 0x2e, 0x78, 0xe0, 0xdb, 0x59, 0xb9, 0x3a, 0xcd, 0xcc, 0xdb, 0x35, 0x58, 0x3f, 0x31, 0xbd, + 0x09, 0x6d, 0xfd, 0x7e, 0x06, 0xce, 0x2d, 0x7c, 0x26, 0x88, 0x50, 0x71, 0xcc, 0xd0, 0x91, 0xb5, + 0xab, 0x4e, 0xe4, 0x18, 0x6f, 0x43, 0xd5, 0xa1, 0xa6, 0x4d, 0x83, 0xb8, 0x38, 0xe9, 0xd9, 0x43, + 0x8a, 0x4a, 0x63, 0x57, 0x3e, 0x6f, 0x57, 0x9e, 0x3e, 0xbf, 0x5c, 0x22, 0xb1, 0x35, 0xf6, 0x60, + 0xdb, 0x33, 0x43, 0xde, 0x8f, 0xd2, 0xae, 0x9f, 0x29, 0x54, 0x8b, 0x1f, 0xdb, 0x3d, 0x33, 0x49, + 0x54, 0x51, 0xab, 0x62, 0xa1, 0x86, 0x37, 0xb3, 0x8a, 0x04, 0x76, 0x06, 0xd3, 0x9f, 0x4c, 0x9f, + 0xbb, 0x3e, 0xed, 0x9f, 0x98, 0x9e, 0x6b, 0x9b, 0x9c, 0x05, 0xa1, 0x5e, 0xb9, 0x52, 0xbe, 0xbe, + 0xb9, 0x7f, 0x71, 0x41, 0xf4, 0xe0, 0xc4, 0xb5, 0xa9, 0x6f, 0xd1, 0x58, 0xee, 0x7c, 0xea, 0xfc, + 0x55, 0xea, 0x8b, 0x77, 0xa0, 0x46, 0x7d, 0x1e, 0xb0, 0xf1, 0x34, 0xb9, 0xa6, 0xff, 0xbf, 0x3a, + 0xd5, 0x28, 0xb8, 0x83, 0xe8, 0x79, 0xac, 0x92, 0x98, 0xb7, 0x7a, 0xf0, 0xbf, 0xa5, 0x37, 0x98, + 0x39, 0xaf, 0xb5, 0xd3, 0x9c, 0x57, 0xeb, 0x3d, 0x38, 0xbf, 0xe4, 0x06, 0xf1, 0x82, 0x90, 0x73, + 0x87, 0x0e, 0x97, 0x72, 0x65, 0x12, 0xcf, 0x5a, 0x3f, 0x03, 0x6c, 0x10, 0x1a, 0x8e, 0x99, 0x1f, + 0x52, 0x6c, 0x83, 0x46, 0x9f, 0x58, 0x34, 0xaa, 0xe9, 0x6b, 0x71, 0x76, 0x2c, 0xe6, 0x72, 0x64, + 0x7d, 0x90, 0x58, 0x8a, 0x92, 0x94, 0xba, 0xe1, 0xad, 0x98, 0x5b, 0x6a, 0x04, 0xc5, 0xee, 0x59, + 0x70, 0xdd, 0x4e, 0xc0, 0x55, 0x56, 0x56, 0xa1, 0xc8, 0x6b, 0x8e, 0x5c, 0xb7, 0x62, 0x72, 0x55, + 0x72, 0x36, 0x9b, 0x41, 0x57, 0x67, 0x06, 0x5d, 0xeb, 0x39, 0x61, 0x2a, 0xd8, 0xd5, 0x99, 0x61, + 0x57, 0x35, 0x47, 0x44, 0x01, 0xaf, 0xdb, 0x09, 0xbc, 0x6a, 0x39, 0x61, 0xcf, 0xd1, 0xeb, 0x70, + 0x96, 0x5e, 0x11, 0x7b, 0xae, 0x2a, 0xbd, 0x95, 0x00, 0xfb, 0x30, 0x03, 0x30, 0x2d, 0x7e, 0x85, + 0xf9, 0x62, 0x10, 0x49, 0x2c, 0xe1, 0x57, 0x67, 0x86, 0x5f, 0x90, 0x73, 0x02, 0x0a, 0x80, 0x7d, + 0x92, 0x05, 0xd8, 0xa6, 0x92, 0x81, 0x71, 0xca, 0x2c, 0x23, 0xd8, 0x07, 0x29, 0xc1, 0xea, 0x4a, + 0x04, 0xc7, 0x31, 0xcc, 0x23, 0xac, 0xb7, 0x80, 0xb0, 0x08, 0x39, 0x6f, 0x29, 0x25, 0x72, 0x18, + 0xd6, 0x5b, 0x60, 0x58, 0x23, 0x47, 0x30, 0x07, 0x62, 0xdf, 0x2d, 0x87, 0x98, 0x1a, 0x33, 0xf1, + 0x6b, 0x16, 0xa3, 0x58, 0x5f, 0x41, 0xb1, 0x6d, 0x29, 0xff, 0xae, 0x52, 0xbe, 0x30, 0xc6, 0x88, + 0x1a, 0x63, 0xd7, 0x14, 0x89, 0x96, 0xcb, 0xb1, 0x7b, 0x2a, 0x8e, 0x5d, 0x55, 0x28, 0x16, 0x03, + 0xd9, 0x9f, 0x67, 0xe0, 0xec, 0x5c, 0xb2, 0x0b, 0x8c, 0x59, 0xcc, 0xa6, 0xb2, 0x12, 0x6e, 0x11, + 0x39, 0x16, 0x6b, 0xb6, 0xc9, 0x4d, 0x59, 0xde, 0xea, 0x44, 0x8e, 0x71, 0x1b, 0xca, 0x1e, 0x1b, + 0xca, 0xda, 0xa5, 0x11, 0x31, 0x14, 0x56, 0x69, 0x5d, 0xd2, 0xe2, 0xb2, 0xd3, 0x04, 0x18, 0x9a, + 0x61, 0xff, 0x47, 0xd3, 0xe7, 0xd4, 0x96, 0x65, 0xa7, 0x4c, 0x32, 0x2b, 0x68, 0xc0, 0x86, 0x98, + 0x4d, 0x42, 0x6a, 0xcb, 0x7a, 0x52, 0x26, 0xe9, 0x1c, 0xbb, 0x50, 0xa5, 0x27, 0xd4, 0xe7, 0xa1, + 0x5e, 0x93, 0x94, 0xba, 0xb0, 0x84, 0x52, 0xd4, 0xe7, 0x6d, 0x5d, 0xa0, 0xe0, 0xdf, 0xe7, 0x97, + 0xb7, 0x23, 0xeb, 0x9b, 0x6c, 0xe4, 0x72, 0x3a, 0x1a, 0xf3, 0x29, 0x89, 0xfd, 0xf1, 0x12, 0x68, + 0x22, 0x8e, 0x70, 0x6c, 0x5a, 0x54, 0x16, 0x0e, 0x8d, 0xbc, 0x5a, 0x10, 0x94, 0x08, 0xa5, 0xb0, + 0x2c, 0x07, 0x1a, 0x89, 0x67, 0xe2, 0xdd, 0xc6, 0x81, 0xcb, 0x02, 0x97, 0x4f, 0xe5, 0x97, 0x5e, + 0x26, 0xe9, 0x1c, 0xaf, 0xc2, 0xd6, 0x88, 0x8e, 0xc6, 0x8c, 0x79, 0x7d, 0x1a, 0x04, 0x2c, 0x90, + 0x9f, 0xb1, 0x46, 0xea, 0xf1, 0xe2, 0x81, 0x58, 0x6b, 0xdd, 0x84, 0x0b, 0xcb, 0x6f, 0x78, 0xd9, + 0x21, 0xb7, 0x6e, 0xc0, 0xce, 0xb2, 0xdb, 0x5b, 0x66, 0xbb, 0xff, 0xdb, 0x26, 0x9c, 0xbd, 0xdb, + 0xee, 0x1c, 0x89, 0xa4, 0x74, 0x2d, 0x33, 0x2e, 0xce, 0x15, 0x81, 0x17, 0x5c, 0xd9, 0x35, 0x19, + 0xab, 0xd9, 0x84, 0x87, 0xb0, 0x2e, 0x69, 0x83, 0xab, 0xdb, 0x28, 0x23, 0x07, 0x56, 0xe2, 0x65, + 0xe4, 0xef, 0x8e, 0x95, 0x7d, 0x95, 0xb1, 0x9a, 0x5d, 0x48, 0x40, 0x4b, 0x41, 0x84, 0xf9, 0x7d, + 0x96, 0x51, 0x80, 0x67, 0x42, 0x33, 0xad, 0xca, 0x98, 0xdf, 0x79, 0x18, 0x05, 0x8a, 0x3b, 0x7e, + 0x06, 0xb5, 0xe4, 0xeb, 0xc9, 0xeb, 0x85, 0x8c, 0x1c, 0xd6, 0x88, 0x0b, 0x90, 0xdc, 0xc3, 0xd5, + 0x4d, 0x9d, 0x91, 0x83, 0x4d, 0x3c, 0x82, 0x6a, 0x54, 0xfa, 0x31, 0xa7, 0xbb, 0x31, 0xf2, 0xd8, + 0x21, 0x8e, 0x2c, 0x45, 0x39, 0xe6, 0xb7, 0xaa, 0x46, 0x81, 0x5f, 0x04, 0xf8, 0x00, 0x20, 0xf3, + 0xd3, 0x39, 0xb7, 0x07, 0x35, 0x8a, 0x70, 0x1e, 0x7b, 0xb0, 0x91, 0xd0, 0x12, 0x73, 0x3b, 0x42, + 0x23, 0x1f, 0xb9, 0xf8, 0x10, 0xb6, 0x66, 0xe0, 0x87, 0xc5, 0xfa, 0x3c, 0xa3, 0x20, 0x4b, 0x85, + 0xfe, 0x0c, 0x0b, 0xb1, 0x58, 0xdf, 0x67, 0x14, 0x44, 0x2b, 0xfe, 0x00, 0xe7, 0x16, 0xa8, 0x88, + 0xc5, 0xdb, 0x40, 0xe3, 0x14, 0xb0, 0xc5, 0x11, 0xe0, 0x22, 0x22, 0xf1, 0x14, 0x5d, 0xa1, 0x71, + 0x1a, 0xf6, 0xe2, 0xf7, 0xd0, 0x98, 0xab, 0xa9, 0x85, 0x7a, 0x44, 0xa3, 0x18, 0x82, 0xf1, 0x6b, + 0xa8, 0xcf, 0x14, 0xe1, 0x02, 0xfd, 0xa2, 0x51, 0x84, 0xc5, 0xed, 0xbb, 0x4f, 0x5f, 0x34, 0xd7, + 0x9e, 0xbd, 0x68, 0xae, 0xfd, 0xf5, 0xa2, 0xb9, 0xf6, 0xcb, 0xcb, 0x66, 0xe9, 0xd9, 0xcb, 0x66, + 0xe9, 0x8f, 0x97, 0xcd, 0xd2, 0x37, 0x6f, 0x0f, 0x5d, 0xee, 0x4c, 0x06, 0xbb, 0x16, 0x1b, 0xed, + 0x1d, 0xba, 0x7e, 0x68, 0x39, 0xae, 0xb9, 0xb7, 0xe4, 0x2f, 0xbb, 0x41, 0x55, 0xfe, 0x6f, 0x76, + 0xeb, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x28, 0x00, 0x44, 0x1c, 0xd0, 0x13, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/blockchain/v0/reactor.go b/blockchain/v0/reactor.go index ed04e0e32..3ecc93b04 100644 --- a/blockchain/v0/reactor.go +++ b/blockchain/v0/reactor.go @@ -400,29 +400,29 @@ FOR_LOOP: bcR.Switch.StopPeerForError(peer2, fmt.Errorf("blockchainReactor validation error: %v", err)) } continue FOR_LOOP - } else { - bcR.pool.PopRequest() + } - // TODO: batch saves so we dont persist to disk every block - bcR.store.SaveBlock(first, firstParts, second.LastCommit) + bcR.pool.PopRequest() - // TODO: same thing for app - but we would need a way to - // get the hash without persisting the state - var err error - state, _, err = bcR.blockExec.ApplyBlock(state, firstID, first, nil) - if err != nil { - // TODO This is bad, are we zombie? - panic(fmt.Sprintf("Failed to process committed block (%d:%X): %v", first.Height, first.Hash(), err)) - } - blocksSynced++ + // TODO: batch saves so we dont persist to disk every block + bcR.store.SaveBlock(first, firstParts, second.LastCommit) - if blocksSynced%100 == 0 { - lastRate = 0.9*lastRate + 0.1*(100/time.Since(lastHundred).Seconds()) - bcR.Logger.Info("Fast Sync Rate", "height", bcR.pool.height, - "max_peer_height", bcR.pool.MaxPeerHeight(), "blocks/s", lastRate) - lastHundred = time.Now() - } + // TODO: same thing for app - but we would need a way to + // get the hash without persisting the state + state, _, err = bcR.blockExec.ApplyBlock(state, firstID, first, nil) + if err != nil { + // TODO This is bad, are we zombie? + panic(fmt.Sprintf("Failed to process committed block (%d:%X): %v", first.Height, first.Hash(), err)) + } + blocksSynced++ + + if blocksSynced%100 == 0 { + lastRate = 0.9*lastRate + 0.1*(100/time.Since(lastHundred).Seconds()) + bcR.Logger.Info("Fast Sync Rate", "height", bcR.pool.height, + "max_peer_height", bcR.pool.MaxPeerHeight(), "blocks/s", lastRate) + lastHundred = time.Now() } + continue FOR_LOOP case <-bcR.Quit(): diff --git a/blockchain/v2/routine.go b/blockchain/v2/routine.go index cba926efa..b0f8c8ec2 100644 --- a/blockchain/v2/routine.go +++ b/blockchain/v2/routine.go @@ -58,7 +58,7 @@ func (rt *Routine) setMetrics(metrics *Metrics) { } func (rt *Routine) start() { - rt.logger.Info(fmt.Sprintf("%s: run", rt.name)) + rt.logger.Info("routine start", "msg", log.NewLazySprintf("%s: run", rt.name)) running := atomic.CompareAndSwapUint32(rt.running, uint32(0), uint32(1)) if !running { panic(fmt.Sprintf("%s is already running", rt.name)) @@ -98,7 +98,7 @@ func (rt *Routine) start() { return } rt.metrics.EventsOut.With("routine", rt.name).Add(1) - rt.logger.Debug(fmt.Sprintf("%s: produced %T %+v", rt.name, oEvent, oEvent)) + rt.logger.Debug("routine start", "msg", log.NewLazySprintf("%s: produced %T %+v", rt.name, oEvent, oEvent)) // Skip rTrySchedule and rProcessBlock events as they clutter the history // due to their frequency. @@ -118,7 +118,7 @@ func (rt *Routine) start() { // XXX: look into returning OpError in the net package func (rt *Routine) send(event Event) bool { - rt.logger.Debug(fmt.Sprintf("%s: received %T %+v", rt.name, event, event)) + rt.logger.Debug("routine send", "msg", log.NewLazySprintf("%s: received %T %+v", rt.name, event, event)) if !rt.isRunning() { return false } @@ -150,7 +150,7 @@ func (rt *Routine) stop() { return } - rt.logger.Info(fmt.Sprintf("%s: stop", rt.name)) + rt.logger.Info("routine stop", "msg", log.NewLazySprintf("%s: stop", rt.name)) rt.queue.Dispose() // this should block until all queue items are free? } diff --git a/buf.gen.yaml b/buf.gen.yaml new file mode 100644 index 000000000..d972360bb --- /dev/null +++ b/buf.gen.yaml @@ -0,0 +1,9 @@ +version: v1 +plugins: + - name: gogofaster + out: ./proto/ + opt: + - Mgoogle/protobuf/timestamp.proto=github.com/gogo/protobuf/types + - Mgoogle/protobuf/duration.proto=github.com/golang/protobuf/ptypes/duration + - plugins=grpc + - paths=source_relative diff --git a/buf.work.yaml b/buf.work.yaml new file mode 100644 index 000000000..494296bfa --- /dev/null +++ b/buf.work.yaml @@ -0,0 +1,4 @@ +version: v1 +directories: + - proto + - third_party/proto diff --git a/cmd/ostracon/commands/compact.go b/cmd/ostracon/commands/compact.go new file mode 100644 index 000000000..2155c7207 --- /dev/null +++ b/cmd/ostracon/commands/compact.go @@ -0,0 +1,66 @@ +package commands + +import ( + "errors" + "path/filepath" + "sync" + + "github.com/spf13/cobra" + "github.com/syndtr/goleveldb/leveldb" + "github.com/syndtr/goleveldb/leveldb/opt" + "github.com/syndtr/goleveldb/leveldb/util" + + "github.com/Finschia/ostracon/libs/log" +) + +var CompactGoLevelDBCmd = &cobra.Command{ + Use: "experimental-compact-goleveldb", + Short: "force compacts the ostracon storage engine (only GoLevelDB supported)", + Long: ` +This is a temporary utility command that performs a force compaction on the state +and blockstores to reduce disk space for a pruning node. This should only be run +once the node has stopped. This command will likely be omitted in the future after +the planned refactor to the storage engine. + +Currently, only GoLevelDB is supported. + `, + RunE: func(cmd *cobra.Command, args []string) error { + if config.DBBackend != "goleveldb" { + return errors.New("compaction is currently only supported with goleveldb") + } + + compactGoLevelDBs(config.RootDir, logger) + return nil + }, +} + +func compactGoLevelDBs(rootDir string, logger log.Logger) { + dbNames := []string{"state", "blockstore"} + o := &opt.Options{ + DisableSeeksCompaction: true, + } + wg := sync.WaitGroup{} + + for _, dbName := range dbNames { + dbName := dbName + wg.Add(1) + go func() { + defer wg.Done() + dbPath := filepath.Join(rootDir, "data", dbName+".db") + store, err := leveldb.OpenFile(dbPath, o) + if err != nil { + logger.Error("failed to initialize ostracon db", "path", dbPath, "err", err) + return + } + defer store.Close() + + logger.Info("starting compaction...", "db", dbPath) + + err = store.CompactRange(util.Range{Start: nil, Limit: nil}) + if err != nil { + logger.Error("failed to compact ostracon db", "path", dbPath, "err", err) + } + }() + } + wg.Wait() +} diff --git a/cmd/ostracon/commands/compact_test.go b/cmd/ostracon/commands/compact_test.go new file mode 100644 index 000000000..38e598a2d --- /dev/null +++ b/cmd/ostracon/commands/compact_test.go @@ -0,0 +1,52 @@ +package commands + +import ( + cfg "github.com/Finschia/ostracon/config" + "github.com/Finschia/ostracon/libs/log" + "github.com/stretchr/testify/assert" + "os" + "testing" +) + +func Test_RunE(t *testing.T) { + config = cfg.TestConfig() + config.RootDir = os.TempDir() + config.DBBackend = "badgerdb" // not support + logger = log.TestingLogger() + err := CompactGoLevelDBCmd.RunE(nil, nil) + assert.Error(t, err) + config.DBBackend = "goleveldb" + err = CompactGoLevelDBCmd.RunE(nil, nil) + assert.NoError(t, err) +} + +func Test_compactGoLevelDBs(t *testing.T) { + type args struct { + rootDir string + logger log.Logger + } + tests := []struct { + name string + args args + }{ + { + name: "success", + args: args{ + rootDir: os.TempDir(), + logger: log.TestingLogger(), + }, + }, + { + name: "doesn't exist db dir", + args: args{ + rootDir: "/nonexistent", + logger: log.TestingLogger(), + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + compactGoLevelDBs(tt.args.rootDir, tt.args.logger) + }) + } +} diff --git a/cmd/ostracon/main.go b/cmd/ostracon/main.go index e40b3695c..a84e2a6ba 100644 --- a/cmd/ostracon/main.go +++ b/cmd/ostracon/main.go @@ -28,6 +28,7 @@ func main() { cmd.GenNodeKeyCmd, cmd.VersionCmd, cmd.RollbackStateCmd, + cmd.CompactGoLevelDBCmd, debug.DebugCmd, cli.NewCompletionCmd(rootCmd, true), ) diff --git a/config/config.go b/config/config.go index 28a5b55ed..7236d9f3a 100644 --- a/config/config.go +++ b/config/config.go @@ -25,6 +25,14 @@ const ( DefaultLogLevel = "info" DefaultDBBackend = "goleveldb" + + // Mempool versions. + // Default is v0. + + // MempoolV0 is regular mempool + MempoolV0 = "v0" + // MempoolV1 is prioritized mempool + MempoolV1 = "v1" ) // NOTE: Most of the structs & relevant comments + the @@ -763,6 +771,13 @@ func DefaultFuzzConnConfig() *FuzzConnConfig { // MempoolConfig defines the configuration options for the Ostracon mempool type MempoolConfig struct { + // Mempool version to use: + // 1) "v0" - (default) FIFO mempool. + // 2) "v1" - prioritized mempool. + // WARNING: There's a known memory leak with the prioritized mempool + // that the team are working on. Read more here: + // https://github.com/tendermint/tendermint/issues/8775 + Version string `mapstructure:"version"` RootDir string `mapstructure:"home"` Recheck bool `mapstructure:"recheck"` Broadcast bool `mapstructure:"broadcast"` @@ -786,20 +801,39 @@ type MempoolConfig struct { // Including space needed by encoding (one varint per transaction). // XXX: Unused due to https://github.com/tendermint/tendermint/issues/5796 MaxBatchBytes int `mapstructure:"max_batch_bytes"` + + // TTLDuration, if non-zero, defines the maximum amount of time a transaction + // can exist for in the mempool. + // + // Note, if TTLNumBlocks is also defined, a transaction will be removed if it + // has existed in the mempool at least TTLNumBlocks number of blocks or if it's + // insertion time into the mempool is beyond TTLDuration. + TTLDuration time.Duration `mapstructure:"ttl-duration"` + + // TTLNumBlocks, if non-zero, defines the maximum number of blocks a transaction + // can exist for in the mempool. + // + // Note, if TTLDuration is also defined, a transaction will be removed if it + // has existed in the mempool at least TTLNumBlocks number of blocks or if + // it's insertion time into the mempool is beyond TTLDuration. + TTLNumBlocks int64 `mapstructure:"ttl-num-blocks"` } // DefaultMempoolConfig returns a default configuration for the Ostracon mempool func DefaultMempoolConfig() *MempoolConfig { return &MempoolConfig{ + Version: MempoolV0, Recheck: true, Broadcast: true, WalPath: "", // Each signature verification takes .5ms, Size reduced until we implement // ABCI Recheck - Size: 5000, - MaxTxsBytes: 1024 * 1024 * 1024, // 1GB - CacheSize: 10000, - MaxTxBytes: 1024 * 1024, // 1MB + Size: 5000, + MaxTxsBytes: 1024 * 1024 * 1024, // 1GB + CacheSize: 10000, + MaxTxBytes: 1024 * 1024, // 1MB + TTLDuration: 0 * time.Second, + TTLNumBlocks: 0, } } diff --git a/config/toml.go b/config/toml.go index 5a1ae5894..e1b82b2ab 100644 --- a/config/toml.go +++ b/config/toml.go @@ -397,6 +397,11 @@ statesync_recv_buf_size = {{ .P2P.StatesyncRecvBufSize }} ####################################################### [mempool] +# Mempool version to use: +# 1) "v0" - (default) FIFO mempool. +# 2) "v1" - prioritized mempool. +version = "{{ .Mempool.Version }}" + recheck = {{ .Mempool.Recheck }} broadcast = {{ .Mempool.Broadcast }} wal_dir = "{{ js .Mempool.WalPath }}" @@ -426,6 +431,22 @@ max_tx_bytes = {{ .Mempool.MaxTxBytes }} # XXX: Unused due to https://github.com/tendermint/tendermint/issues/5796 max_batch_bytes = {{ .Mempool.MaxBatchBytes }} +# ttl-duration, if non-zero, defines the maximum amount of time a transaction +# can exist for in the mempool. +# +# Note, if ttl-num-blocks is also defined, a transaction will be removed if it +# has existed in the mempool at least ttl-num-blocks number of blocks or if it's +# insertion time into the mempool is beyond ttl-duration. +ttl-duration = "{{ .Mempool.TTLDuration }}" + +# ttl-num-blocks, if non-zero, defines the maximum number of blocks a transaction +# can exist for in the mempool. +# +# Note, if ttl-duration is also defined, a transaction will be removed if it +# has existed in the mempool at least ttl-num-blocks number of blocks or if +# it's insertion time into the mempool is beyond ttl-duration. +ttl-num-blocks = {{ .Mempool.TTLNumBlocks }} + ####################################################### ### State Sync Configuration Options ### ####################################################### @@ -531,8 +552,14 @@ peer_query_maj23_sleep_duration = "{{ .Consensus.PeerQueryMaj23SleepDuration }}" # 1) "null" # 2) "kv" (default) - the simplest possible indexer, backed by key-value storage (defaults to levelDB; see DBBackend). # - When "kv" is chosen "tx.height" and "tx.hash" will always be indexed. +# 3) "psql" - the indexer services backed by PostgreSQL. +# When "kv" or "psql" is chosen "tx.height" and "tx.hash" will always be indexed. indexer = "{{ .TxIndex.Indexer }}" +# The PostgreSQL connection configuration, the connection format: +# postgresql://:@:/? +psql-conn = "{{ .TxIndex.PsqlConn }}" + ####################################################### ### Instrumentation Configuration Options ### ####################################################### diff --git a/consensus/byzantine_test.go b/consensus/byzantine_test.go index 8ad4a3138..5aadcc274 100644 --- a/consensus/byzantine_test.go +++ b/consensus/byzantine_test.go @@ -16,14 +16,17 @@ import ( tmproto "github.com/tendermint/tendermint/proto/tendermint/types" dbm "github.com/tendermint/tm-db" - config2 "github.com/Finschia/ostracon/config" - abcicli "github.com/Finschia/ostracon/abci/client" "github.com/Finschia/ostracon/evidence" "github.com/Finschia/ostracon/libs/log" "github.com/Finschia/ostracon/libs/service" tmsync "github.com/Finschia/ostracon/libs/sync" mempl "github.com/Finschia/ostracon/mempool" + + cfg "github.com/Finschia/ostracon/config" + mempoolv0 "github.com/Finschia/ostracon/mempool/v0" + + //mempoolv1 "github.com/Finschia/ostracon/mempool/v1" "github.com/Finschia/ostracon/p2p" sm "github.com/Finschia/ostracon/state" "github.com/Finschia/ostracon/store" @@ -60,14 +63,34 @@ func TestByzantinePrevoteEquivocation(t *testing.T) { blockDB := dbm.NewMemDB() blockStore := store.NewBlockStore(blockDB) - // one for mempool, one for consensus mtx := new(tmsync.Mutex) - proxyAppConnMem := abcicli.NewLocalClient(mtx, app) + // one for mempool, one for consensus proxyAppConnCon := abcicli.NewLocalClient(mtx, app) + proxyAppConnConMem := abcicli.NewLocalClient(mtx, app) // Make Mempool - mempool := mempl.NewCListMempool(thisConfig.Mempool, proxyAppConnMem, 0) - mempool.SetLogger(log.TestingLogger().With("module", "mempool")) + var mempool mempl.Mempool + + switch thisConfig.Mempool.Version { + case cfg.MempoolV0: + mempool = mempoolv0.NewCListMempool(config.Mempool, + proxyAppConnConMem, + state.LastBlockHeight, + mempoolv0.WithPreCheck(sm.TxPreCheck(state)), + mempoolv0.WithPostCheck(sm.TxPostCheck(state))) + case cfg.MempoolV1: // XXX Deprecated + panic("Deprecated MempoolV1") + /* + mempool = mempoolv1.NewTxMempool(logger, + config.Mempool, + proxyAppConnConMem, + state.LastBlockHeight, + mempoolv1.WithPreCheck(sm.TxPreCheck(state)), + mempoolv1.WithPostCheck(sm.TxPostCheck(state)), + ) + */ + } + if thisConfig.Consensus.WaitForTxs() { mempool.EnableTxsAvailable() } @@ -124,7 +147,7 @@ func TestByzantinePrevoteEquivocation(t *testing.T) { } } // make connected switches and start all reactors - p2p.MakeConnectedSwitches(config.P2P, nValidators, func(i int, s *p2p.Switch, c *config2.P2PConfig) *p2p.Switch { + p2p.MakeConnectedSwitches(config.P2P, nValidators, func(i int, s *p2p.Switch, c *cfg.P2PConfig) *p2p.Switch { s.AddReactor("CONSENSUS", reactors[i]) s.SetLogger(log.NewNopLogger().With("module", "p2p")) // Switch log is noisy for this test return s @@ -311,7 +334,7 @@ func TestByzantineConflictingProposalsWithPartition(t *testing.T) { config.P2P, i, "foo", "1.0.0", - func(i int, sw *p2p.Switch, config *config2.P2PConfig) *p2p.Switch { + func(i int, sw *p2p.Switch, config *cfg.P2PConfig) *p2p.Switch { return sw }) switches[i].SetLogger(p2pLogger.With("validator", i)) @@ -373,7 +396,7 @@ func TestByzantineConflictingProposalsWithPartition(t *testing.T) { } }() - p2p.MakeConnectedSwitches(config.P2P, N, func(i int, s *p2p.Switch, config *config2.P2PConfig) *p2p.Switch { + p2p.MakeConnectedSwitches(config.P2P, N, func(i int, s *p2p.Switch, config *cfg.P2PConfig) *p2p.Switch { // ignore new switch s, we already made ours switches[i].AddReactor("CONSENSUS", reactors[i]) return switches[i] diff --git a/consensus/common_test.go b/consensus/common_test.go index c0a2887c8..44c7b9be1 100644 --- a/consensus/common_test.go +++ b/consensus/common_test.go @@ -33,6 +33,9 @@ import ( tmpubsub "github.com/Finschia/ostracon/libs/pubsub" tmsync "github.com/Finschia/ostracon/libs/sync" mempl "github.com/Finschia/ostracon/mempool" + mempoolv0 "github.com/Finschia/ostracon/mempool/v0" + + //mempoolv1 "github.com/Finschia/ostracon/mempool/v1" "github.com/Finschia/ostracon/p2p" "github.com/Finschia/ostracon/privval" sm "github.com/Finschia/ostracon/state" @@ -420,12 +423,38 @@ func newStateWithConfigAndBlockStoreWithLoggers( // one for mempool, one for consensus mtx := new(tmsync.Mutex) - proxyAppConnMem := abcicli.NewLocalClient(mtx, app) + proxyAppConnCon := abcicli.NewLocalClient(mtx, app) + proxyAppConnConMem := abcicli.NewLocalClient(mtx, app) + // Make Mempool + memplMetrics := mempl.NopMetrics() // Make Mempool - mempool := mempl.NewCListMempool(thisConfig.Mempool, proxyAppConnMem, 0) - mempool.SetLogger(loggers.memLogger.With("module", "mempool")) + var mempool mempl.Mempool + + switch config.Mempool.Version { + case cfg.MempoolV0: + mempool = mempoolv0.NewCListMempool(config.Mempool, + proxyAppConnConMem, + state.LastBlockHeight, + mempoolv0.WithMetrics(memplMetrics), + mempoolv0.WithPreCheck(sm.TxPreCheck(state)), + mempoolv0.WithPostCheck(sm.TxPostCheck(state))) + mempool.(*mempoolv0.CListMempool).SetLogger(loggers.memLogger.With("module", "mempool")) + case cfg.MempoolV1: // XXX Deprecated + panic("Deprecated MempoolV1") + /* + logger := consensusLogger() + mempool = mempoolv1.NewTxMempool(logger, + config.Mempool, + proxyAppConnConMem, + state.LastBlockHeight, + mempoolv1.WithMetrics(memplMetrics), + mempoolv1.WithPreCheck(sm.TxPreCheck(state)), + mempoolv1.WithPostCheck(sm.TxPostCheck(state)), + ) + */ + } if thisConfig.Consensus.WaitForTxs() { mempool.EnableTxsAvailable() } diff --git a/consensus/mempool_test.go b/consensus/mempool_test.go index 8bcde0b71..9be7d0e87 100644 --- a/consensus/mempool_test.go +++ b/consensus/mempool_test.go @@ -105,7 +105,7 @@ func deliverTxsRange(cs *State, start, end int) { for i := start; i < end; i++ { txBytes := make([]byte, 8) binary.BigEndian.PutUint64(txBytes, uint64(i)) - _, err := assertMempool(cs.txNotifier).CheckTxSync(txBytes, mempl.TxInfo{}) + err := assertMempool(cs.txNotifier).CheckTxSync(txBytes, nil, mempl.TxInfo{}) if err != nil { panic(fmt.Sprintf("Error after CheckTx: %v", err)) } diff --git a/consensus/reactor.go b/consensus/reactor.go index 7c6adb9cd..a071cfd19 100644 --- a/consensus/reactor.go +++ b/consensus/reactor.go @@ -1276,12 +1276,12 @@ func (ps *PeerState) SetHasVote(vote *types.Vote) { } func (ps *PeerState) setHasVote(height int64, round int32, voteType tmproto.SignedMsgType, index int32) { - logger := ps.logger.With( + ps.logger.Debug("setHasVote", "peerH/R", - fmt.Sprintf("%d/%d", ps.PRS.Height, ps.PRS.Round), + log.NewLazySprintf("%d/%d", ps.PRS.Height, ps.PRS.Round), "H/R", - fmt.Sprintf("%d/%d", height, round)) - logger.Debug("setHasVote", "type", voteType, "index", index) + log.NewLazySprintf("%d/%d", height, round), + "type", voteType, "index", index) // NOTE: some may be nil BitArrays -> no side effects. psVotes := ps.getVoteBitArray(height, round, voteType) diff --git a/consensus/reactor_test.go b/consensus/reactor_test.go index 690fb1489..2c722dccc 100644 --- a/consensus/reactor_test.go +++ b/consensus/reactor_test.go @@ -30,6 +30,9 @@ import ( "github.com/Finschia/ostracon/libs/log" tmsync "github.com/Finschia/ostracon/libs/sync" mempl "github.com/Finschia/ostracon/mempool" + mempoolv0 "github.com/Finschia/ostracon/mempool/v0" + + //mempoolv1 "github.com/Finschia/ostracon/mempool/v1" "github.com/Finschia/ostracon/p2p" p2pmock "github.com/Finschia/ostracon/p2p/mock" sm "github.com/Finschia/ostracon/state" @@ -152,14 +155,36 @@ func TestReactorWithEvidence(t *testing.T) { blockDB := dbm.NewMemDB() blockStore := store.NewBlockStore(blockDB) - // one for mempool, one for consensus mtx := new(tmsync.Mutex) - proxyAppConnMem := abcicli.NewLocalClient(mtx, app) + memplMetrics := mempl.NopMetrics() + // one for mempool, one for consensus proxyAppConnCon := abcicli.NewLocalClient(mtx, app) + proxyAppConnConMem := abcicli.NewLocalClient(mtx, app) // Make Mempool - mempool := mempl.NewCListMempool(thisConfig.Mempool, proxyAppConnMem, 0) - mempool.SetLogger(log.TestingLogger().With("module", "mempool")) + var mempool mempl.Mempool + + switch config.Mempool.Version { + case cfg.MempoolV0: + mempool = mempoolv0.NewCListMempool(config.Mempool, + proxyAppConnConMem, + state.LastBlockHeight, + mempoolv0.WithMetrics(memplMetrics), + mempoolv0.WithPreCheck(sm.TxPreCheck(state)), + mempoolv0.WithPostCheck(sm.TxPostCheck(state))) + case cfg.MempoolV1: // XXX Deprecated MempoolV1 + panic("Deprecated MempoolV1") + /* + mempool = mempoolv1.NewTxMempool(logger, + config.Mempool, + proxyAppConnConMem, + state.LastBlockHeight, + mempoolv1.WithMetrics(memplMetrics), + mempoolv1.WithPreCheck(sm.TxPreCheck(state)), + mempoolv1.WithPostCheck(sm.TxPostCheck(state)), + ) + */ + } if thisConfig.Consensus.WaitForTxs() { mempool.EnableTxsAvailable() } @@ -221,7 +246,7 @@ func TestReactorCreatesBlockWhenEmptyBlocksFalse(t *testing.T) { defer stopConsensusNet(log.TestingLogger(), reactors, eventBuses) // send a tx - if _, err := assertMempool(css[3].txNotifier).CheckTxSync([]byte{1, 2, 3}, mempl.TxInfo{}); err != nil { + if err := assertMempool(css[3].txNotifier).CheckTxSync([]byte{1, 2, 3}, nil, mempl.TxInfo{}); err != nil { t.Error(err) } @@ -549,7 +574,7 @@ func waitForAndValidateBlock( err := validateBlock(newBlock, activeVals) assert.Nil(t, err) for _, tx := range txs { - _, err := assertMempool(css[j].txNotifier).CheckTxSync(tx, mempl.TxInfo{}) + err := assertMempool(css[j].txNotifier).CheckTxSync(tx, nil, mempl.TxInfo{}) assert.Nil(t, err) } }, css) diff --git a/consensus/replay_stubs.go b/consensus/replay_stubs.go index 13694208e..6f67e3bd0 100644 --- a/consensus/replay_stubs.go +++ b/consensus/replay_stubs.go @@ -17,17 +17,23 @@ type emptyMempool struct{} var _ mempl.Mempool = emptyMempool{} -func (emptyMempool) Lock() {} -func (emptyMempool) Unlock() {} -func (emptyMempool) Size() int { return 0 } -func (emptyMempool) CheckTxSync(_ types.Tx, _ mempl.TxInfo) (*ocabci.Response, error) { - return nil, nil +func (emptyMempool) Lock() {} +func (emptyMempool) Unlock() {} +func (emptyMempool) Size() int { return 0 } +func (emptyMempool) SizeBytes() int64 { return 0 } +func (emptyMempool) CheckTxSync(_ types.Tx, _ func(*ocabci.Response), _ mempl.TxInfo) error { + return nil } func (emptyMempool) CheckTxAsync(_ types.Tx, _ mempl.TxInfo, _ func(error), _ func(*ocabci.Response)) { } func (emptyMempool) ReapMaxBytesMaxGas(_, _ int64) types.Txs { return types.Txs{} } func (emptyMempool) ReapMaxBytesMaxGasMaxTxs(_, _, _ int64) types.Txs { return types.Txs{} } func (emptyMempool) ReapMaxTxs(n int) types.Txs { return types.Txs{} } + +func (txmp emptyMempool) RemoveTxByKey(txKey types.TxKey) error { + return nil +} + func (emptyMempool) Update( _ *types.Block, _ []*abci.ResponseDeliverTx, diff --git a/consensus/replay_test.go b/consensus/replay_test.go index 5582faab2..4b46cb949 100644 --- a/consensus/replay_test.go +++ b/consensus/replay_test.go @@ -121,7 +121,7 @@ func sendTxs(ctx context.Context, cs *State) { return default: tx := []byte{byte(i)} - if _, err := assertMempool(cs.txNotifier).CheckTxSync(tx, mempl.TxInfo{}); err != nil { + if err := assertMempool(cs.txNotifier).CheckTxSync(tx, nil, mempl.TxInfo{}); err != nil { panic(err) } i++ @@ -471,7 +471,7 @@ func TestSimulateValidatorsChange(t *testing.T) { valPubKey1ABCI, err := cryptoenc.PubKeyToProto(newValidatorPubKey1) assert.Nil(t, err) newValidatorTx1 := kvstore.MakeValSetChangeTx(valPubKey1ABCI, testMinPower) - _, err = assertMempool(css[0].txNotifier).CheckTxSync(newValidatorTx1, mempl.TxInfo{}) + err = assertMempool(css[0].txNotifier).CheckTxSync(newValidatorTx1, nil, mempl.TxInfo{}) assert.Nil(t, err) }) @@ -485,7 +485,7 @@ func TestSimulateValidatorsChange(t *testing.T) { updatePubKey1ABCI, err := cryptoenc.PubKeyToProto(updateValidatorPubKey1) require.NoError(t, err) updateValidatorTx1 := kvstore.MakeValSetChangeTx(updatePubKey1ABCI, 25) - _, err = assertMempool(css[0].txNotifier).CheckTxSync(updateValidatorTx1, mempl.TxInfo{}) + err = assertMempool(css[0].txNotifier).CheckTxSync(updateValidatorTx1, nil, mempl.TxInfo{}) assert.Nil(t, err) }) @@ -502,14 +502,14 @@ func TestSimulateValidatorsChange(t *testing.T) { newVal2ABCI, err := cryptoenc.PubKeyToProto(newValidatorPubKey2) require.NoError(t, err) newValidatorTx2 := kvstore.MakeValSetChangeTx(newVal2ABCI, testMinPower) - _, err = assertMempool(css[0].txNotifier).CheckTxSync(newValidatorTx2, mempl.TxInfo{}) + err = assertMempool(css[0].txNotifier).CheckTxSync(newValidatorTx2, nil, mempl.TxInfo{}) assert.Nil(t, err) newValidatorPubKey3, err := css[nVals+2].privValidator.GetPubKey() require.NoError(t, err) newVal3ABCI, err := cryptoenc.PubKeyToProto(newValidatorPubKey3) require.NoError(t, err) newValidatorTx3 := kvstore.MakeValSetChangeTx(newVal3ABCI, testMinPower) - _, err = assertMempool(css[0].txNotifier).CheckTxSync(newValidatorTx3, mempl.TxInfo{}) + err = assertMempool(css[0].txNotifier).CheckTxSync(newValidatorTx3, nil, mempl.TxInfo{}) assert.Nil(t, err) }) @@ -549,7 +549,7 @@ func TestSimulateValidatorsChange(t *testing.T) { newVal3ABCI, err := cryptoenc.PubKeyToProto(newValidatorPubKey3) require.NoError(t, err) removeValidatorTx3 := kvstore.MakeValSetChangeTx(newVal3ABCI, 0) - _, err = assertMempool(css[0].txNotifier).CheckTxSync(removeValidatorTx3, mempl.TxInfo{}) + err = assertMempool(css[0].txNotifier).CheckTxSync(removeValidatorTx3, nil, mempl.TxInfo{}) assert.Nil(t, err) }) diff --git a/consensus/state.go b/consensus/state.go index 4a0faecce..8700acebb 100644 --- a/consensus/state.go +++ b/consensus/state.go @@ -1030,7 +1030,7 @@ func (cs *State) enterNewRound(height int64, round int32) { if cs.Height != height || round < cs.Round || (cs.Round == round && cs.Step != cstypes.RoundStepNewHeight) { logger.Debug( "entering new round with invalid args", - "current", fmt.Sprintf("%v/%v/%v", cs.Height, cs.Round, cs.Step), + "current", log.NewLazySprintf("%v/%v/%v", cs.Height, cs.Round, cs.Step), ) return } @@ -1040,7 +1040,7 @@ func (cs *State) enterNewRound(height int64, round int32) { logger.Debug("need to set a buffer and log message here for sanity", "start_time", cs.StartTime, "now", now) } - logger.Debug("entering new round", "current", fmt.Sprintf("%v/%v/%v", cs.Height, cs.Round, cs.Step)) + logger.Debug("entering new round", "current", log.NewLazySprintf("%v/%v/%v", cs.Height, cs.Round, cs.Step)) // Select the current height and round Proposer cs.Proposer = cs.Validators.SelectProposer(cs.state.LastProofHash, height, round) @@ -1108,12 +1108,12 @@ func (cs *State) enterPropose(height int64, round int32) { if cs.Height != height || round < cs.Round || (cs.Round == round && cstypes.RoundStepPropose <= cs.Step) { logger.Debug( "entering propose step with invalid args", - "current", fmt.Sprintf("%v/%v/%v", cs.Height, cs.Round, cs.Step), + "current", log.NewLazySprintf("%v/%v/%v", cs.Height, cs.Round, cs.Step), ) return } - logger.Debug("entering propose step", "current", fmt.Sprintf("%v/%v/%v", cs.Height, cs.Round, cs.Step)) + logger.Debug("entering propose step", "current", log.NewLazySprintf("%v/%v/%v", cs.Height, cs.Round, cs.Step)) defer func() { // Done enterPropose: @@ -1286,7 +1286,7 @@ func (cs *State) enterPrevote(height int64, round int32) { if cs.Height != height || round < cs.Round || (cs.Round == round && cstypes.RoundStepPrevote <= cs.Step) { logger.Debug( "entering prevote step with invalid args", - "current", fmt.Sprintf("%v/%v/%v", cs.Height, cs.Round, cs.Step), + "current", log.NewLazySprintf("%v/%v/%v", cs.Height, cs.Round, cs.Step), ) return } @@ -1297,7 +1297,7 @@ func (cs *State) enterPrevote(height int64, round int32) { cs.newStep() }() - logger.Debug("entering prevote step", "current", fmt.Sprintf("%v/%v/%v", cs.Height, cs.Round, cs.Step)) + logger.Debug("entering prevote step", "current", log.NewLazySprintf("%v/%v/%v", cs.Height, cs.Round, cs.Step)) // Sign and broadcast vote as necessary cs.stepTimes.ToPrevoteStep() @@ -1350,7 +1350,7 @@ func (cs *State) enterPrevoteWait(height int64, round int32) { if cs.Height != height || round < cs.Round || (cs.Round == round && cstypes.RoundStepPrevoteWait <= cs.Step) { logger.Debug( "entering prevote wait step with invalid args", - "current", fmt.Sprintf("%v/%v/%v", cs.Height, cs.Round, cs.Step), + "current", log.NewLazySprintf("%v/%v/%v", cs.Height, cs.Round, cs.Step), ) return } @@ -1362,7 +1362,7 @@ func (cs *State) enterPrevoteWait(height int64, round int32) { )) } - logger.Debug("entering prevote wait step", "current", fmt.Sprintf("%v/%v/%v", cs.Height, cs.Round, cs.Step)) + logger.Debug("entering prevote wait step", "current", log.NewLazySprintf("%v/%v/%v", cs.Height, cs.Round, cs.Step)) defer func() { // Done enterPrevoteWait: @@ -1386,12 +1386,12 @@ func (cs *State) enterPrecommit(height int64, round int32) { if cs.Height != height || round < cs.Round || (cs.Round == round && cstypes.RoundStepPrecommit <= cs.Step) { logger.Debug( "entering precommit step with invalid args", - "current", fmt.Sprintf("%v/%v/%v", cs.Height, cs.Round, cs.Step), + "current", log.NewLazySprintf("%v/%v/%v", cs.Height, cs.Round, cs.Step), ) return } - logger.Debug("entering precommit step", "current", fmt.Sprintf("%v/%v/%v", cs.Height, cs.Round, cs.Step)) + logger.Debug("entering precommit step", "current", log.NewLazySprintf("%v/%v/%v", cs.Height, cs.Round, cs.Step)) defer func() { // Done enterPrecommit: @@ -1512,7 +1512,7 @@ func (cs *State) enterPrecommitWait(height int64, round int32) { logger.Debug( "entering precommit wait step with invalid args", "triggered_timeout", cs.TriggeredTimeoutPrecommit, - "current", fmt.Sprintf("%v/%v", cs.Height, cs.Round), + "current", log.NewLazySprintf("%v/%v", cs.Height, cs.Round), ) return } @@ -1524,7 +1524,7 @@ func (cs *State) enterPrecommitWait(height int64, round int32) { )) } - logger.Debug("entering precommit wait step", "current", fmt.Sprintf("%v/%v/%v", cs.Height, cs.Round, cs.Step)) + logger.Debug("entering precommit wait step", "current", log.NewLazySprintf("%v/%v/%v", cs.Height, cs.Round, cs.Step)) defer func() { // Done enterPrecommitWait: @@ -1543,12 +1543,12 @@ func (cs *State) enterCommit(height int64, commitRound int32) { if cs.Height != height || cstypes.RoundStepCommit <= cs.Step { logger.Debug( "entering commit step with invalid args", - "current", fmt.Sprintf("%v/%v/%v", cs.Height, cs.Round, cs.Step), + "current", log.NewLazySprintf("%v/%v/%v", cs.Height, cs.Round, cs.Step), ) return } - logger.Debug("entering commit step", "current", fmt.Sprintf("%v/%v/%v", cs.Height, cs.Round, cs.Step)) + logger.Debug("entering commit step", "current", log.NewLazySprintf("%v/%v/%v", cs.Height, cs.Round, cs.Step)) defer func() { // Done enterCommit: @@ -1581,7 +1581,7 @@ func (cs *State) enterCommit(height int64, commitRound int32) { if !cs.ProposalBlockParts.HasHeader(blockID.PartSetHeader) { logger.Info( "commit is for a block we do not know about; set ProposalBlock=nil", - "proposal", cs.ProposalBlock.Hash(), + "proposal", log.NewLazyBlockHash(cs.ProposalBlock), "commit", blockID.Hash, ) @@ -1618,7 +1618,7 @@ func (cs *State) tryFinalizeCommit(height int64) { // TODO: ^^ wait, why does it matter that we're a validator? logger.Debug( "failed attempt to finalize commit; we do not have the commit block", - "proposal_block", cs.ProposalBlock.Hash(), + "proposal_block", log.NewLazyBlockHash(cs.ProposalBlock), "commit_block", blockID.Hash, ) return @@ -1634,7 +1634,7 @@ func (cs *State) finalizeCommit(height int64) { if cs.Height != height || cs.Step != cstypes.RoundStepCommit { logger.Debug( "entering finalize commit step", - "current", fmt.Sprintf("%v/%v/%v", cs.Height, cs.Round, cs.Step), + "current", log.NewLazySprintf("%v/%v/%v", cs.Height, cs.Round, cs.Step), ) return } @@ -1659,11 +1659,11 @@ func (cs *State) finalizeCommit(height int64) { logger.Info( "finalizing commit of block", - "hash", block.Hash(), + "hash", log.NewLazyBlockHash(block), "root", block.AppHash, "num_txs", len(block.Txs), ) - logger.Debug(fmt.Sprintf("%v", block)) + logger.Debug("committed block", "block", log.NewLazySprintf("%v", block)) fail.Fail() // XXX @@ -2018,7 +2018,7 @@ func (cs *State) handleCompleteProposal(blockHeight int64) { cs.Logger.Debug( "updating valid block to new proposal block", "valid_round", cs.Round, - "valid_block_hash", cs.ProposalBlock.Hash(), + "valid_block_hash", log.NewLazyBlockHash(cs.ProposalBlock), ) cs.ValidRound = cs.Round @@ -2193,7 +2193,7 @@ func (cs *State) addVote(vote *types.Vote, peerID p2p.ID) (added bool, err error } else { cs.Logger.Debug( "valid block we do not know about; set ProposalBlock=nil", - "proposal", cs.ProposalBlock.Hash(), + "proposal", log.NewLazyBlockHash(cs.ProposalBlock), "block_id", blockID.Hash, ) diff --git a/evidence/mocks/block_store.go b/evidence/mocks/block_store.go index a7a47e962..5377b61f2 100644 --- a/evidence/mocks/block_store.go +++ b/evidence/mocks/block_store.go @@ -58,13 +58,12 @@ func (_m *BlockStore) LoadBlockMeta(height int64) *types.BlockMeta { return r0 } -type mockConstructorTestingTNewBlockStore interface { +// NewBlockStore creates a new instance of BlockStore. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewBlockStore(t interface { mock.TestingT Cleanup(func()) -} - -// NewBlockStore creates a new instance of BlockStore. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewBlockStore(t mockConstructorTestingTNewBlockStore) *BlockStore { +}) *BlockStore { mock := &BlockStore{} mock.Mock.Test(t) diff --git a/go.mod b/go.mod index 936676918..0c738651e 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( github.com/spf13/viper v1.16.0 github.com/stretchr/testify v1.8.4 github.com/tendermint/go-amino v0.16.0 - github.com/tendermint/tendermint v0.34.19 + github.com/tendermint/tendermint v0.34.20 github.com/tendermint/tm-db v0.6.7 github.com/yahoo/coname v0.0.0-20170609175141-84592ddf8673 // indirect golang.org/x/crypto v0.11.0 @@ -48,8 +48,11 @@ require ( github.com/Finschia/r2ishiguro_vrf v0.1.2 github.com/bufbuild/buf v1.25.0 github.com/golangci/golangci-lint v1.53.3 + github.com/klauspost/pgzip v1.2.6 // indirect github.com/oasisprotocol/curve25519-voi v0.0.0-20230110094441-db37f07504ce + github.com/prometheus/common v0.42.0 // indirect github.com/rs/zerolog v1.29.1 + github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca github.com/vektra/mockery/v2 v2.32.0 gopkg.in/natefinch/lumberjack.v2 v2.2.1 ) @@ -81,7 +84,6 @@ require ( github.com/breml/bidichk v0.2.4 // indirect github.com/breml/errchkjson v0.3.1 // indirect github.com/bufbuild/connect-go v1.9.0 // indirect - github.com/bufbuild/connect-opentelemetry-go v0.4.0 // indirect github.com/bufbuild/protocompile v0.5.1 // indirect github.com/butuzov/ireturn v0.2.0 // indirect github.com/butuzov/mirror v1.1.0 // indirect @@ -131,7 +133,7 @@ require ( github.com/go-xmlfmt/xmlfmt v1.1.2 // indirect github.com/gobwas/glob v0.2.3 // indirect github.com/gofrs/flock v0.8.1 // indirect - github.com/gofrs/uuid/v5 v5.0.0 // indirect + github.com/gofrs/uuid v4.4.0+incompatible // indirect github.com/golang/snappy v0.0.3 // indirect github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 // indirect github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a // indirect @@ -170,7 +172,6 @@ require ( github.com/kisielk/gotool v1.0.0 // indirect github.com/kkHAIKE/contextcheck v1.1.4 // indirect github.com/klauspost/compress v1.16.7 // indirect - github.com/klauspost/pgzip v1.2.6 // indirect github.com/kulti/thelper v0.6.3 // indirect github.com/kunwardeep/paralleltest v1.0.7 // indirect github.com/kyoh86/exportloopref v0.1.11 // indirect @@ -210,7 +211,6 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/polyfloyd/go-errorlint v1.4.2 // indirect github.com/prometheus/client_model v0.3.0 // indirect - github.com/prometheus/common v0.42.0 // indirect github.com/prometheus/procfs v0.10.1 // indirect github.com/quasilyte/go-ruleguard v0.3.19 // indirect github.com/quasilyte/gogrep v0.5.0 // indirect @@ -238,11 +238,9 @@ require ( github.com/stbenjam/no-sprintf-host-port v0.1.1 // indirect github.com/stretchr/objx v0.5.0 // indirect github.com/subosito/gotenv v1.4.2 // indirect - github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca // indirect github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c // indirect github.com/tdakkota/asciicheck v0.2.0 // indirect github.com/tetafro/godot v1.4.11 // indirect - github.com/tetratelabs/wazero v1.3.0 // indirect github.com/timakin/bodyclose v0.0.0-20230421092635-574207250966 // indirect github.com/timonwong/loggercheck v0.9.4 // indirect github.com/tomarrell/wrapcheck/v2 v2.8.1 // indirect @@ -258,7 +256,6 @@ require ( gitlab.com/bosi/decorder v0.2.3 // indirect go.etcd.io/bbolt v1.3.6 // indirect go.opentelemetry.io/otel v1.16.0 // indirect - go.opentelemetry.io/otel/metric v1.16.0 // indirect go.opentelemetry.io/otel/sdk v1.16.0 // indirect go.opentelemetry.io/otel/trace v1.16.0 // indirect go.tmz.dev/musttag v0.7.0 // indirect @@ -283,3 +280,15 @@ require ( mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b // indirect mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d // indirect ) + +// This is a "replace" directive for "golang-v1.18". If upgrading to golang-v1.19, we can remove +replace ( + github.com/bufbuild/buf => github.com/bufbuild/buf v1.14.0 + github.com/bufbuild/connect-go => github.com/bufbuild/connect-go v1.5.0 + github.com/docker/cli => github.com/docker/cli v24.0.2+incompatible + github.com/docker/docker-credential-helpers => github.com/docker/docker-credential-helpers v0.7.0 + github.com/google/go-containerregistry => github.com/google/go-containerregistry v0.13.0 + go.opentelemetry.io/otel => go.opentelemetry.io/otel v1.12.0 + go.opentelemetry.io/otel/sdk => go.opentelemetry.io/otel/sdk v1.12.0 + go.uber.org/multierr => go.uber.org/multierr v1.8.0 +) diff --git a/go.sum b/go.sum index fdef9eb9a..eb8f2c86c 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,9 @@ 4d63.com/gocheckcompilerdirectives v1.2.1 h1:AHcMYuw56NPjq/2y615IGg2kYkBdTvOaojYCBcRE7MA= 4d63.com/gocheckcompilerdirectives v1.2.1/go.mod h1:yjDJSxmDTtIHHCqX0ufRYZDL6vQtMG7tJdKVeWwsqvs= +4d63.com/gochecknoglobals v0.1.0/go.mod h1:wfdC5ZjKSPr7CybKEcgJhUOgeAQW1+7WcyK8OvUilfo= 4d63.com/gochecknoglobals v0.2.1 h1:1eiorGsgHOFOuoOiJDy2psSrQbRdIHrlge0IJIkUgDc= 4d63.com/gochecknoglobals v0.2.1/go.mod h1:KRE8wtJB3CXCsb1xy421JfTHIIbmT3U5ruxw2Qu8fSU= -bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM= +bitbucket.org/creachadair/shell v0.0.6/go.mod h1:8Qqi/cYk7vPnsOePHroKXDJYmb5x7ENhtiFtfZq8K+M= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -17,6 +18,7 @@ cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6 cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.60.0/go.mod h1:yw2G51M9IfRboUH61Us8GqCeF1PzPblB823Mn2q2eAU= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= @@ -32,42 +34,65 @@ cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aD cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= +cloud.google.com/go v0.98.0/go.mod h1:ua6Ush4NALrHk5QXDWnjvZHN93OuF0HfuEPq9I1X0cM= cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= +cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= +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/asset v1.5.0/go.mod h1:5mfs8UvcM5wHhqtSv8J1CtxxaQq3AdBxxQi2jGW/K4o= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= +cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= +cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= +cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= +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/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY= +cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/pubsub v1.5.0/go.mod h1:ZEwJccE3z93Z2HWvstpri00jOg7oO4UZDtKhwDwqF0w= +cloud.google.com/go/security v1.5.0/go.mod h1:lgxGdyOKKjHL4YG3/YwIL2zLqMFCKs0UbQwgyZmfJl4= +cloud.google.com/go/spanner v1.7.0/go.mod h1:sd3K2gZ9Fd0vMPLXzeCrF6fq4i63Q7aTLW/lBIfBkIk= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= 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= +contrib.go.opencensus.io/exporter/stackdriver v0.13.4/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/4meepo/tagalign v1.2.2 h1:kQeUTkFTaBRtd/7jm8OKJl9iHk0gAO+TDFPHGSna0aw= github.com/4meepo/tagalign v1.2.2/go.mod h1:Q9c1rYMZJc9dPRkbQPpcBNCLEmY2njbAsXhQOZFE2dE= github.com/Abirdcfly/dupword v0.0.11 h1:z6v8rMETchZXUIuHxYNmlUAuKuB21PeaSymTed16wgU= github.com/Abirdcfly/dupword v0.0.11/go.mod h1:wH8mVGuf3CP5fsBTkfWwwwKTjDnVVCxtU8d8rgeVYXA= +github.com/Antonboom/errname v0.1.6/go.mod h1:7lz79JAnuoMNDAWE9MeeIr1/c/VpSUWatBv2FH9NYpI= github.com/Antonboom/errname v0.1.10 h1:RZ7cYo/GuZqjr1nuJLNe8ZH+a+Jd9DaZzttWzak9Bls= github.com/Antonboom/errname v0.1.10/go.mod h1:xLeiCIrvVNpUtsN0wxAh05bNIZpqE22/qDMnTBTttiA= +github.com/Antonboom/nilnil v0.1.1/go.mod h1:L1jBqoWM7AOeTD+tSquifKSesRHs4ZdaxvZR+xdJEaI= github.com/Antonboom/nilnil v0.1.5 h1:X2JAdEVcbPaOom2TUa1FxZ3uyuUlex0XMLGYMemu6l0= github.com/Antonboom/nilnil v0.1.5/go.mod h1:I24toVuBKhfP5teihGWctrRiPbRKHwZIFOvc6v3HZXk= github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0/go.mod h1:h6H6c8enJmmocHUbLiiGY6sx7f9i+X3m1CHdd5c6Rdw= github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0/go.mod h1:HcM1YX14R7CJcghJGOYCgdezslRSVzqwLf/q+4Y2r/0= github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +github.com/Azure/go-ansiterm v0.0.0-20210608223527-2377c96fe795/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= 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 v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= @@ -84,20 +109,27 @@ github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 h1:sHglBQTwgx+rW github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= github.com/Finschia/r2ishiguro_vrf v0.1.2 h1:lDBz6NQMx1pw5I3End6xFmXpM//7KcmTr3Ka983e7v8= github.com/Finschia/r2ishiguro_vrf v0.1.2/go.mod h1:OHRtvzcJnfIrcJ0bvPNktJozRFAyZFuv56E9R3/qB+Y= +github.com/GaijinEntertainment/go-exhaustruct/v2 v2.1.0/go.mod h1:LGOGuvEgCfCQsy3JF2tRmpGDpzA53iZfyGEWSPwQ6/4= github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0 h1:+r1rSv4gvYn0wmRjC8X7IAzX8QezqtFV9m0MUHFJgts= github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0/go.mod h1:b3g59n2Y+T5xmcxJL+UEG2f8cQploZm1mR/v6BW0mU0= github.com/HdrHistogram/hdrhistogram-go v1.1.0/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= +github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= -github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Masterminds/sprig v2.15.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= +github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= +github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= +github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE= 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/OpenPeeDeeP/depguard v1.1.0/go.mod h1:JtAMzWkmFEzDPyAd+W0NHl1lvpQKTvT9jnRVsohBKpc= github.com/OpenPeeDeeP/depguard/v2 v2.1.0 h1:aQl70G173h/GZYhWf36aE5H0KaujXfVMnn/f1kSDVYY= github.com/OpenPeeDeeP/depguard/v2 v2.1.0/go.mod h1:PUBgk35fX4i7JDmwzlJwJ+GMe6NfO1723wmJMgPThNQ= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= @@ -107,7 +139,7 @@ github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/ github.com/Workiva/go-datastructures v1.0.53/go.mod h1:1yZL+zfsztete+ePzZz/Zb1/t5BnDuE2Ya2MMGhzP6A= github.com/Workiva/go-datastructures v1.1.0 h1:hu20UpgZneBhQ3ZvwiOGlqJSKIosin2Rd5wAKUHEO/k= github.com/Workiva/go-datastructures v1.1.0/go.mod h1:1yZL+zfsztete+ePzZz/Zb1/t5BnDuE2Ya2MMGhzP6A= -github.com/adlio/schema v1.3.0/go.mod h1:51QzxkpeFs6lRY11kPye26IaFPOV+HqEj01t5aXXKfs= +github.com/adlio/schema v1.3.3/go.mod h1:1EsRssiv9/Ce2CMzq5DoL7RiMshhuigQxrR4DMV9fHg= github.com/adlio/schema v1.3.4 h1:8K+41sfQkxfT6a79aLBxx+dBKcid6Raw2JPk5COqeqE= github.com/adlio/schema v1.3.4/go.mod h1:gFMaHYzLkZRfaIqZ5u96LLXPt+DdXSFWUwtr6YBz0kk= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= @@ -124,7 +156,11 @@ github.com/alexkohler/prealloc v1.0.0 h1:Hbq0/3fJPQhNkN0dR95AVrr6R7tou91y0uHG5pO github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQRnw= github.com/alingse/asasalint v0.0.11/go.mod h1:nCaoMhw7a9kSJObvQyVzNTPBDbNpdocqrSP7t/cW5+I= +github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= +github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/aokoli/goutils v1.0.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ= github.com/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= @@ -132,37 +168,45 @@ github.com/armon/go-metrics v0.3.9/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4 github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/ashanbrown/forbidigo v1.3.0/go.mod h1:vVW7PEdqEFqapJe95xHkTfB1+XvZXBFg8t0sG2FIxmI= github.com/ashanbrown/forbidigo v1.5.3 h1:jfg+fkm/snMx+V9FBwsl1d340BV/99kZGv5jN9hBoXk= github.com/ashanbrown/forbidigo v1.5.3/go.mod h1:Y8j9jy9ZYAEHXdu723cUlraTqbzjKF1MUyfOKL+AjcU= github.com/ashanbrown/makezero v1.1.1 h1:iCQ87C0V0vSyO+M9E/FZYbu65auqH0lnsOkf5FcB28s= github.com/ashanbrown/makezero v1.1.1/go.mod h1:i1bJLCRSCHOcOa9Y6MyF2FTfMZMFdHvxKHxgO5Z1axI= +github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.25.37/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.36.30/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/aws/aws-sdk-go v1.40.45/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= github.com/aws/aws-sdk-go-v2 v1.9.1/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4= github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.8.1/go.mod h1:CM+19rL1+4dFWnOQKwDc7H1KwXTz+h61oUSHyhV0b3o= github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= +github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= +github.com/benbjohnson/clock v1.3.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= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= +github.com/bkielbasa/cyclop v1.2.0/go.mod h1:qOI0yy6A7dYC4Zgsa72Ppm9kONl0RoIlPbzot9mhmeI= github.com/bkielbasa/cyclop v1.2.1 h1:AeF71HZDob1P2/pRm1so9cd1alZnrpyc4q2uP2l0gJY= github.com/bkielbasa/cyclop v1.2.1/go.mod h1:K/dT/M0FPAiYjBgQGau7tz+3TMh4FWAEqlMhzFWCrgM= github.com/blizzy78/varnamelen v0.8.0 h1:oqSblyuQvFsW1hbBHh1zfwrKe3kcSj0rnXkKzsQ089M= github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k= +github.com/bombsimon/wsl/v3 v3.3.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc= github.com/bombsimon/wsl/v3 v3.4.0 h1:RkSxjT3tmlptwfgEgTgU+KYKLI35p/tviNXNXiL2aNU= github.com/bombsimon/wsl/v3 v3.4.0/go.mod h1:KkIB+TXkqy6MvK9BDZVbZxKNYsE1/oLRJbIFtf14qqo= +github.com/breml/bidichk v0.2.3/go.mod h1:8u2C6DnAy0g2cEq+k/A2+tr9O1s+vHGxWn0LTc70T2A= github.com/breml/bidichk v0.2.4 h1:i3yedFWWQ7YzjdZJHnPo9d/xURinSq3OM+gyM43K4/8= github.com/breml/bidichk v0.2.4/go.mod h1:7Zk0kRFt1LIZxtQdl9W9JwGAcLTTkOs+tN7wuEYGJ3s= +github.com/breml/errchkjson v0.3.0/go.mod h1:9Cogkyv9gcT8HREpzi3TiqBxCqDzo8awa92zSDFcofU= github.com/breml/errchkjson v0.3.1 h1:hlIeXuspTyt8Y/UmP5qy1JocGNR00KQHgfaNtRAjoxQ= github.com/breml/errchkjson v0.3.1/go.mod h1:XroxrzKjdiutFyW3nWhw34VGg7kiMsDQox73yWCGI2U= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= -github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= github.com/btcsuite/btcd v0.22.1/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce h1:YtWJF7RHm2pYCvA5t0RPmAaLUhREsKuKd+SLhxFbFeQ= @@ -174,14 +218,14 @@ 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/buf v1.25.0 h1:HFxKrR8wFcZwrBInN50K/oJX/WOtPVq24rHb/ArjfBA= -github.com/bufbuild/buf v1.25.0/go.mod h1:GCKZ5bAP6Ht4MF7KcfaGVgBEXGumwAz2hXjjLVxx8ZU= -github.com/bufbuild/connect-go v1.9.0 h1:JIgAeNuFpo+SUPfU19Yt5TcWlznsN5Bv10/gI/6Pjoc= -github.com/bufbuild/connect-go v1.9.0/go.mod h1:CAIePUgkDR5pAFaylSMtNK45ANQjp9JvpluG20rhpV8= -github.com/bufbuild/connect-opentelemetry-go v0.4.0 h1:6JAn10SNqlQ/URhvRNGrIlczKw1wEXknBUUtmWqOiak= -github.com/bufbuild/connect-opentelemetry-go v0.4.0/go.mod h1:nwPXYoDOoc2DGyKE/6pT1Q9MPSi2Et2e6BieMD0l6WU= +github.com/bufbuild/buf v1.14.0 h1:BSpRDgxC8jKwV+XJXyVuB0PM1na/qL80rNAgzb1PZnU= +github.com/bufbuild/buf v1.14.0/go.mod h1:Z5FtbEZtMdog6dGRZdCvIZTc6lPYaCz3AONEPmXNkyk= +github.com/bufbuild/connect-go v1.5.0 h1:IfbgbzzaaZvF+OM3SfxO2EjtvNJarNAz2DIRuuNjAgc= +github.com/bufbuild/connect-go v1.5.0/go.mod h1:9iNvh/NOsfhNBUH5CtvXeVUskQO1xsrEviH7ZArwZ3I= +github.com/bufbuild/protocompile v0.2.0/go.mod h1:tleDrpPTlLUVmgnEoN6qBliKWqJaZFJXqZdFjTd+ocU= github.com/bufbuild/protocompile v0.5.1 h1:mixz5lJX4Hiz4FpqFREJHIXLfaLBntfaJv1h+/jS+Qg= github.com/bufbuild/protocompile v0.5.1/go.mod h1:G5iLmavmF4NsYtpZFvE3B/zFch2GIY8+wjsYLR/lc40= +github.com/butuzov/ireturn v0.1.1/go.mod h1:Wh6Zl3IMtTpaIKbmwzqi6olnM9ptYQxxVacMsOEFPoc= github.com/butuzov/ireturn v0.2.0 h1:kCHi+YzC150GE98WFuZQu9yrTn6GEydO2AuPLbTgnO4= github.com/butuzov/ireturn v0.2.0/go.mod h1:Wh6Zl3IMtTpaIKbmwzqi6olnM9ptYQxxVacMsOEFPoc= github.com/butuzov/mirror v1.1.0 h1:ZqX54gBVMXu78QLoiqdwpl2mgmoOJTk7s4p4o+0avZI= @@ -191,6 +235,7 @@ github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEe github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= +github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= @@ -199,18 +244,21 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/charithe/durationcheck v0.0.9/go.mod h1:SSbRIBVfMjCi/kEB6K65XEA83D6prSM8ap1UCpNKtgg= github.com/charithe/durationcheck v0.0.10 h1:wgw73BiocdBDQPik+zcEoBG/ob8uyBHf2iyoHGPf5w4= github.com/charithe/durationcheck v0.0.10/go.mod h1:bCWXb7gYRysD1CU3C+u4ceO49LoGOY1C1L6uouGNreQ= +github.com/chavacava/garif v0.0.0-20220316182200-5cad0b5181d4/go.mod h1:W8EnPSQ8Nv4fUjc/v1/8tHFqhuOJXnRub0dTfuAQktU= github.com/chavacava/garif v0.0.0-20230227094218-b8c73b2037b8 h1:W9o46d2kbNL06lq7UNDPV0zYLzkrde/bjIqO02eoll0= github.com/chavacava/garif v0.0.0-20230227094218-b8c73b2037b8/go.mod h1:gakxgyXaaPkxvLw1XQxNGK4I37ys9iBRzNUx/B7pUCo= -github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= github.com/chigopher/pathlib v0.15.0 h1:1pg96WL3iC1/YyWV4UJSl3E0GBf4B+h5amBtsbAAieY= github.com/chigopher/pathlib v0.15.0/go.mod h1:3+YPPV21mU9vyw8Mjp+F33CyCfE6iOzinpiqBcccv7I= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= +github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= @@ -226,21 +274,23 @@ github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWH 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-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= -github.com/containerd/continuity v0.2.1/go.mod h1:wCYX+dRqZdImhGucXOqTQn05AhX6EUDaGEMUzTFFpLg= github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= +github.com/containerd/stargz-snapshotter/estargz v0.12.1/go.mod h1:12VUuCq3qPq4y8yUW+l5w3+oXV3cx2Po3KSe/SmPGqw= github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k= github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= 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/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190620071333-e64a0ec8b42a/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d h1:49RLWk1j44Xu4fjHb6JFYmeUnDORVwHNkDxaQ0ctCVU= github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= @@ -252,14 +302,19 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsr github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= 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/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/curioswitch/go-reassign v0.2.0 h1:G9UZyOcpk/d7Gd6mqYgd8XYWFMw/znxwGDUstnC9DIo= github.com/curioswitch/go-reassign v0.2.0/go.mod h1:x6OpXuWvgfQaMGks2BZybTngWjT84hqJfKoO8Tt/Roc= -github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= +github.com/daixiang0/gci v0.3.3/go.mod h1:1Xr2bxnQbDxCqqulUOv8qpGqkgRw9RSCGGjEC2LjF8o= github.com/daixiang0/gci v0.10.1 h1:eheNA3ljF6SxnPD/vE4lCBusVHmV3Rs3dkKvFrJ7MR0= github.com/daixiang0/gci v0.10.1/go.mod h1:xtHP9N7AHdNvtRNfcx9gwTDfw7FRJx4bZUsiEfiNNAI= +github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= +github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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= @@ -276,21 +331,26 @@ github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de/go.mod h1:KP github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= -github.com/docker/cli v24.0.4+incompatible h1:Y3bYF9ekNTm2VFz5U/0BlMdJy73D+Y1iAAZ8l63Ydzw= -github.com/docker/cli v24.0.4+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v24.0.2+incompatible h1:QdqR7znue1mtkXIJ+ruQMGQhpw2JzMJLRXp6zpzF6tM= +github.com/docker/cli v24.0.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= 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/docker/docker v20.10.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v20.10.17+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v20.10.20+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v23.0.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v24.0.4+incompatible h1:s/LVDftw9hjblvqIeTiGYXBCD95nOEEl7qRsRrIOuQI= github.com/docker/docker v24.0.4+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker-credential-helpers v0.8.0 h1:YQFtbBQb4VrpoPxhFuzEBPQ9E16qz5SpHLS+uswaCp8= -github.com/docker/docker-credential-helpers v0.8.0/go.mod h1:UGFXcuoQ5TxPiB54nHOZ32AWRqQdECoh/Mg0AlEYb40= +github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= +github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= 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.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= 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 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= @@ -306,6 +366,8 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.m github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= 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.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ= +github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= +github.com/envoyproxy/protoc-gen-validate v0.0.14/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws= github.com/esimonov/ifshort v1.0.4 h1:6SID4yGWfRae/M7hkVDVVyppy8q/v9OuxNdmjLQStBA= @@ -320,6 +382,7 @@ github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870/go.mod h1:5tD+ne github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= @@ -328,6 +391,7 @@ github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4 github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g= github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw= +github.com/firefart/nonamedreturns v1.0.1/go.mod h1:D3dpIBojGGNh5UfElmwPu73SwDCm+VKhHYqwlNOk2uQ= github.com/firefart/nonamedreturns v1.0.4 h1:abzI1p7mAEPYuR4A+VLKn4eNDOycjYo2phmY9sfv40Y= github.com/firefart/nonamedreturns v1.0.4/go.mod h1:TDhe/tjI1BXo48CmYbUduTV7BdIga8MAO/xbKdcVsGI= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= @@ -336,17 +400,24 @@ github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHqu github.com/franela/goblin v0.0.0-20210519012713-85d372ac71e2/go.mod h1:VzmDKDJVZI3aJmnRI9VjAn9nJ8qPPsN1fqzr9dqInIo= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= +github.com/frankban/quicktest v1.14.2/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= +github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= +github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/fullstorydev/grpcurl v1.6.0/go.mod h1:ZQ+ayqbKMJNhzLmbpCiurTVlaK2M/3nqZCxaQ2Ze/sM= +github.com/fzipp/gocyclo v0.5.1/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk= github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/go-critic/go-critic v0.6.3/go.mod h1:c6b3ZP1MQ7o6lPR7Rv3lEf7pYQUmAcx8ABHgdZCQt/k= github.com/go-critic/go-critic v0.8.1 h1:16omCF1gN3gTzt4j4J6fKI/HnRojhEp+Eks6EuKw3vw= github.com/go-critic/go-critic v0.8.1/go.mod h1:kpzXl09SIJX1cr9TB/g/sAG+eFEl7ZS9f9cqvZtyNl0= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= @@ -367,32 +438,46 @@ github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KE 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/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/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/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-redis/redis v6.15.8+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4= github.com/go-toolsmith/astcast v1.1.0 h1:+JN9xZV1A+Re+95pgnMgDboWNVnIMMQXwfBwLRPgSC8= github.com/go-toolsmith/astcast v1.1.0/go.mod h1:qdcuFWeGGS2xX5bLM/c3U9lewg7+Zu4mr+xPwZIB4ZU= +github.com/go-toolsmith/astcopy v1.0.0/go.mod h1:vrgyG+5Bxrnz4MZWPF+pI4R8h3qKRjjyvV/DSez4WVQ= github.com/go-toolsmith/astcopy v1.1.0 h1:YGwBN0WM+ekI/6SS6+52zLDEf8Yvp3n2seZITCUBt5s= github.com/go-toolsmith/astcopy v1.1.0/go.mod h1:hXM6gan18VA1T/daUEHCFcYiW8Ai1tIwIzHY6srfEAw= +github.com/go-toolsmith/astequal v1.0.0/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= +github.com/go-toolsmith/astequal v1.0.1/go.mod h1:4oGA3EZXTVItV/ipGiOx7NWkY5veFfcsOJVS2YxltLw= github.com/go-toolsmith/astequal v1.0.3/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/OXVTSLnCyTAx4= github.com/go-toolsmith/astequal v1.1.0 h1:kHKm1AWqClYn15R0K1KKE4RG614D46n+nqUQ06E1dTw= github.com/go-toolsmith/astequal v1.1.0/go.mod h1:sedf7VIdCL22LD8qIvv7Nn9MuWJruQA/ysswh64lffQ= +github.com/go-toolsmith/astfmt v1.0.0/go.mod h1:cnWmsOAuq4jJY6Ct5YWlVLmcmLMn1JUPuQIHCY7CJDw= github.com/go-toolsmith/astfmt v1.1.0 h1:iJVPDPp6/7AaeLJEruMsBUlOYCmvg0MoCfJprsOmcco= github.com/go-toolsmith/astfmt v1.1.0/go.mod h1:OrcLlRwu0CuiIBp/8b5PYF9ktGVZUjlNMV634mhwuQ4= +github.com/go-toolsmith/astp v1.0.0/go.mod h1:RSyrtpVlfTFGDYRbrjyWP1pYu//tSFcvdYrA8meBmLI= github.com/go-toolsmith/astp v1.1.0 h1:dXPuCl6u2llURjdPLLDxJeZInAeZ0/eZwFJmqZMnpQA= github.com/go-toolsmith/astp v1.1.0/go.mod h1:0T1xFGz9hicKs8Z5MfAqSUitoUYS30pDMsRVIDHs8CA= +github.com/go-toolsmith/pkgload v1.0.2-0.20220101231613-e814995d17c5/go.mod h1:3NAwwmD4uY/yggRxoEjk/S00MIV3A+H7rrE3i87eYxM= github.com/go-toolsmith/pkgload v1.2.2 h1:0CtmHq/02QhxcF7E9N5LIFcYFsMR5rdovfqTtRKkgIk= github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= github.com/go-toolsmith/strparse v1.1.0 h1:GAioeZUK9TGxnLS+qfdqNbA4z0SSm5zVNtCQiyP2Bvw= github.com/go-toolsmith/strparse v1.1.0/go.mod h1:7ksGy58fsaQkGQlY8WVoBFNyEPMGuJin1rfoPS4lBSQ= +github.com/go-toolsmith/typep v1.0.2/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU= github.com/go-toolsmith/typep v1.1.0 h1:fIRYDyF+JywLfqzyhdiHzRop/GQDxxNhLGQ6gFUNHus= github.com/go-toolsmith/typep v1.1.0/go.mod h1:fVIw+7zjdsMxDA3ITWnH1yOiw1rnTQKCsF/sk2H/qig= +github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= github.com/go-xmlfmt/xmlfmt v1.1.2 h1:Nea7b4icn8s57fTx1M5AI4qQT5HEM3rVUO8MuE6g80U= github.com/go-xmlfmt/xmlfmt v1.1.2/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= github.com/go-zookeeper/zk v1.0.2/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw= @@ -402,10 +487,12 @@ github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= -github.com/gofrs/uuid/v5 v5.0.0 h1:p544++a97kEL+svbcFbCQVM9KFu0Yo25UoISXGNNH9M= -github.com/gofrs/uuid/v5 v5.0.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8= +github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= +github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= @@ -415,7 +502,7 @@ github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188 h1:+eHOFJl1BaXrQ github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188/go.mod h1:vXjM/+wXQnTPR4KqTKDgJukSZ6amVRtWMPEjE6sQoK8= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +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= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -429,6 +516,7 @@ github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -459,16 +547,20 @@ github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a h1:w8hkcTqaFpzKqonE9 github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk= github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe h1:6RGUuS7EGotKx6J5HIP8ZtyMdiDscjMLfRBSPuzVVeo= github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe/go.mod h1:gjqyPShc/m8pEMpk0a3SeagVb0kaqvhscv+i9jI5ZhQ= +github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU= github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2 h1:amWTbTGqOZ71ruzrdA+Nx5WA3tV1N0goTspwmKCQvBY= github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2/go.mod h1:9wOXstvyDRshQ9LggQuzBCGysxs3b6Uo/1MvYCR2NMs= +github.com/golangci/golangci-lint v1.46.2/go.mod h1:3DkdHnxn9eoTTrpT2gB0TEv8KSziuoqe9FitgQLHvAY= github.com/golangci/golangci-lint v1.53.3 h1:CUcRafczT4t1F+mvdkUm6KuOpxUZTl0yWN/rSU6sSMo= github.com/golangci/golangci-lint v1.53.3/go.mod h1:W4Gg3ONq6p3Jl+0s/h9Gr0j7yEgHJWWZO2bHl2tBUXM= github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 h1:MfyDlzVjl1hoaPzPD4Gpb/QgoRfSBR0jdhwGyAWwMSA= github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg= github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca h1:kNY3/svz5T29MYHubXix4aDDuE3RWHkPvopM/EDv/MA= github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o= +github.com/golangci/misspell v0.3.5/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA= github.com/golangci/misspell v0.4.0 h1:KtVB/hTK4bbL/S6bs64rYyk8adjmh1BygbBiaAiX+a0= github.com/golangci/misspell v0.4.0/go.mod h1:W6O/bwV6lGDxUCChm2ykw9NQdd5bYd1Xkjo88UcWyJc= +github.com/golangci/revgrep v0.0.0-20210930125155-c22e5001d4f2/go.mod h1:LK+zW4MpyytAWQRz0M4xnzEk50lSvqDQKfx304apFkY= github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6 h1:DIPQnGy2Gv2FSA4B/hh8Q7xx3B7AIDk3DAMeHclH1vQ= github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6/go.mod h1:0AKcRCkMoKvUvlf89F6O7H2LYdhr1zBh736mBItOdRs= github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 h1:zwtduBRr5SSWhqsYNgcuWO2kFlpdOZbP0+yRjmvPGys= @@ -476,6 +568,8 @@ github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg= +github.com/google/certificate-transparency-go v1.1.1/go.mod h1:FDKqPvSXawb2ecErVRrD+nfy23RCzyl7eqVCEmlT1Zs= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -488,11 +582,12 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 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-containerregistry v0.15.2 h1:MMkSh+tjSdnmJZO7ljvEqV1DjfekB6VUEAZgy3a+TQE= -github.com/google/go-containerregistry v0.15.2/go.mod h1:wWK+LnOv4jXMM23IT/F1wdYftGWGr47Is8CG+pmHK1Q= +github.com/google/go-containerregistry v0.13.0 h1:y1C7Z3e149OJbOPDBxLYR8ITPz8dTKqQwjErKVHJC8k= +github.com/google/go-containerregistry v0.13.0/go.mod h1:J9FQ+eSS4a1aC2GNZxvNpbWhgp0487v+cgiilB4FqDo= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -508,36 +603,62 @@ github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200507031123-427632fa3b1c/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 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-20210407192527-94a9f03dee38/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-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= +github.com/google/pprof v0.0.0-20230131232505-5a9e8f65f08f/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= github.com/google/pprof v0.0.0-20230705174524-200ffdc848b8 h1:n6vlPhxsA+BW/XsS5+uqi7GyzaLa5MH7qlSLBZtRdiA= github.com/google/pprof v0.0.0-20230705174524-200ffdc848b8/go.mod h1:Jh3hGz2jkYak8qXPD19ryItVnUgpgeqzdkY/D0EaeuA= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= +github.com/google/trillian v1.3.11/go.mod h1:0tPraVHrSDkA3BO6vKX67zgLXs6SsOAbHEivX+9mPgw= +github.com/google/uuid v0.0.0-20161128191214-064e2069ce9c/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.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/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= github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= +github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= +github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= +github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= +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/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU= +github.com/gordonklaus/ineffassign v0.0.0-20210914165742-4cc7213b9bc8/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0= github.com/gordonklaus/ineffassign v0.0.0-20230610083614-0e73809eb601 h1:mrEEilTAUmaAORhssPPkxj84TsHrPMLBGW2Z4SoTxm8= github.com/gordonklaus/ineffassign v0.0.0-20230610083614-0e73809eb601/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0= +github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75/go.mod h1:g2644b03hfBX9Ov0ZBDgXXens4rxSxmqFBbhvKv2yVA= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +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/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= +github.com/gostaticanalysis/analysisutil v0.0.3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= +github.com/gostaticanalysis/analysisutil v0.1.0/go.mod h1:dMhHRU9KTiDcuLGdy87/2gTR8WruwYZrKdRq9m1O6uw= +github.com/gostaticanalysis/analysisutil v0.4.1/go.mod h1:18U/DLpRgIUd459wGxVHE0fRgmo1UgHDcbw7F5idXu0= github.com/gostaticanalysis/analysisutil v0.7.1 h1:ZMCjoue3DtDWQ5WyU16YbjbQEQ3VuzwxALrpYd+HeKk= github.com/gostaticanalysis/analysisutil v0.7.1/go.mod h1:v21E3hY37WKMGSnbsw2S/ojApNWb6C1//mXO48CXbVc= +github.com/gostaticanalysis/comment v1.3.0/go.mod h1:xMicKDx7XRXYdVwY9f9wQpDJVnqWxw9wCauCMKp+IBI= github.com/gostaticanalysis/comment v1.4.1/go.mod h1:ih6ZxzTHLdadaiSnF5WY3dxUoXfXAlTaRzuaNDlSado= github.com/gostaticanalysis/comment v1.4.2 h1:hlnx5+S2fY9Zo9ePo4AhgYsYHbM2+eAv8m/s1JiCd6Q= github.com/gostaticanalysis/comment v1.4.2/go.mod h1:KLUTGDv6HOCotCH8h2erHKmpci2ZoR8VPu34YA2uzdM= @@ -547,11 +668,15 @@ github.com/gostaticanalysis/nilerr v0.1.1 h1:ThE+hJP0fEp4zWLkWHWcRyI2Od0p7DlgYG3 github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW0HU0GPE3+5PWN4A= github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= github.com/gostaticanalysis/testutil v0.4.0 h1:nhdCmubdmDF6VEatUNjgUZBJKWRqugoISdUv3PPQgHY= +github.com/gostaticanalysis/testutil v0.4.0/go.mod h1:bLIoPefWXrRi/ssLFWX1dx7Repi5x3CuviD3dgAZaBU= github.com/gotestyourself/gotestyourself v2.2.0+incompatible h1:AQwinXlbQR2HvPjQZOmDhRqsv5mZf+Jb1RnSLxcqZcI= github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +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-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.12.1/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= 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= @@ -559,6 +684,7 @@ github.com/gtank/merlin v0.1.1/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/b 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.10.1/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= +github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0= github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= @@ -569,6 +695,7 @@ github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/S github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v1.0.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-hclog v1.2.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= @@ -583,6 +710,7 @@ github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdv github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.4.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/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -597,17 +725,26 @@ github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOn github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk= github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= +github.com/hashicorp/serf v0.9.7/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo= +github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4= github.com/hudl/fargo v1.4.0/go.mod h1:9Ai6uvFy5fQNq6VPKtg+Ceq1+eTY4nKUlR2JElEOcDo= github.com/iancoleman/strcase v0.2.0 h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHLwW0= github.com/iancoleman/strcase v0.2.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/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= +github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= +github.com/imdario/mergo v0.3.4/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= +github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= 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-20200827194710-b269163b24ab/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= @@ -617,21 +754,32 @@ github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jgautheron/goconst v1.5.1 h1:HxVbL1MhydKs8R8n/HE5NPvzfaYmQJA3o879lE4+WcM= github.com/jgautheron/goconst v1.5.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= -github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= +github.com/jhump/gopoet v0.0.0-20190322174617-17282ff210b3/go.mod h1:me9yfT6IJSlOL3FCfrg+L6yzUEZ+5jW6WHt4Sk+UPUI= +github.com/jhump/gopoet v0.1.0/go.mod h1:me9yfT6IJSlOL3FCfrg+L6yzUEZ+5jW6WHt4Sk+UPUI= +github.com/jhump/goprotoc v0.5.0/go.mod h1:VrbvcYrQOrTi3i0Vf+m+oqQWk9l72mjkJCYo7UvLHRQ= +github.com/jhump/protoreflect v1.6.1/go.mod h1:RZQ/lnuN+zqeRVpQigTwO6o0AJUkxbnSnpuG7toUTG4= +github.com/jhump/protoreflect v1.11.0/go.mod h1:U7aMIjN0NWq9swDP7xDdoMfRHb35uiuTd3Z9nFXJf5E= +github.com/jhump/protoreflect v1.14.1 h1:N88q7JkxTHWFEqReuTsYH1dPIwXxA0ITNQp7avLY10s= +github.com/jhump/protoreflect v1.14.1/go.mod h1:JytZfP5d0r8pVNLZvai7U/MCuTWITgrI4tTg7puQFKI= github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c= github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg= github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af h1:KA9BjwUk7KlCh6S9EAGWBt1oExIUv9WyNCiRz5amv48= github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= +github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jonboulle/clockwork v0.2.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= +github.com/josharian/txtarfs v0.0.0-20210218200122-0702f000015a/go.mod h1:izVPOvVRsHiKkeGCT6tYBNWyDVuzj9wAaBb5R9qamfw= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= 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= 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.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -639,13 +787,17 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/juju/ratelimit v1.0.1/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSgWNm/qk= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/julz/importas v0.1.0 h1:F78HnrsjY3cR7j0etXy5+TU1Zuy7Xt08X/1aJnH5xXY= github.com/julz/importas v0.1.0/go.mod h1:oSFU2R4XK/P7kNBrnL/FEQlDGN1/6WoxXEjSSXO0DV0= github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= +github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +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/errcheck v1.6.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/errcheck v1.6.3 h1:dEKh+GLHcWm2oN34nMvDzn1sqI0i0WxPvrgiJA5JuM8= github.com/kisielk/errcheck v1.6.3/go.mod h1:nXw/i/MfnvRHqXa7XXmQMUB0oNFGuBrNI8d8NLy0LPw= github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= @@ -654,52 +806,73 @@ github.com/kkHAIKE/contextcheck v1.1.4 h1:B6zAaLhOEEcjvUgIYEqystmnFk1Oemn8bvJhbt github.com/kkHAIKE/contextcheck v1.1.4/go.mod h1:1+i/gWqokIa+dm31mqGLZhZJ7Uh44DJGZVmr6QRBNJg= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= +github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= +github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4= github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 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.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/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/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kulti/thelper v0.6.2/go.mod h1:DsqKShOvP40epevkFrvIwkCMNYxMeTNjdWL4dqWHZ6I= github.com/kulti/thelper v0.6.3 h1:ElhKf+AlItIu+xGnI990no4cE2+XaSu1ULymV2Yulxs= github.com/kulti/thelper v0.6.3/go.mod h1:DsqKShOvP40epevkFrvIwkCMNYxMeTNjdWL4dqWHZ6I= +github.com/kunwardeep/paralleltest v1.0.3/go.mod h1:vLydzomDFpk7yu5UX02RmP0H8QfRPOV/oFhWN85Mjb4= github.com/kunwardeep/paralleltest v1.0.7 h1:2uCk94js0+nVNQoHZNLBkAR1DQJrVzw6T0RMzJn55dQ= github.com/kunwardeep/paralleltest v1.0.7/go.mod h1:2C7s65hONVqY7Q5Efj5aLzRCNLjw2h4eMc9EcypGjcY= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/kyoh86/exportloopref v0.1.8/go.mod h1:1tUcJeiioIs7VWe5gcOObrux3lb66+sBqGZrRkMwPgg= github.com/kyoh86/exportloopref v0.1.11 h1:1Z0bcmTypkL3Q4k+IDHMWTcnCliEZcaPiIe0/ymEyhQ= github.com/kyoh86/exportloopref v0.1.11/go.mod h1:qkV4UF1zGl6EkF1ox8L5t9SwyeBAZ3qLMd6up458uqA= github.com/ldez/gomoddirectives v0.2.3 h1:y7MBaisZVDYmKvt9/l1mjNCiSA1BVn34U0ObUcJwlhA= github.com/ldez/gomoddirectives v0.2.3/go.mod h1:cpgBogWITnCfRq2qGoDkKMEVSaarhdBr6g8G04uz6d0= +github.com/ldez/tagliatelle v0.3.1/go.mod h1:8s6WJQwEYHbKZDsp/LjArytKOG8qaMrKQQ3mFukHs88= github.com/ldez/tagliatelle v0.5.0 h1:epgfuYt9v0CG3fms0pEgIMNPuFf/LpPIfjk4kyqSioo= github.com/ldez/tagliatelle v0.5.0/go.mod h1:rj1HmWiL1MiKQuOONhd09iySTEkUuE/8+5jtPYz9xa4= +github.com/leonklingele/grouper v1.1.0/go.mod h1:uk3I3uDfi9B6PeUjsCKi6ndcf63Uy7snXgR4yDYQVDY= github.com/leonklingele/grouper v1.1.1 h1:suWXRU57D4/Enn6pXR0QVqqWWrnJ9Osrz+5rjt8ivzU= github.com/leonklingele/grouper v1.1.1/go.mod h1:uk3I3uDfi9B6PeUjsCKi6ndcf63Uy7snXgR4yDYQVDY= +github.com/letsencrypt/pkcs11key/v4 v4.0.0/go.mod h1:EFUvBDay26dErnNb70Nd0/VW3tJiIbETBPTl9ATXQag= +github.com/lib/pq v0.0.0-20180327071824-d34b9ff171c2/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.6/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= 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/lufeee/execinquery v1.2.1 h1:hf0Ems4SHcUGBxpGN7Jz78z1ppVkP/837ZlETPCEtOM= github.com/lufeee/execinquery v1.2.1/go.mod h1:EC7DrEKView09ocscGHC+apXMIaorh4xqSxS/dy8SbM= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/maratori/testableexamples v1.0.0 h1:dU5alXRrD8WKSjOUnmJZuzdxWOEQ57+7s93SLMxb2vI= github.com/maratori/testableexamples v1.0.0/go.mod h1:4rhjL1n20TUTT4vdh3RDqSizKLyXp7K2u6HgraZCGzE= +github.com/maratori/testpackage v1.0.1/go.mod h1:ddKdw+XG0Phzhx8BFDTKgpWP4i7MpApTE5fXSKAqwDU= github.com/maratori/testpackage v1.1.1 h1:S58XVV5AD7HADMmD0fNnziNHqKvSdDuEKdPD1rNTU04= github.com/maratori/testpackage v1.1.1/go.mod h1:s4gRK/ym6AMrqpOa/kEbQTV4Q4jb7WeLZzVhVVVOQMc= +github.com/matoous/godox v0.0.0-20210227103229-6504466cf951/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26 h1:gWg6ZQ4JhDfJPqlo2srm/LN17lpybq15AryXIRcWYLE= github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= @@ -713,6 +886,7 @@ github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb 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.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.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= @@ -721,8 +895,12 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-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.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= @@ -730,31 +908,44 @@ github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zk github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mbilski/exhaustivestruct v1.2.0 h1:wCBmUnSYufAHO6J4AVWY6ff+oxWxsVFrwgOdMUQePUo= github.com/mbilski/exhaustivestruct v1.2.0/go.mod h1:OeTBVxQWoEmB2J2JCHmXWPJ0aksxSUOUy+nvtVEfzXc= +github.com/mgechev/dots v0.0.0-20210922191527-e955255bf517/go.mod h1:KQ7+USdGKfpPjXk4Ga+5XxQM4Lm4e3gAogrreFAYpOg= +github.com/mgechev/revive v1.2.1/go.mod h1:+Ro3wqY4vakcYNtkBWdZC7dBg1xSB6sp054wWwmeFm0= github.com/mgechev/revive v1.3.2 h1:Wb8NQKBaALBJ3xrrj4zpwJwqwNA6nDpyJSEQWcCka6U= github.com/mgechev/revive v1.3.2/go.mod h1:UCLtc7o5vg5aXCwdUTU1kEBQ1v+YXPAkYDIDXbrs5I0= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= +github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= github.com/miekg/dns v1.1.55 h1:GoQ4hpsj0nFLYe+bWiCToyrBEJXkQfOOIvFGFy0lEgo= github.com/miekg/dns v1.1.55/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY= +github.com/miekg/pkcs11 v1.0.2/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= +github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 h1:hLDRPB66XQT/8+wG9WsDpiCvZf1yKO7sz7scAjSlBa0= github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= github.com/minio/highwayhash v1.0.1/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g= github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= +github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= 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/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= +github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= +github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc= +github.com/moby/term v0.0.0-20210610120745-9d4ed1856297/go.mod h1:vgPCkQMyxTZ7IDy8SXRufE172gr8+K/JE/7hHFxHW3A= +github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= +github.com/moby/term v0.0.0-20221205130635-1aeaba878587/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -763,13 +954,19 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= +github.com/moricho/tparallel v0.2.1/go.mod h1:fXEIZxG2vdfl0ZF8b42f5a78EhjjD5mX8qUplsoSU4k= github.com/moricho/tparallel v0.3.1 h1:fQKD4U1wRMAYNngDonW5XupoB/ZGJHdpzrWqgyg9krA= github.com/moricho/tparallel v0.3.1/go.mod h1:leENX2cUv7Sv2qDgdi0D0fCftN8fRC67Bcn8pqzeYNI= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/mozilla/scribe v0.0.0-20180711195314-fb71baf557c1/go.mod h1:FIczTrinKo8VaLxe6PWTPEXRXDIHz2QAwiaBaP5/4a8= +github.com/mozilla/tls-observatory v0.0.0-20210609171429-7bc42856d2e5/go.mod h1:FUqVoUPHSEdDR0MnFM3Dh8AU0pZHLXUD127SAJGER/s= github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-proto-validators v0.0.0-20180403085117-0950a7990007/go.mod h1:m2XC9Qq0AlmmVksL6FktJCdTYyLk7V3fKyp0sl1yWQo= +github.com/mwitkow/go-proto-validators v0.2.0/go.mod h1:ZfA1hW+UH/2ZHOWvQ3HnQaU0DtnpXu850MZiy+YUgcc= github.com/nakabonne/nestif v0.3.1 h1:wm28nZjhQY5HyYPx+weN3Q65k6ilSBxDb8v5S81B81U= github.com/nakabonne/nestif v0.3.1/go.mod h1:9EtoZochLn5iUprVDmDjqGKPofoUEBL8U4Ngq6aY7OE= github.com/nats-io/jwt v1.2.2/go.mod h1:/xX356yQA6LuXI9xWW7mZNpxgF2mBmGecH+Fj34sP5Q= @@ -782,8 +979,10 @@ github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OS github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 h1:4kuARK6Y6FxaNu/BnU2OAaLF86eTVhP2hjTB6iMvItA= github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354/go.mod h1:KSVJerMDfblTH7p5MZaTt+8zaT2iEk3AkVb9PQdZuE8= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nishanths/exhaustive v0.7.11/go.mod h1:gX+MP7DWMKJmNa1HfMozK+u04hQd3na9i0hyqf3/dOI= github.com/nishanths/exhaustive v0.11.0 h1:T3I8nUGhl/Cwu5Z2hfc92l0e04D2GEW6e0l8pzda2l0= github.com/nishanths/exhaustive v0.11.0/go.mod h1:RqwDsZ1xY0dNdqHho2z6X+bgzizwbLYOWnZbbl2wLB4= +github.com/nishanths/predeclared v0.0.0-20190419143655-18a43bb90ffc/go.mod h1:62PewwiQTlm/7Rj+cxVYqZvDIUc+JjZq6GHAC1fsObQ= github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm/w98Vk= github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c= github.com/nunnatsa/ginkgolinter v0.12.1 h1:vwOqb5Nu05OikTXqhvLdHCGcx5uthIYIl0t79UVrERQ= @@ -793,39 +992,51 @@ 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-20230110094441-db37f07504ce h1:/pEpMk55wH0X+E5zedGEMOdLuWmV8P4+4W3+LZaM6kg= github.com/oasisprotocol/curve25519-voi v0.0.0-20230110094441-db37f07504ce/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/oklog/ulid/v2 v2.1.0/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.2/go.mod h1:rSAaSIOAGT9odnlyGlUfAJaoc5w2fSBUmeGDbRWPxyQ= 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.10.3/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.2 h1:HFB2fbVIlhIfCfOW81bZFbiC/RvnpXSdhbF2/DJr134= github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E= +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/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/ginkgo/v2 v2.9.4 h1:xR7vG4IXt5RWx6FfIjyAtsoMAtnc3C/rFXBBd2AjZwE= 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.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE= 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.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/image-spec v1.1.0-rc2/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= github.com/opencontainers/image-spec v1.1.0-rc4 h1:oOxKUJWnFC4YGHCCMNql1x4YaDfYBTS5Y4x/Cgeo1E0= github.com/opencontainers/image-spec v1.1.0-rc4/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= -github.com/opencontainers/runc v1.0.3/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= +github.com/opencontainers/runc v1.1.2/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc= +github.com/opencontainers/runc v1.1.3/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg= 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/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/openzipkin/zipkin-go v0.2.5/go.mod h1:KpXfKdgRDnnhsxw4pNIH9Md5lyFqKUa4YDFlwRYAMyE= 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/ory/dockertest/v3 v3.9.1 h1:v4dkG+dlu76goxMiTT2j8zV7s4oPPEppKT8K8p2f1kY= +github.com/ory/dockertest/v3 v3.9.1/go.mod h1:42Ir9hmvaAPm0Mgibk6mBPi7SFvTXxEcnztDYOJ//uM= github.com/otiai10/copy v1.2.0 h1:HvG945u96iNadPoG2/Ja2+AUJeW5YuFQMixq9yirC+k= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= @@ -834,18 +1045,27 @@ github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT9 github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pelletier/go-toml/v2 v2.0.0-beta.8/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= +github.com/pelletier/go-toml/v2 v2.0.0/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= +github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= +github.com/pelletier/go-toml/v2 v2.0.2/go.mod h1:MovirKjgVRESsAvNZlAjtFwV867yGuwRkXbG66OzopI= github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= github.com/performancecopilot/speed/v4 v4.0.0/go.mod h1:qxrSyuDGrTOWfV+uKRFhfxw6h/4HXRGUiZiufxo49BM= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= +github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d/go.mod h1:3OzsM7FXDQlpCiw2j81fOmAwQLnZnLGXVKUzeKQXIAw= github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= +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= @@ -855,19 +1075,23 @@ github.com/pkg/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA= github.com/pkg/profile v1.7.0/go.mod h1:8Uer0jas47ZQMJ7VD+OHknK4YDY07LPUC6dEvqDjvNo= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= +github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 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/polyfloyd/go-errorlint v1.0.0/go.mod h1:KZy4xxPJyy88/gldCe5OdW6OQRtNO3EZE7hXzmnebgA= github.com/polyfloyd/go-errorlint v1.4.2 h1:CU+O4181IxFDdPH6t/HT7IiDj1I7zxNi1RIUxYwn8d0= github.com/polyfloyd/go-errorlint v1.4.2/go.mod h1:k6fU/+fQe38ednoZS51T7gSIGQW1y94d6TkSr35OzH8= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= 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.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= @@ -876,18 +1100,16 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1: 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/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 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.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/common v0.34.0/go.mod h1:gB3sOl7P0TvJabZpLY5uQMpUqRCPPCyRLCZYc7JZTNE= github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= 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= @@ -895,11 +1117,21 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/pseudomuto/protoc-gen-doc v1.3.2/go.mod h1:y5+P6n3iGrbKG+9O04V5ld71in3v/bX88wUwgt+U8EA= +github.com/pseudomuto/protokit v0.2.0/go.mod h1:2PdH30hxVHsup8KpBTOXTBeMVhJZVio3Q8ViKSAXT0Q= +github.com/quasilyte/go-ruleguard v0.3.1-0.20210203134552-1b5a410e1cc8/go.mod h1:KsAh3x0e7Fkpgs+Q9pNLS5XpFSvYCEVl5gP9Pp1xp30= +github.com/quasilyte/go-ruleguard v0.3.16-0.20220213074421-6aa060fab41a/go.mod h1:VMX+OnnSw4LicdiEGtRSD/1X8kW7GuEscjYNr4cOIT4= github.com/quasilyte/go-ruleguard v0.3.19 h1:tfMnabXle/HzOb5Xe9CUZYWXKfkS1KwRmZyPmD9nVcc= github.com/quasilyte/go-ruleguard v0.3.19/go.mod h1:lHSn69Scl48I7Gt9cX3VrbsZYvYiBYszZOZW4A+oTEw= +github.com/quasilyte/go-ruleguard/dsl v0.3.0/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= +github.com/quasilyte/go-ruleguard/dsl v0.3.16/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= +github.com/quasilyte/go-ruleguard/dsl v0.3.19/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= +github.com/quasilyte/go-ruleguard/rules v0.0.0-20201231183845-9e62ed36efe1/go.mod h1:7JTjp89EGyU1d6XfBiXihJNG37wB2VRkd125Q1u7Plc= +github.com/quasilyte/go-ruleguard/rules v0.0.0-20211022131956-028d6511ab71/go.mod h1:4cgAphtvu7Ftv7vOT2ZOYhC6CvBxZixcasr8qIOTA50= +github.com/quasilyte/gogrep v0.0.0-20220120141003-628d8b3623b5/go.mod h1:wSEyW6O61xRV6zb6My3HxrQ5/8ke7NE2OayqCHa3xRM= github.com/quasilyte/gogrep v0.5.0 h1:eTKODPXbI8ffJMN+W2aE0+oL0z/nh8/5eNdiO34SOAo= github.com/quasilyte/gogrep v0.5.0/go.mod h1:Cm9lpz9NZjEoL1tgZ2OgeUKPIxL1meE7eo60Z6Sk+Ng= +github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0= github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 h1:TCg2WBOl980XxGFEZSS6KlBGIV0diGdySzxATTWoqaU= github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0= github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 h1:M8mH9eK4OUR4lu7Gd+PU1fV2/qnDNfzT635KRSObncs= @@ -907,26 +1139,41 @@ github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8 github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo5oJ0jf870itWm3D0Sjh7+Za9gazKc5LQ= github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/remyoudompheng/go-dbus v0.0.0-20121104212943-b7232d34b1d5/go.mod h1:+u151txRmLpwxBmpYn9z3d1sdJdjRPQpsXuYeY9jNls= +github.com/remyoudompheng/go-liblzma v0.0.0-20190506200333-81bf2d431b96/go.mod h1:90HvCY7+oHHUKkbeMCiHt1WuFR2/hPJ9QrljDG+v6ls= +github.com/remyoudompheng/go-misc v0.0.0-20190427085024-2d6ac652a50e/go.mod h1:80FQABjoFzZ2M5uEa6FUaJYEmqU2UOKojlFVak1UAwI= 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.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/cors v1.8.3/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/cors v1.9.0 h1:l9HGsTsHJcvW14Nk7J9KFz8bzeAWXn3CG6bgt7LsrAE= github.com/rs/cors v1.9.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.27.0/go.mod h1:7frBqO0oezxmnO7GF86FY++uy8I0Tk/If5ni1G9Qc0U= github.com/rs/zerolog v1.29.1 h1:cO+d60CHkknCbvzEWxP0S9K6KqyTjrCNUy1LdQLCGPc= github.com/rs/zerolog v1.29.1/go.mod h1:Le6ESbR7hc+DP6Lt1THiV8CQSdkkNrd3R0XbEgp3ZBU= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= 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/ryancurrah/gomodguard v1.2.3/go.mod h1:rYbA/4Tg5c54mV1sv4sQTP5WOPBcoLtnBZ7/TEhXAbg= github.com/ryancurrah/gomodguard v1.3.0 h1:q15RT/pd6UggBXVBuLps8BXRvl5GPBcwVA7BJHMLuTw= github.com/ryancurrah/gomodguard v1.3.0/go.mod h1:ggBxb3luypPEzqVtq33ee7YSN35V28XeGnid8dnni50= +github.com/ryanrolds/sqlclosecheck v0.3.0/go.mod h1:1gREqxyTGR3lVtpngyFo3hZAgk0KCtEdgEkHwDbigdA= github.com/ryanrolds/sqlclosecheck v0.4.0 h1:i8SX60Rppc1wRuyQjMciLqIzV3xnoHB7/tXbr6RGYNI= github.com/ryanrolds/sqlclosecheck v0.4.0/go.mod h1:TBRRjzL31JONc9i4XMinicuo+s+E8yKZ5FN8X3G6CKQ= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/sagikazarmark/crypt v0.4.0/go.mod h1:ALv2SRj7GxYV4HO9elxH9nS6M9gW+xDNxqmyJ6RfDFM= +github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig= +github.com/sagikazarmark/crypt v0.5.0/go.mod h1:l+nzl7KWh51rpzp2h7t4MZWyiEWdhNpOAnclKvg+mdA= +github.com/sagikazarmark/crypt v0.6.0/go.mod h1:U8+INwJo3nBv1m6A/8OBXAq7Jnpspk5AxSgDyEQcea8= +github.com/sanposhiho/wastedassign/v2 v2.0.6/go.mod h1:KyZ0MWTwxxBmfwn33zh3k1dmsbF2ud9pAAGfoLfjhtI= github.com/sanposhiho/wastedassign/v2 v2.0.7 h1:J+6nrY4VW+gC9xFzUc+XjPD3g3wF3je/NsJFwFK7Uxc= github.com/sanposhiho/wastedassign/v2 v2.0.7/go.mod h1:KyZ0MWTwxxBmfwn33zh3k1dmsbF2ud9pAAGfoLfjhtI= github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= @@ -937,12 +1184,15 @@ github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84d github.com/sashamelentyev/usestdlibvars v1.23.0 h1:01h+/2Kd+NblNItNeux0veSL5cBF1jbEOPrEhDzGYq0= github.com/sashamelentyev/usestdlibvars v1.23.0/go.mod h1:YPwr/Y1LATzHI93CqoPUN/2BzGQ/6N/cl/KwgR0B/aU= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= +github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= +github.com/securego/gosec/v2 v2.11.0/go.mod h1:SX8bptShuG8reGC0XS09+a4H2BoWSJi+fscA+Pulbpo= github.com/securego/gosec/v2 v2.16.0 h1:Pi0JKoasQQ3NnoRao/ww/N/XdynIB9NRYYZT5CyOs5U= github.com/securego/gosec/v2 v2.16.0/go.mod h1:xvLcVZqUfo4aAQu56TNv7/Ltz6emAOQAEsrZrt7uGlI= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c h1:W65qqJCIOVP4jpqPQ0YvHYKwcMEMVWIzWC5iNQQfBTU= github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c/go.mod h1:/PevMnwAxekIXwN8qQyfc5gl2NlkB3CQlkizAbOkeBs= +github.com/shirou/gopsutil/v3 v3.22.4/go.mod h1:D01hZJ4pVHPpCTZ3m3T2+wDF2YAGfd+H4ifUguaQzHM= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= @@ -954,10 +1204,12 @@ github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sivchari/containedctx v1.0.2/go.mod h1:PwZOeqm4/DLoJOqMSIJs3aKqXRX4YO+uXww087KZ7Bw= github.com/sivchari/containedctx v1.0.3 h1:x+etemjbsh2fB5ewm5FeLNi5bUjK0V8n0RB+Wwfd0XE= github.com/sivchari/containedctx v1.0.3/go.mod h1:c1RDvCbnJLtH4lLcYD/GqwiBSSf4F5Qk0xld2rBqzJ4= github.com/sivchari/nosnakecase v1.7.0 h1:7QkpWIRMe8x25gckkFd2A5Pi6Ymo0qgr4JrhGt95do8= github.com/sivchari/nosnakecase v1.7.0/go.mod h1:CwDzrzPea40/GB6uynrNLiorAlgFRvRbFSgJx2Gs+QY= +github.com/sivchari/tenv v1.5.0/go.mod h1:64yStXKSOxDfX47NlhVwND4dHwfZDdbp2Lyl018Icvg= github.com/sivchari/tenv v1.7.1 h1:PSpuD4bu6fSmtWMxSGWcvqUUgIn7k3yOJhOIzVWn8Ak= github.com/sivchari/tenv v1.7.1/go.mod h1:64yStXKSOxDfX47NlhVwND4dHwfZDdbp2Lyl018Icvg= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= @@ -965,9 +1217,11 @@ github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9 github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa h1:YJfZp12Z3AFhSBeXOlv4BO55RMwPn2NoQeDsrdWnBtY= github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa/go.mod h1:oJyF+mSPHbB5mVY2iO9KV3pTt/QbIkGaO8gQ2WrDbP4= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sonatard/noctx v0.0.1/go.mod h1:9D2D/EoULe8Yy2joDHJj7bv3sZoq9AaSb8B4lqBjiZI= github.com/sonatard/noctx v0.0.2 h1:L7Dz4De2zDQhW8S0t+KUjY0MAQJd6SgVwhzNIc4ok00= github.com/sonatard/noctx v0.0.2/go.mod h1:kzFz+CzWSjQ2OzIm46uJZoXuBpa2+0y3T36U18dWqIo= github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= +github.com/sourcegraph/go-diff v0.6.1/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= github.com/sourcegraph/go-diff v0.7.0 h1:9uLlrd5T46OXs5qpp8L/MTltk0zikUGi0sNNyCpA8G0= github.com/sourcegraph/go-diff v0.7.0/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= @@ -976,26 +1230,34 @@ github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2 github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= 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/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.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= +github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4= github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= +github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= +github.com/spf13/cobra v1.6.0/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= +github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +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.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= -github.com/spf13/viper v1.10.1/go.mod h1:IGlFPqhNAPKRxohIzWpI5QEy4kuI7tcl5WvR+8qy1rU= +github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM= +github.com/spf13/viper v1.11.0/go.mod h1:djo0X/bA5+tYVoCn+C7cAYJGcVn/qYLFTG8gdUsX7Zk= +github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI= github.com/spf13/viper v1.16.0 h1:rGGH0XDZhdUOryiDWjmIvUSWpbNqisK8Wk0Vyefw8hc= github.com/spf13/viper v1.16.0/go.mod h1:yg78JgCJcbrQOvV9YLXgkLaZqUidkY9K+Dd1FofRzQg= github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YEwQ0= @@ -1010,6 +1272,7 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ 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= +github.com/stretchr/testify v0.0.0-20170130113145-4d4bfba8f1d1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -1018,6 +1281,7 @@ 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.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= @@ -1025,20 +1289,24 @@ github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/subosito/gotenv v1.3.0/go.mod h1:YzJjq/33h7nrwdY+iHMhEOEEbW0ovIz0tB6t6PwAXzs= +github.com/subosito/gotenv v1.4.0/go.mod h1:mZd6rFysKEcUhUHXJk0C/08wAgyDBFuwEYL7vWWGaGo= 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/sylvia7788/contextcheck v1.0.4/go.mod h1:vuPKJMQ7MQ91ZTqfdyreNKwZjyUg6KO+IebVyQDedZQ= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca h1:Ld/zXl5t4+D69SiV4JoN7kkfvJdOWlPpfxrzxpLMoUk= github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c h1:+aPplBwWcHBo6q9xrfWdMrT9o4kltkmmvpemgIjep/8= github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c/go.mod h1:SbErYREK7xXdsRiigaQiQkI9McGRzYMvlKYaP3Nimdk= +github.com/tdakkota/asciicheck v0.1.1/go.mod h1:yHp0ai0Z9gUljN3o0xMhYJnH/IcvkdTBOX2fmJ93JEM= github.com/tdakkota/asciicheck v0.2.0 h1:o8jvnUANo0qXtnslk2d3nMKTFNlOnJjRrNcj0j9qkHM= github.com/tdakkota/asciicheck v0.2.0/go.mod h1:Qb7Y9EgjCLJGup51gDHFzbI08/gbGhL/UVhYIPWG2rg= github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8= github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= -github.com/tendermint/tendermint v0.34.19 h1:y0P1qI5wSa9IRuhKnTDA6IUcOrLi1hXJuALR+R7HFEk= -github.com/tendermint/tendermint v0.34.19/go.mod h1:R5+wgIwSxMdKQcmOaeudL0Cjkr3HDkhpcdum6VeU3R4= +github.com/tendermint/tendermint v0.34.20 h1:/pmvJhO3IqOxhbi8iRXudTjA2YKpaMqrLwFNkyxDSzw= +github.com/tendermint/tendermint v0.34.20/go.mod h1:KtOwCLYJcsS1ymtAfnjjAtXfXClbqcqjdqzFt2Em1Ac= github.com/tendermint/tm-db v0.6.6/go.mod h1:wP8d49A85B7/erz/r4YbKssKw6ylsO/hKtFk7E1aWZI= github.com/tendermint/tm-db v0.6.7 h1:fE00Cbl0jayAoqlExN6oyQJ7fR/ZtoVOmvPJ//+shu8= github.com/tendermint/tm-db v0.6.7/go.mod h1:byQDzFkZV1syXr/ReXS808NxA2xvyuuVgXOJ/088L6I= @@ -1048,43 +1316,62 @@ github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3 h1:f+jULpR github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY= github.com/tetafro/godot v1.4.11 h1:BVoBIqAf/2QdbFmSwAWnaIqDivZdOV0ZRwEm6jivLKw= github.com/tetafro/godot v1.4.11/go.mod h1:LR3CJpxDVGlYOWn3ZZg1PgNZdTUvzsZWu8xaEohUpn8= -github.com/tetratelabs/wazero v1.3.0 h1:nqw7zCldxE06B8zSZAY0ACrR9OH5QCcPwYmYlwtcwtE= -github.com/tetratelabs/wazero v1.3.0/go.mod h1:wYx2gNRg8/WihJfSDxA1TIL8H+GkfLYm+bIfbblu9VQ= +github.com/timakin/bodyclose v0.0.0-20210704033933-f49887972144/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk= github.com/timakin/bodyclose v0.0.0-20230421092635-574207250966 h1:quvGphlmUVU+nhpFa4gg4yJyTRJ13reZMDHrKwYw53M= github.com/timakin/bodyclose v0.0.0-20230421092635-574207250966/go.mod h1:27bSVNWSBOHm+qRp1T9qzaIpsWEP6TbUnei/43HK+PQ= github.com/timonwong/loggercheck v0.9.4 h1:HKKhqrjcVj8sxL7K77beXh0adEm6DLjV/QOGeMXEVi4= github.com/timonwong/loggercheck v0.9.4/go.mod h1:caz4zlPcgvpEkXgVnAJGowHAMW2NwHaNlpS8xDbVhTg= github.com/tinylib/msgp v1.1.5/go.mod h1:eQsjooMTnV42mHu917E26IogZ2930nFyBQdofk10Udg= +github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk= +github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ= +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-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tmc/grpc-websocket-proxy v0.0.0-20200427203606-3cfed13b9966/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tomarrell/wrapcheck/v2 v2.6.1/go.mod h1:Eo+Opt6pyMW1b6cNllOcDSSoHO0aTJ+iF6BfCUbHltA= github.com/tomarrell/wrapcheck/v2 v2.8.1 h1:HxSqDSN0sAt0yJYsrcYVoEeyM4aI9yAm3KQpIXDJRhQ= github.com/tomarrell/wrapcheck/v2 v2.8.1/go.mod h1:/n2Q3NZ4XFT50ho6Hbxg+RV1uyo2Uow/Vdm9NQcl5SE= +github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce/go.mod h1:o8v6yHRoik09Xen7gje4m9ERNah1d1PPsVq1VEx9vE4= +github.com/tommy-muehle/go-mnd/v2 v2.5.0/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= github.com/tommy-muehle/go-mnd/v2 v2.5.1 h1:NowYhSdyE/1zwK9QCLeRb6USWdoif80Ie+v+yU8u1Zw= github.com/tommy-muehle/go-mnd/v2 v2.5.1/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= github.com/ttacon/chalk v0.0.0-20160626202418-22c06c80ed31/go.mod h1:onvgF043R+lC5RZ8IT9rBXDaEDnpnw/Cl+HFiw+v/7Q= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= -github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= -github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ultraware/funlen v0.0.3 h1:5ylVWm8wsNwH5aWo9438pwvsK0QiqVuUrt9bn7S/iLA= github.com/ultraware/funlen v0.0.3/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA= github.com/ultraware/whitespace v0.0.5 h1:hh+/cpIcopyMYbZNVov9iSxvJU3OYQg78Sfaqzi/CzI= github.com/ultraware/whitespace v0.0.5/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA= +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/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.12/go.mod h1:sSBEIC79qR6OvcmsD4U3KABeOTxDqQtdDnaFuUN30b8= +github.com/uudashr/gocognit v1.0.5/go.mod h1:wgYz0mitoKOTysqxTDMOUXg+Jb5SvtihkfmugIZYpEA= github.com/uudashr/gocognit v1.0.6 h1:2Cgi6MweCsdB6kpcVQp7EW4U23iBFQWfTXiWlyp842Y= github.com/uudashr/gocognit v1.0.6/go.mod h1:nAIUuVBnYU7pcninia3BHOvQkpQCeO76Uscky5BOwcY= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.30.0/go.mod h1:2rsYD01CKFrjjsvFxx75KlEUNpWNBY9JWD3K/7o2Cus= +github.com/valyala/quicktemplate v1.7.0/go.mod h1:sqKJnoaOF88V07vkO+9FL8fb9uZg/VPSJnLYn+LmLk8= +github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= +github.com/vbatts/tar-split v0.11.2/go.mod h1:vV3ZuO2yWSVsz+pfFzDG/upWH1JhjOiEaWq6kXyQ3VI= github.com/vbatts/tar-split v0.11.3 h1:hLFqsOLQ1SsppQNTMpkpPXClLDfC2A3Zgy9OUU+RVck= github.com/vbatts/tar-split v0.11.3/go.mod h1:9QlHN18E+fEH7RdG+QAJJcuya3rqT7eXSTY7wGrAokY= +github.com/vektra/mockery/v2 v2.14.0/go.mod h1:bnD1T8tExSgPD1ripLkDbr60JA9VtQeu12P3wgLZd7M= github.com/vektra/mockery/v2 v2.32.0 h1:IXUoQ3s5VxJPpi95DECUmkRUXZ44I1spQ3YatEypIF4= github.com/vektra/mockery/v2 v2.32.0/go.mod h1:9lREs4VEeQiUS3rizYQx1saxHu2JiIhThP0q9+fDegM= +github.com/viki-org/dnscache v0.0.0-20130720023526-c70c1f23c5d8/go.mod h1:dniwbG03GafCjFohMDmz6Zc6oCuiqgH6tGNyXTkHzXE= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xen0n/gosmopolitan v1.2.1 h1:3pttnTuFumELBRSh+KQs1zcz4fN6Zy7aB0xlnQSn1Iw= github.com/xen0n/gosmopolitan v1.2.1/go.mod h1:JsHq/Brs1o050OOdmzHeOr0N7OtlnKRAGAsElF8xBQA= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yagipy/maintidx v1.0.0 h1:h5NvIsCz+nRDapQ0exNv4aJ0yXSI0420omVANTv3GJM= github.com/yagipy/maintidx v1.0.0/go.mod h1:0qNf/I/CCZXSMhsRsrEPDZ+DkekpKLXAJfsTACwgXLk= @@ -1094,26 +1381,42 @@ github.com/yeya24/promlinter v0.2.0 h1:xFKDQ82orCU5jQujdaD8stOHiv8UN68BSdn2a8u8Y github.com/yeya24/promlinter v0.2.0/go.mod h1:u54lkmBOZrpEbQQ6gox2zWKKLKu2SGe+2KOiextY+IA= github.com/ykadowak/zerologlint v0.1.2 h1:Um4P5RMmelfjQqQJKtE8ZW+dLZrXrENeIzWWKw800U4= github.com/ykadowak/zerologlint v0.1.2/go.mod h1:KaUskqF3e/v59oPmdq1U1DnKcuHokl2/K1U4pmIELKg= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +gitlab.com/bosi/decorder v0.2.1/go.mod h1:6C/nhLSbF6qZbYD8bRmISBwc6vcWdNsiIBkRvjJFrH0= gitlab.com/bosi/decorder v0.2.3 h1:gX4/RgK16ijY8V+BRQHAySfQAb354T7/xQpDB2n10P0= gitlab.com/bosi/decorder v0.2.3/go.mod h1:9K1RB5+VPNQYtXtTDAzd2OEftsZb1oV0IrJrzChSdGE= go-simpler.org/assert v0.5.0 h1:+5L/lajuQtzmbtEfh69sr5cRf2/xZzyJhFjoOz/PPqs= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= +go.etcd.io/etcd v0.0.0-20200513171258-e048e166ab9c/go.mod h1:xCI7ZzBfRuGgBXyXO6yfWfDmlWd35khcWpUa4L0xI/k= go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= +go.etcd.io/etcd/api/v3 v3.5.2/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A= +go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A= go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/pkg/v3 v3.5.2/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/pkg/v3 v3.5.4/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= go.etcd.io/etcd/client/v2 v2.305.1/go.mod h1:pMEacxZW7o8pg4CrFE7pquyCJJzZvkvdD2RibOCCCGs= +go.etcd.io/etcd/client/v2 v2.305.2/go.mod h1:2D7ZejHVMIfog1221iLSYlQRzrtECw3kz4I4VAQm3qI= +go.etcd.io/etcd/client/v2 v2.305.4/go.mod h1:Ud+VUwIi9/uQHOMA+4ekToJ12lTxlv0zB/+DHwTGEbU= go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= +go.etcd.io/etcd/client/v3 v3.5.4/go.mod h1:ZaRkVgBZC+L+dLCjTcF1hRXpgZXQPOvnA/Ak/gq3kiY= +go.mozilla.org/mozlog v0.0.0-20170222151521-4bb13139d403/go.mod h1:jHoPAGnDrCy6kaI2tAze5Prf0Nr0w/oNkROt2lw3n3o= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -1121,36 +1424,37 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opentelemetry.io/otel v1.16.0 h1:Z7GVAX/UkAXPKsy94IU+i6thsQS4nb7LviLpnaNeW8s= -go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4= -go.opentelemetry.io/otel/metric v1.16.0 h1:RbrpwVG1Hfv85LgnZ7+txXioPDoh6EdbZHo26Q3hqOo= -go.opentelemetry.io/otel/metric v1.16.0/go.mod h1:QE47cpOmkwipPiefDwo2wDzwJrlfxxNYodqc4xnGCo4= -go.opentelemetry.io/otel/sdk v1.16.0 h1:Z1Ok1YsijYL0CSJpHt4cS3wDDh7p572grzNrBMiMWgE= -go.opentelemetry.io/otel/sdk v1.16.0/go.mod h1:tMsIuKXuuIWPBAOrH+eHtvhTL+SntFtXF9QD68aP6p4= -go.opentelemetry.io/otel/sdk/metric v0.39.0 h1:Kun8i1eYf48kHH83RucG93ffz0zGV1sh46FAScOTuDI= +go.opentelemetry.io/otel v1.12.0 h1:IgfC7kqQrRccIKuB7Cl+SRUmsKbEwSGPr0Eu+/ht1SQ= +go.opentelemetry.io/otel v1.12.0/go.mod h1:geaoz0L0r1BEOR81k7/n9W4TCXYCJ7bPO7K374jQHG0= +go.opentelemetry.io/otel/sdk v1.12.0 h1:8npliVYV7qc0t1FKdpU08eMnOjgPFMnriPhn0HH4q3o= +go.opentelemetry.io/otel/sdk v1.12.0/go.mod h1:WYcvtgquYvgODEvxOry5owO2y9MyciW7JqMz6cpXShE= +go.opentelemetry.io/otel/trace v1.12.0/go.mod h1:pHlgBynn6s25qJ2szD+Bv+iwKJttjHSI3lUAyf0GNuQ= go.opentelemetry.io/otel/trace v1.16.0 h1:8JRpaObFoW0pxuVPapkgH8UhHQj+bJW8jJsCZEu5MQs= go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLkqr2QVwea0ef0= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.tmz.dev/musttag v0.7.0 h1:QfytzjTWGXZmChoX0L++7uQN+yRCPfyFm+whsM+lfGc= go.tmz.dev/musttag v0.7.0/go.mod h1:oTFPvgOkJmp5kYL02S8+jrH0eLrBIl57rzWeA26zDEM= +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/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= -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/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +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/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.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180501155221-613d6eafa307/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= @@ -1166,14 +1470,21 @@ golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210915214749-c084706c2272/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-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220313003712-b769efc7c000/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1189,8 +1500,11 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 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-20230131160201-f062dba9d201/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 h1:MGwJjxBy0HJshjDNfLsYO8xppfqWlA5ZT9OhtUUhTNw= golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= +golang.org/x/exp/typeparams v0.0.0-20220218215828-6cf2b201936e/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/exp/typeparams v0.0.0-20230224173230-c95f2b4c22f2 h1:J74nGeMgeFnYQJN59eFwh06jX/V8g0lB7LWpjSLxtgU= @@ -1243,13 +1557,14 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -1257,6 +1572,7 @@ golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= @@ -1278,15 +1594,26 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/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-20211208012354-db4efeb81f4b/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= +golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= @@ -1310,10 +1637,19 @@ golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= +golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= +golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= 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= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1321,6 +1657,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220513210516-0976fa681c29/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +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.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= @@ -1346,7 +1684,9 @@ golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/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-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-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1356,7 +1696,6 @@ golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1369,6 +1708,7 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1378,12 +1718,13 @@ golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1398,7 +1739,6 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/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-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1408,7 +1748,9 @@ golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1422,22 +1764,45 @@ golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/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-20211213223007-03aa0b5f6827/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220403020550-483a9cbc67c0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220405210540-1e041c57c461/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220406163625-3f8b81556e12/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-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-20220702020025-31831981b65f/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-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220906165534-d0df966e6959/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-20220919091848-fb04ddd9f9c8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= @@ -1458,6 +1823,7 @@ golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +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= @@ -1467,34 +1833,45 @@ golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190228203856-589c23e65e65/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190307163923-6a08e3108db3/go.mod h1:25r3+/G6/xytQM8iWZKq3Hn0kr0rgFKPUNVEL/dr3z4= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190321232350-e250d351ecad/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190322203728-c1a832b0ad89/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-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-20190624222133-a101b041ded4/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-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/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-20190916130336-e45ffcd953cc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191010075000-0337d82405ff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 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= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117220505-0cba7a3a9ee9/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= @@ -1507,24 +1884,38 @@ golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjs golang.org/x/tools v0.0.0-20200324003944-a576cf524670/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200329025819-fd4102a86c65/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200414032229-332987a829c3/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200422022333-3d57cf2e726e/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200426102838-f3a5411a4c3b/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200622203043-20e05c1c8ffa/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200624225443-88f3c62a19ff/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200625211823-6506e20df31f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200626171337-aa94e735be7f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200630154851-b2d8b0336632/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200706234117-b22de6825cf7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200724022722-7017fd6b1305/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200812195022-5ae4c3c160a0/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200820010801-b793a1359eac/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200831203904-5a2aa26beb65/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= golang.org/x/tools v0.0.0-20201001104356-43ebab892c4c/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= +golang.org/x/tools v0.0.0-20201002184944-ecd9fd270d5d/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201028025901-8cd080b735b3/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201230224404-63754364767c/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= @@ -1536,8 +1927,12 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 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.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= +golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.1.9-0.20211228192929-ee1ca4ffc4da/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= +golang.org/x/tools v0.1.11-0.20220316014157-77aa08bb151a/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= @@ -1550,6 +1945,9 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T 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= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= gonum.org/v1/gonum v0.13.0 h1:a0T3bh+7fhRyqeNbiC3qVHYmkiQgit3wnNan/2c0HMM= @@ -1560,6 +1958,7 @@ google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEt google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.10.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= @@ -1587,16 +1986,31 @@ google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqiv google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU= google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= +google.golang.org/api v0.62.0/go.mod h1:dKmwPCydfsad4qCH08MSdgWjfHOyfpd4VtDGgRFdavw= google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= +google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= +google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= +google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= +google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= +google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= +google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw= +google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg= +google.golang.org/api v0.81.0/go.mod h1:FA6Mb/bZxj706H2j+j2d6mHEEaHBmbbWnkfvmorOCko= +google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o= +google.golang.org/api v0.93.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= +google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.2/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/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 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-20181107211654-5fc9ac540362/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -1604,6 +2018,7 @@ google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= @@ -1617,12 +2032,15 @@ google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200626011028-ee7919e894b5/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200707001353-8e8330bf89df/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -1637,6 +2055,7 @@ google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6D 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= +google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= @@ -1658,20 +2077,48 @@ google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ6 google.golang.org/genproto v0.0.0-20211008145708-270636b82663/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211028162531-8db9c33dc351/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211129164237-f09f9a12af12/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211203200212-54befc351ae9/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= +google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220815135757-37a418bb8959/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220915135415-7fd63a7952de/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= +google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.0/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= @@ -1690,8 +2137,12 @@ google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnD 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.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +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= +google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= google.golang.org/grpc v1.56.2 h1:fVRFRnXvU+x6C4IlHZewvJOVHoOv1TUuQyoRsYnB4bI= google.golang.org/grpc v1.56.2/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= @@ -1708,6 +2159,9 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 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.28.2-0.20220831092852-f930b1dc76e8/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= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= @@ -1717,10 +2171,15 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/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.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= 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/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.66.4/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.66.6/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= 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/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= @@ -1735,17 +2194,22 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.6/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0/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 v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= -gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= +gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= +gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= +gotest.tools/v3 v3.2.0 h1:I0DwBVMGAx26dttAj1BtJLAkVGncrkkUXfJLC4Flt/I= +gotest.tools/v3 v3.2.0/go.mod h1:Mcr9QNxkg0uMvy/YElmo4SpXgJKWgQvYrT7Kw5RzJ1A= 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= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1753,18 +2217,22 @@ 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= +honnef.co/go/tools v0.3.1/go.mod h1:vlRD9XErLMGT+mDuofSr0mMMquscM/1nQqtRSsh6m70= honnef.co/go/tools v0.4.3 h1:o/n5/K5gXqk8Gozvs2cnL0F2S1/g1vcGCAx2vETjITw= honnef.co/go/tools v0.4.3/go.mod h1:36ZgoUOrqOk1GxwHhyryEkq8FQWkUO2xGuSMhUCcdvA= +mvdan.cc/gofumpt v0.3.1/go.mod h1:w3ymliuxvzVx8DAutBnVyDqYb1Niy/yCJt/lk821YCE= mvdan.cc/gofumpt v0.5.0 h1:0EQ+Z56k8tXjj/6TQD25BFNKQXpCvT0rnansIc7Ug5E= mvdan.cc/gofumpt v0.5.0/go.mod h1:HBeVDtMKRZpXyxFciAirzdKklDlGu8aAy1wEbH5Y9js= mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed h1:WX1yoOaKQfddO/mLzdV4wptyWgoH/6hwLs7QHTixo0I= mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc= mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphDJbHOQO1DFFFTeBo= mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= +mvdan.cc/unparam v0.0.0-20211214103731-d0ef000c54e5/go.mod h1:b8RRCBm0eeiWR8cfN88xeq2G5SG3VKGO+5UPWi5FSOY= mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d h1:3rvTIIM22r9pvXk+q3swxUQAQOxksVMGK7sml4nG57w= mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d/go.mod h1:IeHQjmn6TOD+e4Z3RFiZMMsLVL+A96Nvptar8Fj71is= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= 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.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/libs/os/os.go b/libs/os/os.go index 535c31e50..b21ab1f08 100644 --- a/libs/os/os.go +++ b/libs/os/os.go @@ -7,6 +7,8 @@ import ( "os" "os/signal" "syscall" + + "github.com/Finschia/ostracon/libs/log" ) type logger interface { @@ -20,7 +22,7 @@ func TrapSignal(logger logger, cb func()) { signal.Notify(c, os.Interrupt, syscall.SIGTERM) go func() { for sig := range c { - logger.Info(fmt.Sprintf("captured %v, exiting...", sig)) + logger.Info("signal trapped", "msg", log.NewLazySprintf("captured %v, exiting...", sig)) if cb != nil { cb() } diff --git a/libs/service/service.go b/libs/service/service.go index 3227852ab..0d31fc864 100644 --- a/libs/service/service.go +++ b/libs/service/service.go @@ -136,7 +136,11 @@ func (bs *BaseService) Start() error { atomic.StoreUint32(&bs.started, 0) return ErrAlreadyStopped } - bs.Logger.Info(fmt.Sprintf("Starting %v service", bs.name), "impl", bs.impl.String()) + bs.Logger.Info("service start", + "msg", + log.NewLazySprintf("Starting %v service", bs.name), + "impl", + bs.impl.String()) err := bs.impl.OnStart() if err != nil { // revert flag @@ -145,7 +149,11 @@ func (bs *BaseService) Start() error { } return nil } - bs.Logger.Debug(fmt.Sprintf("Not starting %v service -- already started", bs.name), "impl", bs.impl) + bs.Logger.Debug("service start", + "msg", + log.NewLazySprintf("Not starting %v service -- already started", bs.name), + "impl", + bs.impl) return ErrAlreadyStarted } @@ -165,12 +173,20 @@ func (bs *BaseService) Stop() error { atomic.StoreUint32(&bs.stopped, 0) return ErrNotStarted } - bs.Logger.Info(fmt.Sprintf("Stopping %v service", bs.name), "impl", bs.impl) + bs.Logger.Info("service stop", + "msg", + log.NewLazySprintf("Stopping %v service", bs.name), + "impl", + bs.impl) bs.impl.OnStop() close(bs.quit) return nil } - bs.Logger.Debug(fmt.Sprintf("Stopping %v service (already stopped)", bs.name), "impl", bs.impl) + bs.Logger.Debug("service stop", + "msg", + log.NewLazySprintf("Stopping %v service (already stopped)", bs.name), + "impl", + bs.impl) return ErrAlreadyStopped } @@ -183,7 +199,11 @@ func (bs *BaseService) OnStop() {} // will be returned if the service is running. func (bs *BaseService) Reset() error { if !atomic.CompareAndSwapUint32(&bs.stopped, 1, 0) { - bs.Logger.Debug(fmt.Sprintf("Can't reset %v service. Not stopped", bs.name), "impl", bs.impl) + bs.Logger.Debug("service reset", + "msg", + log.NewLazySprintf("Can't reset %v service. Not stopped", bs.name), + "impl", + bs.impl) return fmt.Errorf("can't reset running %s", bs.name) } diff --git a/light/rpc/mocks/light_client.go b/light/rpc/mocks/light_client.go index d7c18e496..e928be743 100644 --- a/light/rpc/mocks/light_client.go +++ b/light/rpc/mocks/light_client.go @@ -109,13 +109,12 @@ func (_m *LightClient) VerifyLightBlockAtHeight(ctx context.Context, height int6 return r0, r1 } -type mockConstructorTestingTNewLightClient interface { +// NewLightClient creates a new instance of LightClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewLightClient(t interface { mock.TestingT Cleanup(func()) -} - -// NewLightClient creates a new instance of LightClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewLightClient(t mockConstructorTestingTNewLightClient) *LightClient { +}) *LightClient { mock := &LightClient{} mock.Mock.Test(t) diff --git a/mempool/bench_test.go b/mempool/bench_test.go deleted file mode 100644 index 4e2fa92dd..000000000 --- a/mempool/bench_test.go +++ /dev/null @@ -1,100 +0,0 @@ -package mempool - -import ( - "encoding/binary" - "testing" - - "github.com/Finschia/ostracon/abci/example/kvstore" - "github.com/Finschia/ostracon/proxy" -) - -func BenchmarkReap(b *testing.B) { - app := kvstore.NewApplication() - cc := proxy.NewLocalClientCreator(app) - mempool, cleanup := newMempoolWithApp(cc) - defer cleanup() - - size := 10000 - for i := 0; i < size; i++ { - tx := make([]byte, 8) - binary.BigEndian.PutUint64(tx, uint64(i)) - mempool.CheckTxSync(tx, TxInfo{}) // nolint: errcheck - } - b.ResetTimer() - for i := 0; i < b.N; i++ { - mempool.ReapMaxBytesMaxGas(100000000, 10000000) - } -} - -func BenchmarkReapWithCheckTxAsync(b *testing.B) { - app := kvstore.NewApplication() - cc := proxy.NewLocalClientCreator(app) - mempool, cleanup := newMempoolWithApp(cc) - defer cleanup() - - size := 10000 - for i := 0; i < size; i++ { - tx := make([]byte, 8) - binary.BigEndian.PutUint64(tx, uint64(i)) - mempool.CheckTxAsync(tx, TxInfo{}, nil, nil) - } - b.ResetTimer() - for i := 0; i < b.N; i++ { - mempool.ReapMaxBytesMaxGas(100000000, 10000000) - } -} - -func BenchmarkCheckTxSync(b *testing.B) { - app := kvstore.NewApplication() - cc := proxy.NewLocalClientCreator(app) - mempool, cleanup := newMempoolWithApp(cc) - defer cleanup() - - for i := 0; i < b.N; i++ { - tx := make([]byte, 8) - binary.BigEndian.PutUint64(tx, uint64(i)) - mempool.CheckTxSync(tx, TxInfo{}) // nolint: errcheck - } -} - -func BenchmarkCheckTxAsync(b *testing.B) { - app := kvstore.NewApplication() - cc := proxy.NewLocalClientCreator(app) - mempool, cleanup := newMempoolWithApp(cc) - defer cleanup() - - for i := 0; i < b.N; i++ { - tx := make([]byte, 8) - binary.BigEndian.PutUint64(tx, uint64(i)) - mempool.CheckTxAsync(tx, TxInfo{}, nil, nil) - } -} - -func BenchmarkCacheInsertTime(b *testing.B) { - cache := newMapTxCache(b.N) - txs := make([][]byte, b.N) - for i := 0; i < b.N; i++ { - txs[i] = make([]byte, 8) - binary.BigEndian.PutUint64(txs[i], uint64(i)) - } - b.ResetTimer() - for i := 0; i < b.N; i++ { - cache.Push(txs[i]) - } -} - -// This benchmark is probably skewed, since we actually will be removing -// txs in parallel, which may cause some overhead due to mutex locking. -func BenchmarkCacheRemoveTime(b *testing.B) { - cache := newMapTxCache(b.N) - txs := make([][]byte, b.N) - for i := 0; i < b.N; i++ { - txs[i] = make([]byte, 8) - binary.BigEndian.PutUint64(txs[i], uint64(i)) - cache.Push(txs[i]) - } - b.ResetTimer() - for i := 0; i < b.N; i++ { - cache.Remove(txs[i]) - } -} diff --git a/mempool/cache.go b/mempool/cache.go new file mode 100644 index 000000000..c5b84e412 --- /dev/null +++ b/mempool/cache.go @@ -0,0 +1,120 @@ +package mempool + +import ( + "container/list" + + tmsync "github.com/Finschia/ostracon/libs/sync" + "github.com/Finschia/ostracon/types" +) + +// TxCache defines an interface for raw transaction caching in a mempool. +// Currently, a TxCache does not allow direct reading or getting of transaction +// values. A TxCache is used primarily to push transactions and removing +// transactions. Pushing via Push returns a boolean telling the caller if the +// transaction already exists in the cache or not. +type TxCache interface { + // Reset resets the cache to an empty state. + Reset() + + // Push adds the given raw transaction to the cache and returns true if it was + // newly added. Otherwise, it returns false. + Push(tx types.Tx) bool + + // Remove removes the given raw transaction from the cache. + Remove(tx types.Tx) + + // Has reports whether tx is present in the cache. Checking for presence is + // not treated as an access of the value. + Has(tx types.Tx) bool +} + +var _ TxCache = (*LRUTxCache)(nil) + +// LRUTxCache maintains a thread-safe LRU cache of raw transactions. The cache +// only stores the hash of the raw transaction. +type LRUTxCache struct { + mtx tmsync.Mutex + size int + cacheMap map[types.TxKey]*list.Element + list *list.List +} + +func NewLRUTxCache(cacheSize int) *LRUTxCache { + return &LRUTxCache{ + size: cacheSize, + cacheMap: make(map[types.TxKey]*list.Element, cacheSize), + list: list.New(), + } +} + +// GetList returns the underlying linked-list that backs the LRU cache. Note, +// this should be used for testing purposes only! +func (c *LRUTxCache) GetList() *list.List { + return c.list +} + +func (c *LRUTxCache) Reset() { + c.mtx.Lock() + defer c.mtx.Unlock() + + c.cacheMap = make(map[types.TxKey]*list.Element, c.size) + c.list.Init() +} + +func (c *LRUTxCache) Push(tx types.Tx) bool { + c.mtx.Lock() + defer c.mtx.Unlock() + + key := tx.Key() + + moved, ok := c.cacheMap[key] + if ok { + c.list.MoveToBack(moved) + return false + } + + if c.list.Len() >= c.size { + front := c.list.Front() + if front != nil { + frontKey := front.Value.(types.TxKey) + delete(c.cacheMap, frontKey) + c.list.Remove(front) + } + } + + e := c.list.PushBack(key) + c.cacheMap[key] = e + + return true +} + +func (c *LRUTxCache) Remove(tx types.Tx) { + c.mtx.Lock() + defer c.mtx.Unlock() + + key := tx.Key() + e := c.cacheMap[key] + delete(c.cacheMap, key) + + if e != nil { + c.list.Remove(e) + } +} + +func (c *LRUTxCache) Has(tx types.Tx) bool { + c.mtx.Lock() + defer c.mtx.Unlock() + + _, ok := c.cacheMap[tx.Key()] + return ok +} + +// NopTxCache defines a no-op raw transaction cache. +type NopTxCache struct{} + +var _ TxCache = (*NopTxCache)(nil) + +func (NopTxCache) Reset() {} +func (NopTxCache) Push(types.Tx) bool { return true } +func (NopTxCache) Remove(types.Tx) {} +func (NopTxCache) Has(types.Tx) bool { return false } diff --git a/mempool/cache_bench_test.go b/mempool/cache_bench_test.go new file mode 100644 index 000000000..1c26999d1 --- /dev/null +++ b/mempool/cache_bench_test.go @@ -0,0 +1,41 @@ +package mempool + +import ( + "encoding/binary" + "testing" +) + +func BenchmarkCacheInsertTime(b *testing.B) { + cache := NewLRUTxCache(b.N) + + txs := make([][]byte, b.N) + for i := 0; i < b.N; i++ { + txs[i] = make([]byte, 8) + binary.BigEndian.PutUint64(txs[i], uint64(i)) + } + + b.ResetTimer() + + for i := 0; i < b.N; i++ { + cache.Push(txs[i]) + } +} + +// This benchmark is probably skewed, since we actually will be removing +// txs in parallel, which may cause some overhead due to mutex locking. +func BenchmarkCacheRemoveTime(b *testing.B) { + cache := NewLRUTxCache(b.N) + + txs := make([][]byte, b.N) + for i := 0; i < b.N; i++ { + txs[i] = make([]byte, 8) + binary.BigEndian.PutUint64(txs[i], uint64(i)) + cache.Push(txs[i]) + } + + b.ResetTimer() + + for i := 0; i < b.N; i++ { + cache.Remove(txs[i]) + } +} diff --git a/mempool/cache_test.go b/mempool/cache_test.go index ce72b27a9..513f67ff3 100644 --- a/mempool/cache_test.go +++ b/mempool/cache_test.go @@ -2,32 +2,48 @@ package mempool import ( "crypto/rand" - "crypto/sha256" "testing" - "github.com/stretchr/testify/require" - - "github.com/Finschia/ostracon/abci/example/kvstore" - abci "github.com/Finschia/ostracon/abci/types" - "github.com/Finschia/ostracon/proxy" "github.com/Finschia/ostracon/types" + + "github.com/stretchr/testify/require" ) +func TestCacheBasic(t *testing.T) { + size := 10 + cache := NewLRUTxCache(size) + require.Equal(t, 0, cache.GetList().Len()) + for i := 0; i < size; i++ { + cache.Push(types.Tx{byte(i)}) + } + require.Equal(t, size, cache.GetList().Len()) + cache.Push(types.Tx{byte(0)}) // MoveToBack + require.Equal(t, size, cache.GetList().Len()) + cache.Push(types.Tx{byte(size + 1)}) // Cache out + require.Equal(t, size, cache.GetList().Len()) + cache.Reset() + require.Equal(t, 0, cache.GetList().Len()) +} + func TestCacheRemove(t *testing.T) { - cache := newMapTxCache(100) + cache := NewLRUTxCache(100) numTxs := 10 + txs := make([][]byte, numTxs) for i := 0; i < numTxs; i++ { // probability of collision is 2**-256 txBytes := make([]byte, 32) _, err := rand.Read(txBytes) require.NoError(t, err) + txs[i] = txBytes cache.Push(txBytes) + // make sure its added to both the linked list and the map require.Equal(t, i+1, len(cache.cacheMap)) require.Equal(t, i+1, cache.list.Len()) } + for i := 0; i < numTxs; i++ { cache.Remove(txs[i]) // make sure its removed from both the map and the linked list @@ -35,71 +51,3 @@ func TestCacheRemove(t *testing.T) { require.Equal(t, numTxs-(i+1), cache.list.Len()) } } - -func TestCacheAfterUpdate(t *testing.T) { - app := kvstore.NewApplication() - cc := proxy.NewLocalClientCreator(app) - mempool, cleanup := newMempoolWithApp(cc) - defer cleanup() - - // reAddIndices & txsInCache can have elements > numTxsToCreate - // also assumes max index is 255 for convenience - // txs in cache also checks order of elements - tests := []struct { - numTxsToCreate int - updateIndices []int - reAddIndices []int - txsInCache []int - }{ - {1, []int{}, []int{1}, []int{1, 0}}, // adding new txs works - {2, []int{1}, []int{}, []int{1, 0}}, // update doesn't remove tx from cache - {2, []int{2}, []int{}, []int{2, 1, 0}}, // update adds new tx to cache - {2, []int{1}, []int{1}, []int{1, 0}}, // re-adding after update doesn't make dupe - } - for tcIndex, tc := range tests { - for i := 0; i < tc.numTxsToCreate; i++ { - tx := types.Tx{byte(i)} - _, err := mempool.CheckTxSync(tx, TxInfo{}) - require.NoError(t, err) - } - - updateTxs := []types.Tx{} - for _, v := range tc.updateIndices { - tx := types.Tx{byte(v)} - updateTxs = append(updateTxs, tx) - } - err := mempool.Update(newTestBlock(int64(tcIndex), updateTxs), - abciResponses(len(updateTxs), abci.CodeTypeOK), nil, nil) - require.NoError(t, err) - - for _, v := range tc.reAddIndices { - tx := types.Tx{byte(v)} - _, _ = mempool.CheckTxSync(tx, TxInfo{}) - } - - cache := mempool.cache.(*mapTxCache) - node := cache.list.Front() - counter := 0 - for node != nil { - require.NotEqual(t, len(tc.txsInCache), counter, - "cache larger than expected on testcase %d", tcIndex) - - nodeVal := node.Value.([sha256.Size]byte) - expectedBz := sha256.Sum256([]byte{byte(tc.txsInCache[len(tc.txsInCache)-counter-1])}) - // Reference for reading the errors: - // >>> sha256('\x00').hexdigest() - // '6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d' - // >>> sha256('\x01').hexdigest() - // '4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a' - // >>> sha256('\x02').hexdigest() - // 'dbc1b4c900ffe48d575b5da5c638040125f65db0fe3e24494b76ea986457d986' - - require.Equal(t, expectedBz, nodeVal, "Equality failed on index %d, tc %d", counter, tcIndex) - counter++ - node = node.Next() - } - require.Equal(t, len(tc.txsInCache), counter, - "cache smaller than expected on testcase %d", tcIndex) - mempool.Flush() - } -} diff --git a/mempool/errors.go b/mempool/errors.go deleted file mode 100644 index be520742e..000000000 --- a/mempool/errors.go +++ /dev/null @@ -1,54 +0,0 @@ -package mempool - -import ( - "errors" - "fmt" -) - -var ( - // ErrTxInMap is returned to the client if we saw tx earlier in txsMap - ErrTxInMap = errors.New("tx already exists in txsMap") - // ErrTxInCache is returned to the client if we saw tx earlier in cache - ErrTxInCache = errors.New("tx already exists in cache") -) - -// ErrTxTooLarge means the tx is too big to be sent in a message to other peers -type ErrTxTooLarge struct { - max int - actual int -} - -func (e ErrTxTooLarge) Error() string { - return fmt.Sprintf("Tx too large. Max size is %d, but got %d", e.max, e.actual) -} - -// ErrMempoolIsFull means Ostracon & an application can't handle that much load -type ErrMempoolIsFull struct { - numTxs int - maxTxs int - - txsBytes int64 - maxTxsBytes int64 -} - -func (e ErrMempoolIsFull) Error() string { - return fmt.Sprintf( - "mempool is full: number of txs %d (max: %d), total txs bytes %d (max: %d)", - e.numTxs, e.maxTxs, - e.txsBytes, e.maxTxsBytes) -} - -// ErrPreCheck is returned when tx is too big -type ErrPreCheck struct { - Reason error -} - -func (e ErrPreCheck) Error() string { - return e.Reason.Error() -} - -// IsPreCheckError returns true if err is due to pre check failure. -func IsPreCheckError(err error) bool { - _, ok := err.(ErrPreCheck) - return ok -} diff --git a/mempool/ids.go b/mempool/ids.go new file mode 100644 index 000000000..d64a07bda --- /dev/null +++ b/mempool/ids.go @@ -0,0 +1,3 @@ +package mempool + +// These functions were moved into v0/reactor.go and v1/reactor.go diff --git a/mempool/ids_test.go b/mempool/ids_test.go new file mode 100644 index 000000000..2d72076e7 --- /dev/null +++ b/mempool/ids_test.go @@ -0,0 +1,23 @@ +package mempool + +// import ( +// "testing" + +// "github.com/stretchr/testify/require" +// "github.com/tendermint/tendermint/types" +// ) + +// func TestMempoolIDsBasic(t *testing.T) { +// ids := NewMempoolIDs() + +// peerID, err := types.NewNodeID("0011223344556677889900112233445566778899") +// require.NoError(t, err) + +// ids.ReserveForPeer(peerID) +// require.EqualValues(t, 1, ids.GetForPeer(peerID)) +// ids.Reclaim(peerID) + +// ids.ReserveForPeer(peerID) +// require.EqualValues(t, 2, ids.GetForPeer(peerID)) +// ids.Reclaim(peerID) +// } diff --git a/mempool/mempool.go b/mempool/mempool.go index beb3110a1..818039a93 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -1,49 +1,73 @@ package mempool import ( + "crypto/sha256" + "errors" "fmt" + "math" abci "github.com/tendermint/tendermint/abci/types" ocabci "github.com/Finschia/ostracon/abci/types" - "github.com/Finschia/ostracon/p2p" "github.com/Finschia/ostracon/types" ) +const ( + MempoolChannel = byte(0x30) + + // PeerCatchupSleepIntervalMS defines how much time to sleep if a peer is behind + PeerCatchupSleepIntervalMS = 100 + + // UnknownPeerID is the peer ID to use when running CheckTx when there is + // no peer (e.g. RPC) + UnknownPeerID uint16 = 0 + + MaxActiveIDs = math.MaxUint16 +) + // Mempool defines the mempool interface. // // Updates to the mempool need to be synchronized with committing a block so -// apps can reset their transient state on Commit. +// applications can reset their transient state on Commit. type Mempool interface { // CheckTx executes a new transaction against the application to determine // its validity and whether it should be added to the mempool. - CheckTxSync(tx types.Tx, txInfo TxInfo) (*ocabci.Response, error) + CheckTxSync(tx types.Tx, checkTxCb func(*ocabci.Response), txInfo TxInfo) error CheckTxAsync(tx types.Tx, txInfo TxInfo, prepareCb func(error), checkTxCb func(*ocabci.Response)) + // RemoveTxByKey removes a transaction, identified by its key, + // from the mempool. + RemoveTxByKey(txKey types.TxKey) error + // ReapMaxBytesMaxGas reaps transactions from the mempool up to maxBytes // bytes total with the condition that the total gasWanted must be less than // maxGas. + // // If both maxes are negative, there is no cap on the size of all returned // transactions (~ all available transactions). ReapMaxBytesMaxGas(maxBytes, maxGas int64) types.Txs - // Puts cap on txs as well on top of ReapMaxBytesMaxGas + // ReapMaxBytesMaxGasMaxTxs puts cap on txs as well on top of ReapMaxBytesMaxGas ReapMaxBytesMaxGasMaxTxs(maxBytes, maxGas, maxTxs int64) types.Txs - // ReapMaxTxs reaps up to max transactions from the mempool. - // If max is negative, there is no cap on the size of all returned - // transactions (~ all available transactions). + // ReapMaxTxs reaps up to max transactions from the mempool. If max is + // negative, there is no cap on the size of all returned transactions + // (~ all available transactions). ReapMaxTxs(max int) types.Txs - // Lock locks the mempool. The consensus must be able to hold lock to safely update. + // Lock locks the mempool. The consensus must be able to hold lock to safely + // update. Lock() // Unlock unlocks the mempool. Unlock() - // Update informs the mempool that the given txs were committed and can be discarded. - // NOTE: this should be called *after* block is committed by consensus. - // NOTE: Lock/Unlock must be managed by caller + // Update informs the mempool that the given txs were committed and can be + // discarded. + // + // NOTE: + // 1. This should be called *after* block is committed by consensus. + // 2. Lock/Unlock must be managed by the caller. Update( block *types.Block, deliverTxResponses []*abci.ResponseDeliverTx, @@ -51,17 +75,21 @@ type Mempool interface { newPostFn PostCheckFunc, ) error - // FlushAppConn flushes the mempool connection to ensure async reqResCb calls are - // done. E.g. from CheckTx. - // NOTE: Lock/Unlock must be managed by caller + // FlushAppConn flushes the mempool connection to ensure async callback calls + // are done, e.g. from CheckTx. + // + // NOTE: + // 1. Lock/Unlock must be managed by caller. FlushAppConn() error - // Flush removes all transactions from the mempool and cache + // Flush removes all transactions from the mempool and caches. Flush() - // TxsAvailable returns a channel which fires once for every height, - // and only when transactions are available in the mempool. - // NOTE: the returned channel may be nil if EnableTxsAvailable was not called. + // TxsAvailable returns a channel which fires once for every height, and only + // when transactions are available in the mempool. + // + // NOTE: + // 1. The returned channel may be nil if EnableTxsAvailable was not called. TxsAvailable() <-chan struct{} // EnableTxsAvailable initializes the TxsAvailable channel, ensuring it will @@ -71,20 +99,10 @@ type Mempool interface { // Size returns the number of transactions in the mempool. Size() int - // TxsBytes returns the total size of all txs in the mempool. - TxsBytes() int64 - - // InitWAL creates a directory for the WAL file and opens a file itself. If - // there is an error, it will be of type *PathError. - InitWAL() error - - // CloseWAL closes and discards the underlying WAL file. - // Any further writes will not be relayed to disk. - CloseWAL() + // SizeBytes returns the total size of all txs in the mempool. + SizeBytes() int64 } -//-------------------------------------------------------------------------------- - // PreCheckFunc is an optional filter executed before CheckTx and rejects // transaction if false is returned. An example would be to ensure that a // transaction doesn't exceeded the block size. @@ -95,27 +113,16 @@ type PreCheckFunc func(types.Tx) error // transaction doesn't require more gas than available for the block. type PostCheckFunc func(types.Tx, *ocabci.ResponseCheckTx) error -// TxInfo are parameters that get passed when attempting to add a tx to the -// mempool. -type TxInfo struct { - // SenderID is the internal peer ID used in the mempool to identify the - // sender, storing 2 bytes with each tx instead of 20 bytes for the p2p.ID. - SenderID uint16 - // SenderP2PID is the actual p2p.ID of the sender, used e.g. for logging. - SenderP2PID p2p.ID -} - -//-------------------------------------------------------------------------------- - -// PreCheckMaxBytes checks that the size of the transaction is smaller or equal to the expected maxBytes. +// PreCheckMaxBytes checks that the size of the transaction is smaller or equal +// to the expected maxBytes. func PreCheckMaxBytes(maxBytes int64) PreCheckFunc { return func(tx types.Tx) error { txSize := types.ComputeProtoSizeForTxs([]types.Tx{tx}) if txSize > maxBytes { - return fmt.Errorf("tx size is too big: %d, max: %d", - txSize, maxBytes) + return fmt.Errorf("tx size is too big: %d, max: %d", txSize, maxBytes) } + return nil } } @@ -135,6 +142,60 @@ func PostCheckMaxGas(maxGas int64) PostCheckFunc { return fmt.Errorf("gas wanted %d is greater than max gas %d", res.GasWanted, maxGas) } + return nil } } + +// ErrTxInMap is returned to the client if we saw tx earlier in txsMap +var ErrTxInMap = errors.New("tx already exists in txsMap") + +// ErrTxInCache is returned to the client if we saw tx earlier +var ErrTxInCache = errors.New("tx already exists in cache") + +// TxKey is the fixed length array key used as an index. +type TxKey [sha256.Size]byte + +// ErrTxTooLarge defines an error when a transaction is too big to be sent in a +// message to other peers. +type ErrTxTooLarge struct { + Max int + Actual int +} + +func (e ErrTxTooLarge) Error() string { + return fmt.Sprintf("Tx too large. Max size is %d, but got %d", e.Max, e.Actual) +} + +// ErrMempoolIsFull defines an error where Tendermint and the application cannot +// handle that much load. +type ErrMempoolIsFull struct { + NumTxs int + MaxTxs int + TxsBytes int64 + MaxTxsBytes int64 +} + +func (e ErrMempoolIsFull) Error() string { + return fmt.Sprintf( + "mempool is full: number of txs %d (max: %d), total txs bytes %d (max: %d)", + e.NumTxs, + e.MaxTxs, + e.TxsBytes, + e.MaxTxsBytes, + ) +} + +// ErrPreCheck defines an error where a transaction fails a pre-check. +type ErrPreCheck struct { + Reason error +} + +func (e ErrPreCheck) Error() string { + return e.Reason.Error() +} + +// IsPreCheckError returns true if err is due to pre check failure. +func IsPreCheckError(err error) bool { + return errors.As(err, &ErrPreCheck{}) +} diff --git a/mempool/mempool_test.go b/mempool/mempool_test.go index 9c5e9f469..b42cae5f4 100644 --- a/mempool/mempool_test.go +++ b/mempool/mempool_test.go @@ -3,8 +3,9 @@ package mempool import ( "testing" - abci "github.com/Finschia/ostracon/abci/types" "github.com/stretchr/testify/require" + + abci "github.com/Finschia/ostracon/abci/types" ) func TestPostCheckMaxGas(t *testing.T) { diff --git a/mempool/metrics.go b/mempool/metrics.go index 39459de69..02affca70 100644 --- a/mempool/metrics.go +++ b/mempool/metrics.go @@ -18,12 +18,27 @@ const ( type Metrics struct { // Size of the mempool. Size metrics.Gauge + // Histogram of transaction sizes, in bytes. TxSizeBytes metrics.Histogram + // Number of failed transactions. FailedTxs metrics.Counter + + // RejectedTxs defines the number of rejected transactions. These are + // transactions that passed CheckTx but failed to make it into the mempool + // due to resource limits, e.g. mempool is full and no lower priority + // transactions exist in the mempool. + RejectedTxs metrics.Counter + + // EvictedTxs defines the number of evicted transactions. These are valid + // transactions that passed CheckTx and existed in the mempool but were later + // evicted to make room for higher priority valid transactions that passed + // CheckTx. + EvictedTxs metrics.Counter + // Number of times transactions are rechecked in the mempool. - RecheckCount metrics.Counter + RecheckTimes metrics.Counter // Time of recheck transactions in the mempool. RecheckTime metrics.Gauge } @@ -43,6 +58,7 @@ func PrometheusMetrics(namespace string, labelsAndValues ...string) *Metrics { Name: "size", Help: "Size of the mempool (number of uncommitted transactions).", }, labels).With(labelsAndValues...), + TxSizeBytes: prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{ Namespace: namespace, Subsystem: MetricsSubsystem, @@ -50,18 +66,35 @@ func PrometheusMetrics(namespace string, labelsAndValues ...string) *Metrics { Help: "Transaction sizes in bytes.", Buckets: stdprometheus.ExponentialBuckets(1, 3, 17), }, labels).With(labelsAndValues...), + FailedTxs: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ Namespace: namespace, Subsystem: MetricsSubsystem, Name: "failed_txs", Help: "Number of failed transactions.", }, labels).With(labelsAndValues...), - RecheckCount: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ + RejectedTxs: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "rejected_txs", + Help: "Number of rejected transactions.", + }, labels).With(labelsAndValues...), + + EvictedTxs: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "evicted_txs", + Help: "Number of evicted transactions.", + }, labels).With(labelsAndValues...), + + RecheckTimes: prometheus.NewCounterFrom(stdprometheus.CounterOpts{ Namespace: namespace, Subsystem: MetricsSubsystem, - Name: "recheck_count", + Name: "recheck_times", Help: "Number of times transactions are rechecked in the mempool.", }, labels).With(labelsAndValues...), + + // Add by Ostracon RecheckTime: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ Namespace: namespace, Subsystem: MetricsSubsystem, @@ -77,7 +110,9 @@ func NopMetrics() *Metrics { Size: discard.NewGauge(), TxSizeBytes: discard.NewHistogram(), FailedTxs: discard.NewCounter(), - RecheckCount: discard.NewCounter(), + RejectedTxs: discard.NewCounter(), + EvictedTxs: discard.NewCounter(), + RecheckTimes: discard.NewCounter(), RecheckTime: discard.NewGauge(), } } diff --git a/mempool/mock/mempool.go b/mempool/mock/mempool.go index 163646c25..3af779b39 100644 --- a/mempool/mock/mempool.go +++ b/mempool/mock/mempool.go @@ -5,31 +5,32 @@ import ( ocabci "github.com/Finschia/ostracon/abci/types" "github.com/Finschia/ostracon/libs/clist" - mempl "github.com/Finschia/ostracon/mempool" + "github.com/Finschia/ostracon/mempool" "github.com/Finschia/ostracon/types" ) // Mempool is an empty implementation of a Mempool, useful for testing. type Mempool struct{} -var _ mempl.Mempool = Mempool{} +var _ mempool.Mempool = Mempool{} func (Mempool) Lock() {} func (Mempool) Unlock() {} func (Mempool) Size() int { return 0 } -func (Mempool) CheckTxSync(_ types.Tx, _ mempl.TxInfo) (*ocabci.Response, error) { - return nil, nil +func (Mempool) CheckTxSync(_ types.Tx, _ func(*ocabci.Response), _ mempool.TxInfo) error { + return nil } -func (Mempool) CheckTxAsync(_ types.Tx, _ mempl.TxInfo, _ func(error), _ func(*ocabci.Response)) { +func (Mempool) CheckTxAsync(_ types.Tx, _ mempool.TxInfo, _ func(error), _ func(*ocabci.Response)) { } +func (Mempool) RemoveTxByKey(txKey types.TxKey) error { return nil } func (Mempool) ReapMaxBytesMaxGas(_, _ int64) types.Txs { return types.Txs{} } func (Mempool) ReapMaxBytesMaxGasMaxTxs(_, _, _ int64) types.Txs { return types.Txs{} } func (Mempool) ReapMaxTxs(n int) types.Txs { return types.Txs{} } func (Mempool) Update( _ *types.Block, _ []*abci.ResponseDeliverTx, - _ mempl.PreCheckFunc, - _ mempl.PostCheckFunc, + _ mempool.PreCheckFunc, + _ mempool.PostCheckFunc, ) error { return nil } @@ -37,7 +38,7 @@ func (Mempool) Flush() {} func (Mempool) FlushAppConn() error { return nil } func (Mempool) TxsAvailable() <-chan struct{} { return make(chan struct{}) } func (Mempool) EnableTxsAvailable() {} -func (Mempool) TxsBytes() int64 { return 0 } +func (Mempool) SizeBytes() int64 { return 0 } func (Mempool) TxsFront() *clist.CElement { return nil } func (Mempool) TxsWaitChan() <-chan struct{} { return nil } diff --git a/mempool/tx.go b/mempool/tx.go new file mode 100644 index 000000000..e93faa69c --- /dev/null +++ b/mempool/tx.go @@ -0,0 +1,17 @@ +package mempool + +import ( + "github.com/Finschia/ostracon/p2p" +) + +// TxInfo are parameters that get passed when attempting to add a tx to the +// mempool. +type TxInfo struct { + // SenderID is the internal peer ID used in the mempool to identify the + // sender, storing two bytes with each transaction instead of 20 bytes for + // the types.NodeID. + SenderID uint16 + + // SenderP2PID is the actual p2p.ID of the sender, used e.g. for logging. + SenderP2PID p2p.ID +} diff --git a/mempool/v0/bench_test.go b/mempool/v0/bench_test.go new file mode 100644 index 000000000..6da51267f --- /dev/null +++ b/mempool/v0/bench_test.go @@ -0,0 +1,101 @@ +package v0 + +import ( + "encoding/binary" + "sync/atomic" + "testing" + + "github.com/Finschia/ostracon/abci/example/kvstore" + "github.com/Finschia/ostracon/mempool" + "github.com/Finschia/ostracon/proxy" +) + +func BenchmarkReap(b *testing.B) { + app := kvstore.NewApplication() + cc := proxy.NewLocalClientCreator(app) + mp, cleanup := newMempoolWithApp(cc) + defer cleanup() + + mp.config.Size = 100000 + + size := 10000 + for i := 0; i < size; i++ { + tx := make([]byte, 8) + binary.BigEndian.PutUint64(tx, uint64(i)) + if err := mp.CheckTxSync(tx, nil, mempool.TxInfo{}); err != nil { + b.Fatal(err) + } + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + mp.ReapMaxBytesMaxGas(100000000, 10000000) + } +} + +func BenchmarkCheckTx(b *testing.B) { + app := kvstore.NewApplication() + cc := proxy.NewLocalClientCreator(app) + mp, cleanup := newMempoolWithApp(cc) + defer cleanup() + + mp.config.Size = 1000000 + + b.ResetTimer() + + for i := 0; i < b.N; i++ { + b.StopTimer() + tx := make([]byte, 8) + binary.BigEndian.PutUint64(tx, uint64(i)) + b.StartTimer() + + if err := mp.CheckTxSync(tx, nil, mempool.TxInfo{}); err != nil { + b.Fatal(err) + } + } +} + +func BenchmarkParallelCheckTx(b *testing.B) { + app := kvstore.NewApplication() + cc := proxy.NewLocalClientCreator(app) + mp, cleanup := newMempoolWithApp(cc) + defer cleanup() + + mp.config.Size = 100000000 + + var txcnt uint64 + next := func() uint64 { + return atomic.AddUint64(&txcnt, 1) - 1 + } + + b.ResetTimer() + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + tx := make([]byte, 8) + binary.BigEndian.PutUint64(tx, next()) + if err := mp.CheckTxSync(tx, nil, mempool.TxInfo{}); err != nil { + b.Fatal(err) + } + } + }) +} + +func BenchmarkCheckDuplicateTx(b *testing.B) { + app := kvstore.NewApplication() + cc := proxy.NewLocalClientCreator(app) + mp, cleanup := newMempoolWithApp(cc) + defer cleanup() + + mp.config.Size = 1000000 + + for i := 0; i < b.N; i++ { + tx := make([]byte, 8) + binary.BigEndian.PutUint64(tx, uint64(i)) + if err := mp.CheckTxSync(tx, nil, mempool.TxInfo{}); err != nil { + b.Fatal(err) + } + + if err := mp.CheckTxSync(tx, nil, mempool.TxInfo{}); err == nil { + b.Fatal("tx should be duplicate") + } + } +} diff --git a/mempool/v0/cache_test.go b/mempool/v0/cache_test.go new file mode 100644 index 000000000..aa58b2da2 --- /dev/null +++ b/mempool/v0/cache_test.go @@ -0,0 +1,81 @@ +package v0 + +import ( + "crypto/sha256" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/Finschia/ostracon/abci/example/kvstore" + abci "github.com/Finschia/ostracon/abci/types" + "github.com/Finschia/ostracon/mempool" + "github.com/Finschia/ostracon/proxy" + "github.com/Finschia/ostracon/types" +) + +func TestCacheAfterUpdate(t *testing.T) { + app := kvstore.NewApplication() + cc := proxy.NewLocalClientCreator(app) + mp, cleanup := newMempoolWithApp(cc) + defer cleanup() + + // reAddIndices & txsInCache can have elements > numTxsToCreate + // also assumes max index is 255 for convenience + // txs in cache also checks order of elements + tests := []struct { + numTxsToCreate int + updateIndices []int + reAddIndices []int + txsInCache []int + }{ + {1, []int{}, []int{1}, []int{1, 0}}, // adding new txs works + {2, []int{1}, []int{}, []int{1, 0}}, // update doesn't remove tx from cache + {2, []int{2}, []int{}, []int{2, 1, 0}}, // update adds new tx to cache + {2, []int{1}, []int{1}, []int{1, 0}}, // re-adding after update doesn't make dupe + } + for tcIndex, tc := range tests { + for i := 0; i < tc.numTxsToCreate; i++ { + tx := types.Tx{byte(i)} + err := mp.CheckTxSync(tx, nil, mempool.TxInfo{}) + require.NoError(t, err) + } + + updateTxs := []types.Tx{} + for _, v := range tc.updateIndices { + tx := types.Tx{byte(v)} + updateTxs = append(updateTxs, tx) + } + err := mp.Update(newTestBlock(int64(tcIndex), updateTxs), abciResponses(len(updateTxs), abci.CodeTypeOK), nil, nil) + require.NoError(t, err) + + for _, v := range tc.reAddIndices { + tx := types.Tx{byte(v)} + _ = mp.CheckTxSync(tx, nil, mempool.TxInfo{}) + } + + cache := mp.cache.(*mempool.LRUTxCache) + node := cache.GetList().Front() + counter := 0 + for node != nil { + require.NotEqual(t, len(tc.txsInCache), counter, + "cache larger than expected on testcase %d", tcIndex) + + nodeVal := node.Value.(types.TxKey) + expectedBz := sha256.Sum256([]byte{byte(tc.txsInCache[len(tc.txsInCache)-counter-1])}) + // Reference for reading the errors: + // >>> sha256('\x00').hexdigest() + // '6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d' + // >>> sha256('\x01').hexdigest() + // '4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a' + // >>> sha256('\x02').hexdigest() + // 'dbc1b4c900ffe48d575b5da5c638040125f65db0fe3e24494b76ea986457d986' + + require.EqualValues(t, expectedBz, nodeVal, "Equality failed on index %d, tc %d", counter, tcIndex) + counter++ + node = node.Next() + } + require.Equal(t, len(tc.txsInCache), counter, + "cache smaller than expected on testcase %d", tcIndex) + mp.Flush() + } +} diff --git a/mempool/clist_mempool.go b/mempool/v0/clist_mempool.go similarity index 73% rename from mempool/clist_mempool.go rename to mempool/v0/clist_mempool.go index 36fa25edc..e836fad40 100644 --- a/mempool/clist_mempool.go +++ b/mempool/v0/clist_mempool.go @@ -1,36 +1,27 @@ -package mempool +package v0 import ( - "container/list" - "crypto/sha256" - "fmt" + "errors" "sync" "sync/atomic" "time" + "github.com/Finschia/ostracon/config" + "github.com/Finschia/ostracon/mempool" + abci "github.com/tendermint/tendermint/abci/types" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" ocabci "github.com/Finschia/ostracon/abci/types" - cfg "github.com/Finschia/ostracon/config" - auto "github.com/Finschia/ostracon/libs/autofile" "github.com/Finschia/ostracon/libs/clist" "github.com/Finschia/ostracon/libs/log" tmmath "github.com/Finschia/ostracon/libs/math" - tmos "github.com/Finschia/ostracon/libs/os" tmsync "github.com/Finschia/ostracon/libs/sync" "github.com/Finschia/ostracon/p2p" "github.com/Finschia/ostracon/proxy" "github.com/Finschia/ostracon/types" ) -// TxKeySize is the size of the transaction key index -const TxKeySize = sha256.Size - -var newline = []byte("\n") - -//-------------------------------------------------------------------------------- - // CListMempool is an ordered in-memory pool for transactions before they are // proposed in a consensus round. Transaction validity is checked using the // CheckTx abci message before the transaction is added to the pool. The @@ -49,19 +40,17 @@ type CListMempool struct { notifiedTxsAvailable bool txsAvailable chan struct{} // fires once for each height, when the mempool is not empty - config *cfg.MempoolConfig + config *config.MempoolConfig // Exclusive mutex for Update method to prevent concurrent execution of // CheckTx or ReapMaxBytesMaxGas(ReapMaxTxs) methods. updateMtx tmsync.RWMutex - preCheck PreCheckFunc + preCheck mempool.PreCheckFunc + postCheck mempool.PostCheckFunc chReqCheckTx chan *requestCheckTxAsync - postCheck PostCheckFunc - - wal *auto.AutoFile // a log of mempool txs - txs *clist.CList // concurrent linked-list of good txs + txs *clist.CList // concurrent linked-list of good txs proxyAppConn proxy.AppConnMempool // Map for quick access to txs to record sender in CheckTx. @@ -70,52 +59,54 @@ type CListMempool struct { // Keep a cache of already-seen txs. // This reduces the pressure on the proxyApp. - cache txCache + cache mempool.TxCache - logger log.Logger - - metrics *Metrics + logger log.Logger + metrics *mempool.Metrics } type requestCheckTxAsync struct { tx types.Tx - txInfo TxInfo + txInfo mempool.TxInfo prepareCb func(error) checkTxCb func(*ocabci.Response) } -var _ Mempool = &CListMempool{} +var _ mempool.Mempool = &CListMempool{} // CListMempoolOption sets an optional parameter on the mempool. type CListMempoolOption func(*CListMempool) -// NewCListMempool returns a new mempool with the given configuration and connection to an application. +// NewCListMempool returns a new mempool with the given configuration and +// connection to an application. func NewCListMempool( - config *cfg.MempoolConfig, + cfg *config.MempoolConfig, proxyAppConn proxy.AppConnMempool, height int64, options ...CListMempoolOption, ) *CListMempool { - mempool := &CListMempool{ - config: config, + mp := &CListMempool{ + config: cfg, proxyAppConn: proxyAppConn, txs: clist.New(), height: height, - chReqCheckTx: make(chan *requestCheckTxAsync, config.Size), + chReqCheckTx: make(chan *requestCheckTxAsync, cfg.Size), logger: log.NewNopLogger(), - metrics: NopMetrics(), + metrics: mempool.NopMetrics(), } - if config.CacheSize > 0 { - mempool.cache = newMapTxCache(config.CacheSize) + + if cfg.CacheSize > 0 { + mp.cache = mempool.NewLRUTxCache(cfg.CacheSize) } else { - mempool.cache = nopTxCache{} + mp.cache = mempool.NopTxCache{} } - proxyAppConn.SetGlobalCallback(mempool.globalCb) + proxyAppConn.SetGlobalCallback(mp.globalCb) + for _, option := range options { - option(mempool) + option(mp) } - go mempool.checkTxAsyncReactor() - return mempool + go mp.checkTxAsyncReactor() + return mp } // NOTE: not thread safe - should only be called once, on startup @@ -131,49 +122,22 @@ func (mem *CListMempool) SetLogger(l log.Logger) { // WithPreCheck sets a filter for the mempool to reject a tx if f(tx) returns // false. This is ran before CheckTx. Only applies to the first created block. // After that, Update overwrites the existing value. -func WithPreCheck(f PreCheckFunc) CListMempoolOption { +func WithPreCheck(f mempool.PreCheckFunc) CListMempoolOption { return func(mem *CListMempool) { mem.preCheck = f } } // WithPostCheck sets a filter for the mempool to reject a tx if f(tx) returns // false. This is ran after CheckTx. Only applies to the first created block. // After that, Update overwrites the existing value. -func WithPostCheck(f PostCheckFunc) CListMempoolOption { +func WithPostCheck(f mempool.PostCheckFunc) CListMempoolOption { return func(mem *CListMempool) { mem.postCheck = f } } // WithMetrics sets the metrics. -func WithMetrics(metrics *Metrics) CListMempoolOption { +func WithMetrics(metrics *mempool.Metrics) CListMempoolOption { return func(mem *CListMempool) { mem.metrics = metrics } } -func (mem *CListMempool) InitWAL() error { - var ( - walDir = mem.config.WalDir() - walFile = walDir + "/wal" - ) - - const perm = 0700 - if err := tmos.EnsureDir(walDir, perm); err != nil { - return err - } - - af, err := auto.OpenAutoFile(walFile) - if err != nil { - return fmt.Errorf("can't open autofile %s: %w", walFile, err) - } - - mem.wal = af - return nil -} - -func (mem *CListMempool) CloseWAL() { - if err := mem.wal.Close(); err != nil { - mem.logger.Error("Error closing WAL", "err", err) - } - mem.wal = nil -} - // Safe for concurrent use by multiple goroutines. func (mem *CListMempool) Lock() { mem.updateMtx.Lock() @@ -190,7 +154,7 @@ func (mem *CListMempool) Size() int { } // Safe for concurrent use by multiple goroutines. -func (mem *CListMempool) TxsBytes() int64 { +func (mem *CListMempool) SizeBytes() int64 { return atomic.LoadInt64(&mem.txsBytes) } @@ -239,33 +203,43 @@ func (mem *CListMempool) TxsWaitChan() <-chan struct{} { // It blocks if we're waiting on Update() or Reap(). // Safe for concurrent use by multiple goroutines. -func (mem *CListMempool) CheckTxSync(tx types.Tx, txInfo TxInfo) (res *ocabci.Response, err error) { +func (mem *CListMempool) CheckTxSync( + tx types.Tx, + cb func(*ocabci.Response), + txInfo mempool.TxInfo, +) error { + mem.updateMtx.RLock() // use defer to unlock mutex because application (*local client*) might panic defer mem.updateMtx.RUnlock() - if err = mem.prepareCheckTx(tx, txInfo); err != nil { - return res, err + if err := mem.prepareCheckTx(tx, txInfo); err != nil { + return err } // CONTRACT: `app.CheckTxSync()` should check whether `GasWanted` is valid (0 <= GasWanted <= block.masGas) var r *ocabci.ResponseCheckTx - r, err = mem.proxyAppConn.CheckTxSync(abci.RequestCheckTx{Tx: tx}) + r, err := mem.proxyAppConn.CheckTxSync(abci.RequestCheckTx{Tx: tx}) if err != nil { - return res, err + return err } - res = ocabci.ToResponseCheckTx(*r) - mem.reqResCb(tx, txInfo.SenderID, txInfo.SenderP2PID, res, nil) - return res, err + res := ocabci.ToResponseCheckTx(*r) + mem.reqResCb(tx, txInfo.SenderID, txInfo.SenderP2PID, res, cb) + return err } // cb: A callback from the CheckTx command. -// It gets called from another goroutine. +// +// It gets called from another goroutine. // // Safe for concurrent use by multiple goroutines. -func (mem *CListMempool) CheckTxAsync(tx types.Tx, txInfo TxInfo, prepareCb func(error), - checkTxCb func(*ocabci.Response)) { +func (mem *CListMempool) CheckTxAsync( + tx types.Tx, + txInfo mempool.TxInfo, + prepareCb func(error), + checkTxCb func(*ocabci.Response), +) { mem.chReqCheckTx <- &requestCheckTxAsync{tx: tx, txInfo: txInfo, prepareCb: prepareCb, checkTxCb: checkTxCb} } @@ -276,8 +250,12 @@ func (mem *CListMempool) checkTxAsyncReactor() { } // It blocks if we're waiting on Update() or Reap(). -func (mem *CListMempool) checkTxAsync(tx types.Tx, txInfo TxInfo, prepareCb func(error), - checkTxCb func(*ocabci.Response)) { +func (mem *CListMempool) checkTxAsync( + tx types.Tx, + txInfo mempool.TxInfo, + prepareCb func(error), + checkTxCb func(*ocabci.Response), +) { mem.updateMtx.RLock() defer func() { if r := recover(); r != nil { @@ -307,10 +285,10 @@ func (mem *CListMempool) checkTxAsync(tx types.Tx, txInfo TxInfo, prepareCb func } // CONTRACT: `caller` should held `mem.updateMtx.RLock()` -func (mem *CListMempool) prepareCheckTx(tx types.Tx, txInfo TxInfo) error { +func (mem *CListMempool) prepareCheckTx(tx types.Tx, txInfo mempool.TxInfo) error { // For keeping the consistency between `mem.txs` and `mem.txsMap` - if _, ok := mem.txsMap.Load(TxKey(tx)); ok { - return ErrTxInMap + if _, ok := mem.txsMap.Load(tx.Key()); ok { + return mempool.ErrTxInMap } txSize := len(tx) @@ -320,24 +298,17 @@ func (mem *CListMempool) prepareCheckTx(tx types.Tx, txInfo TxInfo) error { } if txSize > mem.config.MaxTxBytes { - return ErrTxTooLarge{mem.config.MaxTxBytes, txSize} + return mempool.ErrTxTooLarge{ + Max: mem.config.MaxTxBytes, + Actual: txSize, + } } if mem.preCheck != nil { if err := mem.preCheck(tx); err != nil { - return ErrPreCheck{err} - } - } - - // NOTE: writing to the WAL and calling proxy must be done before adding tx - // to the cache. otherwise, if either of them fails, next time CheckTx is - // called with tx, ErrTxInCache will be returned without tx being checked at - // all even once. - if mem.wal != nil { - // TODO: Notify administrators when WAL fails - _, err := mem.wal.Write(append([]byte(tx), newline...)) - if err != nil { - return fmt.Errorf("wal.Write: %w", err) + return mempool.ErrPreCheck{ + Reason: err, + } } } @@ -346,20 +317,19 @@ func (mem *CListMempool) prepareCheckTx(tx types.Tx, txInfo TxInfo) error { return err } - if !mem.cache.Push(tx) { + if !mem.cache.Push(tx) { // if the transaction already exists in the cache // Record a new sender for a tx we've already seen. // Note it's possible a tx is still in the cache but no longer in the mempool // (eg. after committing a block, txs are removed from mempool but not cache), // so we only record the sender for txs still in the mempool. - if e, ok := mem.txsMap.Load(TxKey(tx)); ok { + if e, ok := mem.txsMap.Load(tx.Key()); ok { memTx := e.(*clist.CElement).Value.(*mempoolTx) memTx.senders.LoadOrStore(txInfo.SenderID, true) // TODO: consider punishing peer for dups, // its non-trivial since invalid txs can become valid, // but they can spam the same tx with little cost to them atm. } - - return ErrTxInCache + return mempool.ErrTxInCache } // reserve mempool that should be called just before calling `mem.proxyAppConn.CheckTxAsync()` @@ -388,7 +358,7 @@ func (mem *CListMempool) globalCb(req *ocabci.Request, res *ocabci.Response) { } if checkTxReq.Type == abci.CheckTxType_Recheck { - mem.metrics.RecheckCount.Add(1) + mem.metrics.RecheckTimes.Add(1) mem.resCbRecheck(req, res) // update metrics @@ -424,21 +394,21 @@ func (mem *CListMempool) reqResCb( } // Called from: -// - resCbFirstTime (lock not held) if tx is valid +// - resCbFirstTime (lock not held) if tx is valid func (mem *CListMempool) addTx(memTx *mempoolTx) { e := mem.txs.PushBack(memTx) - mem.txsMap.Store(TxKey(memTx.tx), e) + mem.txsMap.Store(memTx.tx.Key(), e) atomic.AddInt64(&mem.txsBytes, int64(len(memTx.tx))) mem.metrics.TxSizeBytes.Observe(float64(len(memTx.tx))) } // Called from: -// - Update (lock held) if tx was committed -// - resCbRecheck (lock not held) if tx was invalidated +// - Update (lock held) if tx was committed +// - resCbRecheck (lock not held) if tx was invalidated func (mem *CListMempool) removeTx(tx types.Tx, elem *clist.CElement, removeFromCache bool) { mem.txs.Remove(elem) elem.DetachPrev() - mem.txsMap.Delete(TxKey(tx)) + mem.txsMap.Delete(tx.Key()) atomic.AddInt64(&mem.txsBytes, int64(-len(tx))) if removeFromCache { @@ -447,25 +417,30 @@ func (mem *CListMempool) removeTx(tx types.Tx, elem *clist.CElement, removeFromC } // RemoveTxByKey removes a transaction from the mempool by its TxKey index. -func (mem *CListMempool) RemoveTxByKey(txKey [TxKeySize]byte, removeFromCache bool) { +func (mem *CListMempool) RemoveTxByKey(txKey types.TxKey) error { if e, ok := mem.txsMap.Load(txKey); ok { memTx := e.(*clist.CElement).Value.(*mempoolTx) if memTx != nil { - mem.removeTx(memTx.tx, e.(*clist.CElement), removeFromCache) + mem.removeTx(memTx.tx, e.(*clist.CElement), false) + return nil } + return errors.New("transaction not found") } + return errors.New("invalid transaction found") } func (mem *CListMempool) isFull(txSize int) error { var ( memSize = mem.Size() - txsBytes = mem.TxsBytes() + txsBytes = mem.SizeBytes() ) if memSize >= mem.config.Size || int64(txSize)+txsBytes > mem.config.MaxTxsBytes { - return ErrMempoolIsFull{ - memSize, mem.config.Size, - txsBytes, mem.config.MaxTxsBytes, + return mempool.ErrMempoolIsFull{ + NumTxs: memSize, + MaxTxs: mem.config.Size, + TxsBytes: txsBytes, + MaxTxsBytes: mem.config.MaxTxsBytes, } } @@ -478,13 +453,15 @@ func (mem *CListMempool) reserve(txSize int64) error { var ( memSize = mem.Size() - txsBytes = mem.TxsBytes() + txsBytes = mem.SizeBytes() ) if memSize+mem.reserved >= mem.config.Size || txSize+mem.reservedBytes+txsBytes > mem.config.MaxTxsBytes { - return ErrMempoolIsFull{ - memSize + mem.reserved, mem.config.Size, - txsBytes + mem.reservedBytes, mem.config.MaxTxsBytes, + return mempool.ErrMempoolIsFull{ + NumTxs: memSize + mem.reserved, + MaxTxs: mem.config.Size, + TxsBytes: txsBytes + mem.reservedBytes, + MaxTxsBytes: mem.config.MaxTxsBytes, } } @@ -521,8 +498,9 @@ func (mem *CListMempool) resCbFirstTime( } memTx.senders.Store(peerID, true) mem.addTx(memTx) - mem.logger.Debug("added good transaction", - "tx", txID(tx), + mem.logger.Debug( + "added good transaction", + "tx", types.Tx(tx).Hash(), "res", r, "height", memTx.height, "total", mem.Size(), @@ -530,9 +508,14 @@ func (mem *CListMempool) resCbFirstTime( mem.notifyTxsAvailable() } else { // ignore bad transaction - mem.logger.Debug("rejected bad transaction", - "tx", txID(tx), "peerID", peerP2PID, "res", r) + mem.logger.Debug( + "rejected bad transaction", + "tx", types.Tx(tx).Hash(), + "peerID", peerP2PID, + "res", r, + ) mem.metrics.FailedTxs.Add(1) + if !mem.config.KeepInvalidTxsInCache { // remove from cache (it might be good later) mem.cache.Remove(tx) @@ -554,12 +537,12 @@ func (mem *CListMempool) resCbRecheck(req *ocabci.Request, res *ocabci.Response) switch r := res.Value.(type) { case *ocabci.Response_CheckTx: tx := req.GetCheckTx().Tx - txHash := TxKey(tx) - e, ok := mem.txsMap.Load(txHash) + e, ok := mem.txsMap.Load(types.Tx(tx).Key()) if !ok { - mem.logger.Debug("re-CheckTx transaction does not exist", "expected", types.Tx(tx)) + mem.logger.Debug("re-CheckTx transaction does not exist", "expected", types.Tx(tx).Hash()) return } + var postCheckErr error if r.CheckTx.Code == ocabci.CodeTypeOK { if mem.postCheck == nil { @@ -573,7 +556,11 @@ func (mem *CListMempool) resCbRecheck(req *ocabci.Request, res *ocabci.Response) } celem := e.(*clist.CElement) // Tx became invalidated due to newly committed block. - mem.logger.Debug("tx is no longer valid", "tx", txID(tx), "res", r, "err", postCheckErr) + mem.logger.Debug("tx is no longer valid", + "tx", types.Tx(tx).Hash(), + "res", r, + "err", postCheckErr, + ) // NOTE: we remove tx from the cache because it might be good later mem.removeTx(tx, celem, !mem.config.KeepInvalidTxsInCache) default: @@ -605,31 +592,40 @@ func (mem *CListMempool) ReapMaxBytesMaxGas(maxBytes, maxGas int64) types.Txs { mem.updateMtx.RLock() defer mem.updateMtx.RUnlock() - var totalGas int64 + var ( + totalGas int64 + runningSize int64 + ) // TODO: we will get a performance boost if we have a good estimate of avg // size per tx, and set the initial capacity based off of that. // txs := make([]types.Tx, 0, tmmath.MinInt(mem.txs.Len(), max/mem.avgTxSize)) txs := make([]types.Tx, 0, mem.txs.Len()) - protoTxs := tmproto.Data{} for e := mem.txs.Front(); e != nil; e = e.Next() { memTx := e.Value.(*mempoolTx) + txs = append(txs, memTx.tx) + + protoTxs := tmproto.Data{} protoTxs.Txs = append(protoTxs.Txs, memTx.tx) + dataSize := int64(protoTxs.Size()) + // Check total size requirement - if maxBytes > -1 && int64(protoTxs.Size()) > maxBytes { - return txs + if maxBytes > -1 && runningSize+dataSize > maxBytes { + return txs[:len(txs)-1] } + + runningSize += dataSize + // Check total gas requirement. // If maxGas is negative, skip this check. // Since newTotalGas < masGas, which // must be non-negative, it follows that this won't overflow. newTotalGas := totalGas + memTx.gasWanted if maxGas > -1 && newTotalGas > maxGas { - return txs + return txs[:len(txs)-1] } totalGas = newTotalGas - txs = append(txs, memTx.tx) } return txs } @@ -639,35 +635,44 @@ func (mem *CListMempool) ReapMaxBytesMaxGasMaxTxs(maxBytes, maxGas, maxTxs int64 mem.updateMtx.RLock() defer mem.updateMtx.RUnlock() - var totalGas int64 - if maxTxs <= 0 { maxTxs = int64(mem.txs.Len()) } + var ( + totalGas int64 + runningSize int64 + ) + // TODO: we will get a performance boost if we have a good estimate of avg // size per tx, and set the initial capacity based off of that. // txs := make([]types.Tx, 0, tmmath.MinInt(mem.txs.Len(), max/mem.avgTxSize)) txs := make([]types.Tx, 0, mem.txs.Len()) - protoTxs := tmproto.Data{} for e := mem.txs.Front(); e != nil && len(txs) < int(maxTxs); e = e.Next() { memTx := e.Value.(*mempoolTx) + txs = append(txs, memTx.tx) + + protoTxs := tmproto.Data{} protoTxs.Txs = append(protoTxs.Txs, memTx.tx) + dataSize := int64(protoTxs.Size()) + // Check total size requirement - if maxBytes > -1 && int64(protoTxs.Size()) > maxBytes { - return txs + if maxBytes > -1 && runningSize+dataSize > maxBytes { + return txs[:len(txs)-1] } + + runningSize += dataSize + // Check total gas requirement. // If maxGas is negative, skip this check. // Since newTotalGas < masGas, which // must be non-negative, it follows that this won't overflow. newTotalGas := totalGas + memTx.gasWanted if maxGas > -1 && newTotalGas > maxGas { - return txs + return txs[:len(txs)-1] } totalGas = newTotalGas - txs = append(txs, memTx.tx) } return txs } @@ -693,8 +698,8 @@ func (mem *CListMempool) ReapMaxTxs(max int) types.Txs { func (mem *CListMempool) Update( block *types.Block, deliverTxResponses []*abci.ResponseDeliverTx, - preCheck PreCheckFunc, - postCheck PostCheckFunc, + preCheck mempool.PreCheckFunc, + postCheck mempool.PostCheckFunc, ) (err error) { // Set height mem.height = block.Height @@ -726,7 +731,7 @@ func (mem *CListMempool) Update( // Mempool after: // 100 // https://github.com/tendermint/tendermint/issues/3322. - if e, ok := mem.txsMap.Load(TxKey(tx)); ok { + if e, ok := mem.txsMap.Load(tx.Key()); ok { mem.removeTx(tx, e.(*clist.CElement), false) } } @@ -809,98 +814,3 @@ type mempoolTx struct { func (memTx *mempoolTx) Height() int64 { return atomic.LoadInt64(&memTx.height) } - -//-------------------------------------------------------------------------------- - -type txCache interface { - Reset() - Push(tx types.Tx) bool - Remove(tx types.Tx) -} - -// mapTxCache maintains a LRU cache of transactions. This only stores the hash -// of the tx, due to memory concerns. -type mapTxCache struct { - mtx tmsync.Mutex - size int - cacheMap map[[TxKeySize]byte]*list.Element - list *list.List -} - -var _ txCache = (*mapTxCache)(nil) - -// newMapTxCache returns a new mapTxCache. -func newMapTxCache(cacheSize int) *mapTxCache { - return &mapTxCache{ - size: cacheSize, - cacheMap: make(map[[TxKeySize]byte]*list.Element, cacheSize), - list: list.New(), - } -} - -// Reset resets the cache to an empty state. -func (cache *mapTxCache) Reset() { - cache.mtx.Lock() - cache.cacheMap = make(map[[TxKeySize]byte]*list.Element, cache.size) - cache.list.Init() - cache.mtx.Unlock() -} - -// Push adds the given tx to the cache and returns true. It returns -// false if tx is already in the cache. -func (cache *mapTxCache) Push(tx types.Tx) bool { - cache.mtx.Lock() - defer cache.mtx.Unlock() - - // Use the tx hash in the cache - txHash := TxKey(tx) - if moved, exists := cache.cacheMap[txHash]; exists { - cache.list.MoveToBack(moved) - return false - } - - if cache.list.Len() >= cache.size { - popped := cache.list.Front() - if popped != nil { - poppedTxHash := popped.Value.([TxKeySize]byte) - delete(cache.cacheMap, poppedTxHash) - cache.list.Remove(popped) - } - } - e := cache.list.PushBack(txHash) - cache.cacheMap[txHash] = e - return true -} - -// Remove removes the given tx from the cache. -func (cache *mapTxCache) Remove(tx types.Tx) { - cache.mtx.Lock() - txHash := TxKey(tx) - popped := cache.cacheMap[txHash] - delete(cache.cacheMap, txHash) - if popped != nil { - cache.list.Remove(popped) - } - - cache.mtx.Unlock() -} - -type nopTxCache struct{} - -var _ txCache = (*nopTxCache)(nil) - -func (nopTxCache) Reset() {} -func (nopTxCache) Push(types.Tx) bool { return true } -func (nopTxCache) Remove(types.Tx) {} - -//-------------------------------------------------------------------------------- - -// TxKey is the fixed length array hash used as the key in maps. -func TxKey(tx types.Tx) [TxKeySize]byte { - return sha256.Sum256(tx) -} - -// txID is a hash of the Tx. -func txID(tx []byte) []byte { - return types.Tx(tx).Hash() -} diff --git a/mempool/clist_mempool_system_test.go b/mempool/v0/clist_mempool_system_test.go similarity index 96% rename from mempool/clist_mempool_system_test.go rename to mempool/v0/clist_mempool_system_test.go index 8fc04345f..de329466e 100644 --- a/mempool/clist_mempool_system_test.go +++ b/mempool/v0/clist_mempool_system_test.go @@ -1,4 +1,4 @@ -package mempool +package v0 import ( "context" @@ -13,6 +13,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" tmversion "github.com/tendermint/tendermint/proto/tendermint/version" @@ -21,10 +22,10 @@ import ( ocabci "github.com/Finschia/ostracon/abci/types" "github.com/Finschia/ostracon/config" "github.com/Finschia/ostracon/libs/log" + "github.com/Finschia/ostracon/mempool" "github.com/Finschia/ostracon/proxy" "github.com/Finschia/ostracon/types" "github.com/Finschia/ostracon/version" - "github.com/stretchr/testify/require" ) func setupCListMempool(ctx context.Context, t testing.TB, @@ -122,23 +123,23 @@ func commitBlock(ctx context.Context, t *testing.T, func receiveTx(ctx context.Context, t *testing.T, mem *CListMempool, tx []byte, receiveTxCounter *receiveTxCounter) { atomic.AddInt64(&receiveTxCounter.sent, 1) - txInfo := TxInfo{} + txInfo := mempool.TxInfo{} // mempool.lock/unlock in CheckTxAsync mem.CheckTxAsync(tx, txInfo, func(err error) { if err != nil { switch err { - case ErrTxInCache: + case mempool.ErrTxInCache: atomic.AddInt64(&receiveTxCounter.failInCache, 1) - case ErrTxInMap: + case mempool.ErrTxInMap: atomic.AddInt64(&receiveTxCounter.failInMap, 1) } switch err.(type) { - case ErrTxTooLarge: + case mempool.ErrTxTooLarge: atomic.AddInt64(&receiveTxCounter.failTooLarge, 1) - case ErrMempoolIsFull: + case mempool.ErrMempoolIsFull: atomic.AddInt64(&receiveTxCounter.failIsFull, 1) - case ErrPreCheck: + case mempool.ErrPreCheck: atomic.AddInt64(&receiveTxCounter.failPreCheck, 1) } } diff --git a/mempool/clist_mempool_test.go b/mempool/v0/clist_mempool_test.go similarity index 59% rename from mempool/clist_mempool_test.go rename to mempool/v0/clist_mempool_test.go index 81c1c861f..137244adb 100644 --- a/mempool/clist_mempool_test.go +++ b/mempool/v0/clist_mempool_test.go @@ -1,15 +1,12 @@ -package mempool +package v0 import ( "crypto/rand" - "crypto/sha256" "encoding/binary" "errors" "fmt" - "io/ioutil" mrand "math/rand" "os" - "path/filepath" "sync" "testing" "time" @@ -21,14 +18,15 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/Finschia/ostracon/abci/example/counter" + abciclient "github.com/Finschia/ostracon/abci/client" "github.com/Finschia/ostracon/abci/example/kvstore" abciserver "github.com/Finschia/ostracon/abci/server" ocabci "github.com/Finschia/ostracon/abci/types" - cfg "github.com/Finschia/ostracon/config" + "github.com/Finschia/ostracon/config" "github.com/Finschia/ostracon/libs/log" tmrand "github.com/Finschia/ostracon/libs/rand" "github.com/Finschia/ostracon/libs/service" + "github.com/Finschia/ostracon/mempool" "github.com/Finschia/ostracon/proxy" "github.com/Finschia/ostracon/types" ) @@ -37,20 +35,48 @@ import ( // test. type cleanupFunc func() +//func newMempoolWithAppMock(cc proxy.ClientCreator, client abciclient.Client) (*CListMempool, cleanupFunc, error) { +// conf := config.ResetTestRoot("mempool_test") +// +// mp, cu := newMempoolWithAppAndConfigMock(cc, conf, client) +// return mp, cu, nil +//} +// +//func newMempoolWithAppAndConfigMock(cc proxy.ClientCreator, +// cfg *config.Config, +// client abciclient.Client) (*CListMempool, cleanupFunc) { +// appConnMem := client +// appConnMem.SetLogger(log.TestingLogger().With("module", "abci-client", "connection", "mempool")) +// err := appConnMem.Start() +// if err != nil { +// panic(err) +// } +// +// mp := NewCListMempool(cfg.Mempool, appConnMem, 0) +// mp.SetLogger(log.TestingLogger()) +// +// return mp, func() { os.RemoveAll(cfg.RootDir) } +//} + func newMempoolWithApp(cc proxy.ClientCreator) (*CListMempool, cleanupFunc) { - return newMempoolWithAppAndConfig(cc, cfg.ResetTestRoot("mempool_test")) + conf := config.ResetTestRoot("mempool_test") + + mp, cu := newMempoolWithAppAndConfig(cc, conf) + return mp, cu } -func newMempoolWithAppAndConfig(cc proxy.ClientCreator, config *cfg.Config) (*CListMempool, cleanupFunc) { +func newMempoolWithAppAndConfig(cc proxy.ClientCreator, cfg *config.Config) (*CListMempool, cleanupFunc) { appConnMem, _ := cc.NewABCIClient() appConnMem.SetLogger(log.TestingLogger().With("module", "abci-client", "connection", "mempool")) err := appConnMem.Start() if err != nil { panic(err) } - mempool := NewCListMempool(config.Mempool, appConnMem, 0) - mempool.SetLogger(log.TestingLogger()) - return mempool, func() { os.RemoveAll(config.RootDir) } + + mp := NewCListMempool(cfg.Mempool, appConnMem, 0) + mp.SetLogger(log.TestingLogger()) + + return mp, func() { os.RemoveAll(cfg.RootDir) } } func ensureNoFire(t *testing.T, ch <-chan struct{}, timeoutMS int) { @@ -71,9 +97,9 @@ func ensureFire(t *testing.T, ch <-chan struct{}, timeoutMS int) { } } -func checkTxs(t *testing.T, mempool Mempool, count int, peerID uint16) types.Txs { +func checkTxs(t *testing.T, mp mempool.Mempool, count int, peerID uint16) types.Txs { txs := make(types.Txs, count) - txInfo := TxInfo{SenderID: peerID} + txInfo := mempool.TxInfo{SenderID: peerID} for i := 0; i < count; i++ { txBytes := make([]byte, 20) txs[i] = txBytes @@ -81,11 +107,11 @@ func checkTxs(t *testing.T, mempool Mempool, count int, peerID uint16) types.Txs if err != nil { t.Error(err) } - if _, err := mempool.CheckTxSync(txBytes, txInfo); err != nil { + if err := mp.CheckTxSync(txBytes, nil, txInfo); err != nil { // Skip invalid txs. // TestMempoolFilters will fail otherwise. It asserts a number of txs // returned. - if IsPreCheckError(err) { + if mempool.IsPreCheckError(err) { continue } t.Fatalf("CheckTx failed: %v while checking #%d tx", err, i) @@ -97,19 +123,19 @@ func checkTxs(t *testing.T, mempool Mempool, count int, peerID uint16) types.Txs func TestReapMaxBytesMaxGas(t *testing.T) { app := kvstore.NewApplication() cc := proxy.NewLocalClientCreator(app) - mempool, cleanup := newMempoolWithApp(cc) + mp, cleanup := newMempoolWithApp(cc) defer cleanup() // Ensure gas calculation behaves as expected - checkTxs(t, mempool, 1, UnknownPeerID) - tx0 := mempool.TxsFront().Value.(*mempoolTx) + checkTxs(t, mp, 1, mempool.UnknownPeerID) + tx0 := mp.TxsFront().Value.(*mempoolTx) // assert that kv store has gas wanted = 1. require.Equal(t, app.CheckTxSync(abci.RequestCheckTx{Tx: tx0.tx}).GasWanted, int64(1), "KVStore had a gas value neq to 1") require.Equal(t, tx0.gasWanted, int64(1), "transactions gas was set incorrectly") // ensure each tx is 20 bytes long require.Equal(t, len(tx0.tx), 20, "Tx is longer than 20 bytes") - mempool.Flush() + mp.Flush() // each table driven test creates numTxsToCreate txs with checkTx, and at the end clears all remaining txs. // each tx has 20 bytes @@ -140,23 +166,23 @@ func TestReapMaxBytesMaxGas(t *testing.T) { {20, 20000, 30, 20, 100}, } for tcIndex, tt := range tests { - checkTxs(t, mempool, tt.numTxsToCreate, UnknownPeerID) + checkTxs(t, mp, tt.numTxsToCreate, mempool.UnknownPeerID) var got types.Txs if tt.maxTxs <= 0 { - got = mempool.ReapMaxBytesMaxGas(tt.maxBytes, tt.maxGas) + got = mp.ReapMaxBytesMaxGas(tt.maxBytes, tt.maxGas) } else { - got = mempool.ReapMaxBytesMaxGasMaxTxs(tt.maxBytes, tt.maxGas, tt.maxTxs) + got = mp.ReapMaxBytesMaxGasMaxTxs(tt.maxBytes, tt.maxGas, tt.maxTxs) } assert.Equal(t, tt.expectedNumTxs, len(got), "Got %d txs, expected %d, tc #%d", len(got), tt.expectedNumTxs, tcIndex) - mempool.Flush() + mp.Flush() } } func TestMempoolFilters(t *testing.T) { app := kvstore.NewApplication() cc := proxy.NewLocalClientCreator(app) - mempool, cleanup := newMempoolWithApp(cc) + mp, cleanup := newMempoolWithApp(cc) defer cleanup() emptyTxArr := []types.Tx{[]byte{}} @@ -166,70 +192,120 @@ func TestMempoolFilters(t *testing.T) { // each tx has 20 bytes tests := []struct { numTxsToCreate int - preFilter PreCheckFunc + preFilter mempool.PreCheckFunc expectedNumTxs int }{ {10, nopPreFilter, 10}, - {10, PreCheckMaxBytes(10), 0}, - {10, PreCheckMaxBytes(20), 0}, - {10, PreCheckMaxBytes(22), 10}, - {10, PreCheckMaxBytes(30), 10}, + {10, mempool.PreCheckMaxBytes(10), 0}, + {10, mempool.PreCheckMaxBytes(20), 0}, + {10, mempool.PreCheckMaxBytes(22), 10}, + {10, mempool.PreCheckMaxBytes(30), 10}, } for tcIndex, tt := range tests { - err := mempool.Update(newTestBlock(1, emptyTxArr), - abciResponses(len(emptyTxArr), ocabci.CodeTypeOK), tt.preFilter, nil) + err := mp.Update(newTestBlock(1, emptyTxArr), abciResponses(len(emptyTxArr), abci.CodeTypeOK), tt.preFilter, nil) require.NoError(t, err) - checkTxs(t, mempool, tt.numTxsToCreate, UnknownPeerID) - require.Equal(t, tt.expectedNumTxs, mempool.Size(), "mempool had the incorrect size, on test case %d", tcIndex) - mempool.Flush() + checkTxs(t, mp, tt.numTxsToCreate, mempool.UnknownPeerID) + require.Equal(t, tt.expectedNumTxs, mp.Size(), "mempool had the incorrect size, on test case %d", tcIndex) + mp.Flush() } } func TestMempoolUpdate(t *testing.T) { app := kvstore.NewApplication() cc := proxy.NewLocalClientCreator(app) - mempool, cleanup := newMempoolWithApp(cc) + mp, cleanup := newMempoolWithApp(cc) defer cleanup() // 1. Adds valid txs to the cache { - err := mempool.Update(newTestBlock(1, []types.Tx{[]byte{0x01}}), + err := mp.Update(newTestBlock(1, []types.Tx{[]byte{0x01}}), abciResponses(1, ocabci.CodeTypeOK), nil, nil) require.NoError(t, err) - _, err = mempool.CheckTxSync([]byte{0x01}, TxInfo{}) + err = mp.CheckTxSync([]byte{0x01}, nil, mempool.TxInfo{}) if assert.Error(t, err) { - assert.Equal(t, ErrTxInCache, err) + assert.Equal(t, mempool.ErrTxInCache, err) } } // 2. Removes valid txs from the mempool { - _, err := mempool.CheckTxSync([]byte{0x02}, TxInfo{}) + err := mp.CheckTxSync([]byte{0x02}, nil, mempool.TxInfo{}) require.NoError(t, err) - err = mempool.Update(newTestBlock(1, []types.Tx{[]byte{0x02}}), abciResponses(1, ocabci.CodeTypeOK), nil, nil) + err = mp.Update(newTestBlock(1, []types.Tx{[]byte{0x02}}), abciResponses(1, ocabci.CodeTypeOK), nil, nil) require.NoError(t, err) - assert.Zero(t, mempool.Size()) + assert.Zero(t, mp.Size()) } // 3. Removes invalid transactions from the cache and the mempool (if present) { - _, err := mempool.CheckTxSync([]byte{0x03}, TxInfo{}) + err := mp.CheckTxSync([]byte{0x03}, nil, mempool.TxInfo{}) require.NoError(t, err) - err = mempool.Update(newTestBlock(1, []types.Tx{[]byte{0x03}}), abciResponses(1, 1), nil, nil) + err = mp.Update(newTestBlock(1, []types.Tx{[]byte{0x03}}), abciResponses(1, 1), nil, nil) require.NoError(t, err) - assert.Zero(t, mempool.Size()) + assert.Zero(t, mp.Size()) - _, err = mempool.CheckTxSync([]byte{0x03}, TxInfo{}) + err = mp.CheckTxSync([]byte{0x03}, nil, mempool.TxInfo{}) require.NoError(t, err) } } +// FIXME: need to adjust Ostracon's abci +//func TestMempoolUpdateDoesNotPanicWhenApplicationMissedTx(t *testing.T) { +// var callback abciclient.Callback +// mockClient := new(abciclimocks.Client) +// mockClient.On("Start").Return(nil) +// mockClient.On("SetLogger", mock.Anything) +// +// mockClient.On("Error").Return(nil).Times(4) +// mockClient.On("FlushAsync", mock.Anything).Return(abciclient.NewReqRes(abci.ToRequestFlush()), nil) +// mockClient.On("SetResponseCallback", mock.MatchedBy(func(cb abciclient.Callback) bool { callback = cb; return true })) +// +// app := kvstore.NewApplication() +// cc := proxy.NewLocalClientCreator(app) +// mp, cleanup, err := newMempoolWithAppMock(cc, mockClient) +// require.NoError(t, err) +// defer cleanup() +// +// // Add 4 transactions to the mempool by calling the mempool's `CheckTx` on each of them. +// txs := []types.Tx{[]byte{0x01}, []byte{0x02}, []byte{0x03}, []byte{0x04}} +// for _, tx := range txs { +// reqRes := abciclient.NewReqRes(abci.ToRequestCheckTx(abci.RequestCheckTx{Tx: tx})) +// reqRes.Response = abci.ToResponseCheckTx(abci.ResponseCheckTx{Code: abci.CodeTypeOK}) +// +// mockClient.On("CheckTxAsync", mock.Anything, mock.Anything).Return(reqRes, nil) +// err := mp.CheckTxSync(tx, nil, mempool.TxInfo{}) +// require.NoError(t, err) +// +// // ensure that the callback that the mempool sets on the ReqRes is run. +// reqRes.InvokeCallback() +// } +// +// // Calling update to remove the first transaction from the mempool. +// // This call also triggers the mempool to recheck its remaining transactions. +// err = mp.Update(0, []types.Tx{txs[0]}, abciResponses(1, abci.CodeTypeOK), nil, nil) +// require.Nil(t, err) +// +// // The mempool has now sent its requests off to the client to be rechecked +// // and is waiting for the corresponding callbacks to be called. +// // We now call the mempool-supplied callback on the first and third transaction. +// // This simulates the client dropping the second request. +// // Previous versions of this code panicked when the ABCI application missed +// // a recheck-tx request. +// resp := abci.ResponseCheckTx{Code: abci.CodeTypeOK} +// req := abci.RequestCheckTx{Tx: txs[1]} +// callback(abci.ToRequestCheckTx(req), abci.ToResponseCheckTx(resp)) +// +// req = abci.RequestCheckTx{Tx: txs[3]} +// callback(abci.ToRequestCheckTx(req), abci.ToResponseCheckTx(resp)) +// mockClient.AssertExpectations(t) +//} + func TestMempool_KeepInvalidTxsInCache(t *testing.T) { - app := counter.NewApplication(true) + app := kvstore.NewApplication() cc := proxy.NewLocalClientCreator(app) - wcfg := cfg.DefaultConfig() + wcfg := config.DefaultConfig() wcfg.Mempool.KeepInvalidTxsInCache = true - mempool, cleanup := newMempoolWithAppAndConfig(cc, wcfg) + mp, cleanup := newMempoolWithAppAndConfig(cc, wcfg) defer cleanup() // 1. An invalid transaction must remain in the cache after Update @@ -240,43 +316,45 @@ func TestMempool_KeepInvalidTxsInCache(t *testing.T) { b := make([]byte, 8) binary.BigEndian.PutUint64(b, 1) - _, err := mempool.CheckTxSync(b, TxInfo{}) + err := mp.CheckTxSync(b, nil, mempool.TxInfo{}) require.NoError(t, err) // simulate new block _ = app.DeliverTx(abci.RequestDeliverTx{Tx: a}) _ = app.DeliverTx(abci.RequestDeliverTx{Tx: b}) - err = mempool.Update(newTestBlock(1, []types.Tx{a, b}), + err = mp.Update(newTestBlock(1, []types.Tx{a, b}), []*abci.ResponseDeliverTx{{Code: ocabci.CodeTypeOK}, {Code: 2}}, nil, nil) require.NoError(t, err) // a must be added to the cache - _, err = mempool.CheckTxSync(a, TxInfo{}) + err = mp.CheckTxSync(a, nil, mempool.TxInfo{}) if assert.Error(t, err) { - assert.Equal(t, ErrTxInCache, err) + assert.Equal(t, mempool.ErrTxInCache, err) } // b must remain in the cache - _, err = mempool.CheckTxSync(b, TxInfo{}) + err = mp.CheckTxSync(b, nil, mempool.TxInfo{}) if assert.Error(t, err) { - assert.Equal(t, ErrTxInCache, err) + assert.Equal(t, mempool.ErrTxInCache, err) } } - // 2. An invalid transaction must remain in the cache + // 2. An invalid transaction must remain in the Map since checking first in Map on prepareCheckTx { a := make([]byte, 8) binary.BigEndian.PutUint64(a, 0) // remove a from the cache to test (2) - mempool.cache.Remove(a) + mp.cache.Remove(a) - _, err := mempool.CheckTxSync(a, TxInfo{}) + err := mp.CheckTxSync(a, nil, mempool.TxInfo{}) require.NoError(t, err) - _, err = mempool.CheckTxSync(a, TxInfo{}) + err = mp.CheckTxSync(a, nil, mempool.TxInfo{}) if assert.Error(t, err) { - assert.Equal(t, ErrTxInCache, err) + // NOTE: After changing the application KVStore from Counter, + // KVStore doesn't return CodeTypeBadNonce like before Counter + assert.Equal(t, mempool.ErrTxInMap, err) } } } @@ -284,55 +362,54 @@ func TestMempool_KeepInvalidTxsInCache(t *testing.T) { func TestTxsAvailable(t *testing.T) { app := kvstore.NewApplication() cc := proxy.NewLocalClientCreator(app) - mempool, cleanup := newMempoolWithApp(cc) + mp, cleanup := newMempoolWithApp(cc) defer cleanup() - mempool.EnableTxsAvailable() + mp.EnableTxsAvailable() timeoutMS := 500 // with no txs, it shouldnt fire - ensureNoFire(t, mempool.TxsAvailable(), timeoutMS) + ensureNoFire(t, mp.TxsAvailable(), timeoutMS) // send a bunch of txs, it should only fire once - txs := checkTxs(t, mempool, 100, UnknownPeerID) - ensureFire(t, mempool.TxsAvailable(), timeoutMS) - ensureNoFire(t, mempool.TxsAvailable(), timeoutMS) + txs := checkTxs(t, mp, 100, mempool.UnknownPeerID) + ensureFire(t, mp.TxsAvailable(), timeoutMS) + ensureNoFire(t, mp.TxsAvailable(), timeoutMS) // call update with half the txs. // it should fire once now for the new height // since there are still txs left committedTxs, txs := txs[:50], txs[50:] - if err := mempool.Update(newTestBlock(1, committedTxs), + if err := mp.Update(newTestBlock(1, committedTxs), abciResponses(len(committedTxs), ocabci.CodeTypeOK), nil, nil); err != nil { t.Error(err) } - ensureFire(t, mempool.TxsAvailable(), timeoutMS) - ensureNoFire(t, mempool.TxsAvailable(), timeoutMS) + ensureFire(t, mp.TxsAvailable(), timeoutMS) + ensureNoFire(t, mp.TxsAvailable(), timeoutMS) // send a bunch more txs. we already fired for this height so it shouldnt fire again - moreTxs := checkTxs(t, mempool, 50, UnknownPeerID) - ensureNoFire(t, mempool.TxsAvailable(), timeoutMS) + moreTxs := checkTxs(t, mp, 50, mempool.UnknownPeerID) + ensureNoFire(t, mp.TxsAvailable(), timeoutMS) // now call update with all the txs. it should not fire as there are no txs left committedTxs = append(txs, moreTxs...) // nolint: gocritic - if err := mempool.Update(newTestBlock(2, committedTxs), + if err := mp.Update(newTestBlock(2, committedTxs), abciResponses(len(committedTxs), ocabci.CodeTypeOK), nil, nil); err != nil { t.Error(err) } - ensureNoFire(t, mempool.TxsAvailable(), timeoutMS) + ensureNoFire(t, mp.TxsAvailable(), timeoutMS) // send a bunch more txs, it should only fire once - checkTxs(t, mempool, 100, UnknownPeerID) - ensureFire(t, mempool.TxsAvailable(), timeoutMS) - ensureNoFire(t, mempool.TxsAvailable(), timeoutMS) + checkTxs(t, mp, 100, mempool.UnknownPeerID) + ensureFire(t, mp.TxsAvailable(), timeoutMS) + ensureNoFire(t, mp.TxsAvailable(), timeoutMS) } func TestSerialReap(t *testing.T) { - app := counter.NewApplication(true) - app.SetOption(abci.RequestSetOption{Key: "serial", Value: "on"}) + app := kvstore.NewApplication() cc := proxy.NewLocalClientCreator(app) - mempool, cleanup := newMempoolWithApp(cc) + mp, cleanup := newMempoolWithApp(cc) defer cleanup() appConnCon, _ := cc.NewABCIClient() @@ -348,7 +425,7 @@ func TestSerialReap(t *testing.T) { // This will succeed txBytes := make([]byte, 8) binary.BigEndian.PutUint64(txBytes, uint64(i)) - _, err := mempool.CheckTxSync(txBytes, TxInfo{}) + err := mp.CheckTxSync(txBytes, nil, mempool.TxInfo{}) _, cached := cacheMap[string(txBytes)] if cached { require.NotNil(t, err, "expected error for cached tx") @@ -358,13 +435,13 @@ func TestSerialReap(t *testing.T) { cacheMap[string(txBytes)] = struct{}{} // Duplicates are cached and should return error - _, err = mempool.CheckTxSync(txBytes, TxInfo{}) + err = mp.CheckTxSync(txBytes, nil, mempool.TxInfo{}) require.NotNil(t, err, "Expected error after CheckTx on duplicated tx") } } reapCheck := func(exp int) { - txs := mempool.ReapMaxBytesMaxGas(-1, -1) + txs := mp.ReapMaxBytesMaxGas(-1, -1) require.Equal(t, len(txs), exp, fmt.Sprintf("Expected to reap %v txs but got %v", exp, len(txs))) } @@ -375,7 +452,7 @@ func TestSerialReap(t *testing.T) { binary.BigEndian.PutUint64(txBytes, uint64(i)) txs = append(txs, txBytes) } - if err := mempool.Update(newTestBlock(0, txs), + if err := mp.Update(newTestBlock(0, txs), abciResponses(len(txs), ocabci.CodeTypeOK), nil, nil); err != nil { t.Error(err) } @@ -439,58 +516,10 @@ func TestSerialReap(t *testing.T) { reapCheck(600) } -func TestMempoolCloseWAL(t *testing.T) { - // 1. Create the temporary directory for mempool and WAL testing. - rootDir, err := ioutil.TempDir("", "mempool-test") - require.Nil(t, err, "expecting successful tmpdir creation") - - // 2. Ensure that it doesn't contain any elements -- Sanity check - m1, err := filepath.Glob(filepath.Join(rootDir, "*")) - require.Nil(t, err, "successful globbing expected") - require.Equal(t, 0, len(m1), "no matches yet") - - // 3. Create the mempool - wcfg := cfg.DefaultConfig() - wcfg.Mempool.RootDir = rootDir - app := kvstore.NewApplication() - cc := proxy.NewLocalClientCreator(app) - mempool, cleanup := newMempoolWithAppAndConfig(cc, wcfg) - defer cleanup() - mempool.height = 10 - err = mempool.InitWAL() - require.NoError(t, err) - - // 4. Ensure that the directory contains the WAL file - m2, err := filepath.Glob(filepath.Join(rootDir, "*")) - require.Nil(t, err, "successful globbing expected") - require.Equal(t, 1, len(m2), "expecting the wal match in") - - // 5. Write some contents to the WAL - _, err = mempool.CheckTxSync(types.Tx([]byte("foo")), TxInfo{}) - require.NoError(t, err) - walFilepath := mempool.wal.Path - sum1 := checksumFile(walFilepath, t) - - // 6. Sanity check to ensure that the written TX matches the expectation. - require.Equal(t, sum1, checksumIt([]byte("foo\n")), "foo with a newline should be written") - - // 7. Invoke CloseWAL() and ensure it discards the - // WAL thus any other write won't go through. - mempool.CloseWAL() - _, err = mempool.CheckTxSync(types.Tx([]byte("bar")), TxInfo{}) - require.NoError(t, err) - sum2 := checksumFile(walFilepath, t) - require.Equal(t, sum1, sum2, "expected no change to the WAL after invoking CloseWAL() since it was discarded") - - // 8. Sanity check to ensure that the WAL file still exists - m3, err := filepath.Glob(filepath.Join(rootDir, "*")) - require.Nil(t, err, "successful globbing expected") - require.Equal(t, 1, len(m3), "expecting the wal match in") -} - func TestMempool_CheckTxChecksTxSize(t *testing.T) { app := kvstore.NewApplication() cc := proxy.NewLocalClientCreator(app) + mempl, cleanup := newMempoolWithApp(cc) defer cleanup() @@ -516,7 +545,7 @@ func TestMempool_CheckTxChecksTxSize(t *testing.T) { tx := tmrand.Bytes(testCase.len) - _, err := mempl.CheckTxSync(tx, TxInfo{}) + err := mempl.CheckTxSync(tx, nil, mempool.TxInfo{}) bv := gogotypes.BytesValue{Value: tx} bz, err2 := bv.Marshal() require.NoError(t, err2) @@ -525,7 +554,10 @@ func TestMempool_CheckTxChecksTxSize(t *testing.T) { if !testCase.err { require.NoError(t, err, caseString) } else { - require.Equal(t, err, ErrTxTooLarge{maxTxSize, testCase.len}, caseString) + require.Equal(t, err, mempool.ErrTxTooLarge{ + Max: maxTxSize, + Actual: testCase.len, + }, caseString) } } } @@ -533,53 +565,60 @@ func TestMempool_CheckTxChecksTxSize(t *testing.T) { func TestMempoolTxsBytes(t *testing.T) { app := kvstore.NewApplication() cc := proxy.NewLocalClientCreator(app) - config := cfg.ResetTestRoot("mempool_test") - config.Mempool.MaxTxsBytes = 10 - mempool, cleanup := newMempoolWithAppAndConfig(cc, config) + + cfg := config.ResetTestRoot("mempool_test") + + cfg.Mempool.MaxTxsBytes = 10 + mp, cleanup := newMempoolWithAppAndConfig(cc, cfg) defer cleanup() // 1. zero by default - assert.EqualValues(t, 0, mempool.TxsBytes()) + assert.EqualValues(t, 0, mp.SizeBytes()) // 2. len(tx) after CheckTx - _, err := mempool.CheckTxSync([]byte{0x01}, TxInfo{}) + err := mp.CheckTxSync([]byte{0x01}, nil, mempool.TxInfo{}) require.NoError(t, err) - assert.EqualValues(t, 1, mempool.TxsBytes()) + assert.EqualValues(t, 1, mp.SizeBytes()) // 3. zero again after tx is removed by Update - err = mempool.Update(newTestBlock(1, []types.Tx{[]byte{0x01}}), + err = mp.Update(newTestBlock(1, []types.Tx{[]byte{0x01}}), abciResponses(1, ocabci.CodeTypeOK), nil, nil) require.NoError(t, err) - assert.EqualValues(t, 0, mempool.TxsBytes()) + assert.EqualValues(t, 0, mp.SizeBytes()) // 4. zero after Flush - _, err = mempool.CheckTxSync([]byte{0x02, 0x03}, TxInfo{}) + err = mp.CheckTxSync([]byte{0x02, 0x03}, nil, mempool.TxInfo{}) require.NoError(t, err) - assert.EqualValues(t, 2, mempool.TxsBytes()) + assert.EqualValues(t, 2, mp.SizeBytes()) - mempool.Flush() - assert.EqualValues(t, 0, mempool.TxsBytes()) + mp.Flush() + assert.EqualValues(t, 0, mp.SizeBytes()) // 5. ErrMempoolIsFull is returned when/if MaxTxsBytes limit is reached. - _, err = mempool.CheckTxSync([]byte{0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04}, TxInfo{}) + err = mp.CheckTxSync( + []byte{0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04}, + nil, + mempool.TxInfo{}, + ) require.NoError(t, err) - _, err = mempool.CheckTxSync([]byte{0x05}, TxInfo{}) + err = mp.CheckTxSync([]byte{0x05}, nil, mempool.TxInfo{}) if assert.Error(t, err) { - assert.IsType(t, ErrMempoolIsFull{}, err) + assert.IsType(t, mempool.ErrMempoolIsFull{}, err) } // 6. zero after tx is rechecked and removed due to not being valid anymore - app2 := counter.NewApplication(true) + app2 := kvstore.NewApplication() cc = proxy.NewLocalClientCreator(app2) - mempool, cleanup = newMempoolWithApp(cc) + + mp, cleanup = newMempoolWithApp(cc) defer cleanup() txBytes := make([]byte, 8) binary.BigEndian.PutUint64(txBytes, uint64(0)) - _, err = mempool.CheckTxSync(txBytes, TxInfo{}) + err = mp.CheckTxSync(txBytes, nil, mempool.TxInfo{}) require.NoError(t, err) - assert.EqualValues(t, 8, mempool.TxsBytes()) + assert.EqualValues(t, 8, mp.SizeBytes()) appConnCon, _ := cc.NewABCIClient() appConnCon.SetLogger(log.TestingLogger().With("module", "abci-client", "connection", "consensus")) @@ -590,26 +629,28 @@ func TestMempoolTxsBytes(t *testing.T) { t.Error(err) } }) + res, err := appConnCon.DeliverTxSync(abci.RequestDeliverTx{Tx: txBytes}) require.NoError(t, err) require.EqualValues(t, 0, res.Code) + res2, err := appConnCon.CommitSync() require.NoError(t, err) require.NotEmpty(t, res2.Data) // Pretend like we committed nothing so txBytes gets rechecked and removed. - err = mempool.Update(newTestBlock(1, []types.Tx{}), abciResponses(0, ocabci.CodeTypeOK), nil, nil) + err = mp.Update(newTestBlock(1, []types.Tx{}), abciResponses(0, ocabci.CodeTypeOK), nil, nil) require.NoError(t, err) - assert.EqualValues(t, 0, mempool.TxsBytes()) + assert.EqualValues(t, 8, mp.SizeBytes()) // 7. Test RemoveTxByKey function - _, err = mempool.CheckTxSync([]byte{0x06}, TxInfo{}) + err = mp.CheckTxSync([]byte{0x06}, nil, mempool.TxInfo{}) require.NoError(t, err) - assert.EqualValues(t, 1, mempool.TxsBytes()) - mempool.RemoveTxByKey(TxKey([]byte{0x07}), true) - assert.EqualValues(t, 1, mempool.TxsBytes()) - mempool.RemoveTxByKey(TxKey([]byte{0x06}), true) - assert.EqualValues(t, 0, mempool.TxsBytes()) + assert.EqualValues(t, 9, mp.SizeBytes()) + assert.Error(t, mp.RemoveTxByKey(types.Tx([]byte{0x07}).Key())) + assert.EqualValues(t, 9, mp.SizeBytes()) + assert.NoError(t, mp.RemoveTxByKey(types.Tx([]byte{0x06}).Key())) + assert.EqualValues(t, 8, mp.SizeBytes()) } @@ -620,14 +661,16 @@ func TestMempoolTxsBytes(t *testing.T) { func TestMempoolRemoteAppConcurrency(t *testing.T) { sockPath := fmt.Sprintf("unix:///tmp/echo_%v.sock", tmrand.Str(6)) app := kvstore.NewApplication() - cc, server := newRemoteApp(t, sockPath, app) + _, server := newRemoteApp(t, sockPath, app) t.Cleanup(func() { if err := server.Stop(); err != nil { t.Error(err) } }) - config := cfg.ResetTestRoot("mempool_test") - mempool, cleanup := newMempoolWithAppAndConfig(cc, config) + + cfg := config.ResetTestRoot("mempool_test") + + mp, cleanup := newMempoolWithAppAndConfig(proxy.NewRemoteClientCreator(sockPath, "socket", true), cfg) defer cleanup() // generate small number of txs @@ -639,7 +682,7 @@ func TestMempoolRemoteAppConcurrency(t *testing.T) { } // simulate a group of peers sending them over and over - N := config.Mempool.Size + N := cfg.Mempool.Size maxPeers := 5 for i := 0; i < N; i++ { peerID := mrand.Intn(maxPeers) @@ -647,10 +690,10 @@ func TestMempoolRemoteAppConcurrency(t *testing.T) { tx := txs[txNum] // this will err with ErrTxInCache many times ... - mempool.CheckTxSync(tx, TxInfo{SenderID: uint16(peerID)}) // nolint: errcheck + mp.CheckTxSync(tx, nil, mempool.TxInfo{SenderID: uint16(peerID)}) // nolint: errcheck } - err := mempool.FlushAppConn() - require.NoError(t, err) + + require.NoError(t, mp.FlushAppConn()) } func newTestBlock(height int64, txs types.Txs) *types.Block { @@ -665,35 +708,18 @@ func newTestBlock(height int64, txs types.Txs) *types.Block { } // caller must close server -func newRemoteApp( - t *testing.T, - addr string, - app ocabci.Application, -) ( - clientCreator proxy.ClientCreator, - server service.Service, -) { - clientCreator = proxy.NewRemoteClientCreator(addr, "socket", true) +func newRemoteApp(t *testing.T, addr string, app ocabci.Application) (abciclient.Client, service.Service) { + clientCreator, err := abciclient.NewClient(addr, "socket", true) + require.NoError(t, err) // Start server - server = abciserver.NewSocketServer(addr, app) + server := abciserver.NewSocketServer(addr, app) server.SetLogger(log.TestingLogger().With("module", "abci-server")) if err := server.Start(); err != nil { t.Fatalf("Error starting socket server: %v", err.Error()) } - return clientCreator, server -} - -func checksumIt(data []byte) string { - h := sha256.New() - h.Write(data) - return fmt.Sprintf("%x", h.Sum(nil)) -} -func checksumFile(p string, t *testing.T) string { - data, err := ioutil.ReadFile(p) - require.Nil(t, err, "expecting successful read of %q", p) - return checksumIt(data) + return clientCreator, server } func abciResponses(n int, code uint32) []*abci.ResponseDeliverTx { @@ -723,15 +749,15 @@ func TestTxMempoolPostCheckError(t *testing.T) { t.Run(testCase.name, func(t *testing.T) { app := kvstore.NewApplication() cc := proxy.NewLocalClientCreator(app) - mempool, cleanup := newMempoolWithApp(cc) + mp, cleanup := newMempoolWithApp(cc) defer cleanup() - mempool.postCheck = func(_ types.Tx, _ *ocabci.ResponseCheckTx) error { + mp.postCheck = func(_ types.Tx, _ *ocabci.ResponseCheckTx) error { return testCase.err } tx := types.Tx{1} - _, err := mempool.CheckTxSync(tx, TxInfo{}) + err := mp.CheckTxSync(tx, nil, mempool.TxInfo{}) require.NoError(t, err) req := abci.RequestCheckTx{ @@ -742,7 +768,7 @@ func TestTxMempoolPostCheckError(t *testing.T) { m := sync.Mutex{} m.Lock() - mempool.proxyAppConn.CheckTxAsync(req, func(r *ocabci.Response) { + mp.proxyAppConn.CheckTxAsync(req, func(r *ocabci.Response) { res = r m.Unlock() }) diff --git a/mempool/doc.go b/mempool/v0/doc.go similarity index 98% rename from mempool/doc.go rename to mempool/v0/doc.go index 7e6363e12..3b5d0d20d 100644 --- a/mempool/doc.go +++ b/mempool/v0/doc.go @@ -20,4 +20,4 @@ // broadcastTxRoutine(). // TODO: Better handle abci client errors. (make it automatically handle connection errors) -package mempool +package v0 diff --git a/mempool/reactor.go b/mempool/v0/reactor.go similarity index 88% rename from mempool/reactor.go rename to mempool/v0/reactor.go index 350cfc99a..d90f34122 100644 --- a/mempool/reactor.go +++ b/mempool/v0/reactor.go @@ -1,9 +1,8 @@ -package mempool +package v0 import ( "errors" "fmt" - "math" "time" protomem "github.com/tendermint/tendermint/proto/tendermint/mempool" @@ -12,22 +11,11 @@ import ( "github.com/Finschia/ostracon/libs/clist" "github.com/Finschia/ostracon/libs/log" tmsync "github.com/Finschia/ostracon/libs/sync" + "github.com/Finschia/ostracon/mempool" "github.com/Finschia/ostracon/p2p" "github.com/Finschia/ostracon/types" ) -const ( - MempoolChannel = byte(0x30) - - peerCatchupSleepIntervalMS = 100 // If peer is behind, sleep this amount - - // UnknownPeerID is the peer ID to use when running CheckTx when there is - // no peer (e.g. RPC) - UnknownPeerID uint16 = 0 - - maxActiveIDs = math.MaxUint16 -) - // Reactor handles mempool tx broadcasting amongst peers. // It maintains a map from peer ID to counter, to prevent gossiping txs to the // peers you received it from. @@ -59,8 +47,8 @@ func (ids *mempoolIDs) ReserveForPeer(peer p2p.Peer) { // nextPeerID returns the next unused peer ID to use. // This assumes that ids's mutex is already locked. func (ids *mempoolIDs) nextPeerID() uint16 { - if len(ids.activeIDs) == maxActiveIDs { - panic(fmt.Sprintf("node has maximum %d active IDs and wanted to get one more", maxActiveIDs)) + if len(ids.activeIDs) == mempool.MaxActiveIDs { + panic(fmt.Sprintf("node has maximum %d active IDs and wanted to get one more", mempool.MaxActiveIDs)) } _, idExists := ids.activeIDs[ids.nextID] @@ -150,7 +138,7 @@ func (memR *Reactor) GetChannels() []*p2p.ChannelDescriptor { return []*p2p.ChannelDescriptor{ { - ID: MempoolChannel, + ID: mempool.MempoolChannel, Priority: 5, RecvMessageCapacity: batchMsg.Size(), }, @@ -182,20 +170,22 @@ func (memR *Reactor) Receive(chID byte, src p2p.Peer, msgBytes []byte) { } memR.Logger.Debug("Receive", "src", src, "chId", chID, "msg", msg) - txInfo := TxInfo{SenderID: memR.ids.GetForPeer(src)} + txInfo := mempool.TxInfo{SenderID: memR.ids.GetForPeer(src)} if src != nil { txInfo.SenderP2PID = src.ID() } + for _, tx := range msg.Txs { tx := tx // pin! workaround for `scopelint` error memR.mempool.CheckTxAsync(tx, txInfo, func(err error) { - if err == ErrTxInCache { - memR.Logger.Debug("Tx already exists in cache", "tx", txID(tx)) + if errors.Is(err, mempool.ErrTxInCache) { + memR.Logger.Debug("Tx already exists in cache", "tx", tx.String()) } else if err != nil { - memR.Logger.Info("Could not check tx", "tx", txID(tx), "err", err) + memR.Logger.Info("Could not check tx", "tx", tx.String(), "err", err) } }, nil) } + // broadcasting happens from go routines per peer } @@ -238,14 +228,14 @@ func (memR *Reactor) broadcastTxRoutine(peer p2p.Peer) { // different every time due to us using a map. Sometimes other reactors // will be initialized before the consensus reactor. We should wait a few // milliseconds and retry. - time.Sleep(peerCatchupSleepIntervalMS * time.Millisecond) + time.Sleep(mempool.PeerCatchupSleepIntervalMS * time.Millisecond) continue } // Allow for a lag of 1 block. memTx := next.Value.(*mempoolTx) if peerState.GetHeight() < memTx.Height()-1 { - time.Sleep(peerCatchupSleepIntervalMS * time.Millisecond) + time.Sleep(mempool.PeerCatchupSleepIntervalMS * time.Millisecond) continue } @@ -258,13 +248,15 @@ func (memR *Reactor) broadcastTxRoutine(peer p2p.Peer) { Txs: &protomem.Txs{Txs: [][]byte{memTx.tx}}, }, } + bz, err := msg.Marshal() if err != nil { panic(err) } - success := peer.Send(MempoolChannel, bz) + + success := peer.Send(mempool.MempoolChannel, bz) if !success { - time.Sleep(peerCatchupSleepIntervalMS * time.Millisecond) + time.Sleep(mempool.PeerCatchupSleepIntervalMS * time.Millisecond) continue } } @@ -281,9 +273,6 @@ func (memR *Reactor) broadcastTxRoutine(peer p2p.Peer) { } } -//----------------------------------------------------------------------------- -// Messages - func (memR *Reactor) decodeMsg(bz []byte) (TxsMessage, error) { msg := protomem.Message{} err := msg.Unmarshal(bz) @@ -313,8 +302,6 @@ func (memR *Reactor) decodeMsg(bz []byte) (TxsMessage, error) { return message, fmt.Errorf("msg type: %T is not supported", msg) } -//------------------------------------- - // TxsMessage is a Message containing transactions. type TxsMessage struct { Txs []types.Tx diff --git a/mempool/reactor_test.go b/mempool/v0/reactor_test.go similarity index 93% rename from mempool/reactor_test.go rename to mempool/v0/reactor_test.go index 63d2ab438..a5f2f4989 100644 --- a/mempool/reactor_test.go +++ b/mempool/v0/reactor_test.go @@ -1,4 +1,4 @@ -package mempool +package v0 import ( "encoding/hex" @@ -20,6 +20,7 @@ import ( cfg "github.com/Finschia/ostracon/config" "github.com/Finschia/ostracon/libs/log" tmrand "github.com/Finschia/ostracon/libs/rand" + "github.com/Finschia/ostracon/mempool" "github.com/Finschia/ostracon/p2p" "github.com/Finschia/ostracon/p2p/mock" "github.com/Finschia/ostracon/proxy" @@ -67,7 +68,7 @@ func TestReactorBroadcastTxsMessage(t *testing.T) { } } - txs := checkTxs(t, reactors[0].mempool, numTxs, UnknownPeerID) + txs := checkTxs(t, reactors[0].mempool, numTxs, mempool.UnknownPeerID) waitForTxsOnReactors(t, txs, reactors) } @@ -97,7 +98,7 @@ func TestReactorConcurrency(t *testing.T) { // 1. submit a bunch of txs // 2. update the whole mempool - txs := checkTxs(t, reactors[0].mempool, numTxs, UnknownPeerID) + txs := checkTxs(t, reactors[0].mempool, numTxs, mempool.UnknownPeerID) go func() { defer wg.Done() @@ -114,7 +115,7 @@ func TestReactorConcurrency(t *testing.T) { // 1. submit a bunch of txs // 2. update none - _ = checkTxs(t, reactors[1].mempool, numTxs, UnknownPeerID) + _ = checkTxs(t, reactors[1].mempool, numTxs, mempool.UnknownPeerID) go func() { defer wg.Done() @@ -177,7 +178,7 @@ func TestReactor_MaxTxBytes(t *testing.T) { // Broadcast a tx, which has the max size // => ensure it's received by the second reactor. tx1 := tmrand.Bytes(config.Mempool.MaxTxBytes) - _, err := reactors[0].mempool.CheckTxSync(tx1, TxInfo{SenderID: UnknownPeerID}) + err := reactors[0].mempool.CheckTxSync(tx1, nil, mempool.TxInfo{SenderID: mempool.UnknownPeerID}) require.NoError(t, err) waitForTxsOnReactors(t, []types.Tx{tx1}, reactors) @@ -187,7 +188,7 @@ func TestReactor_MaxTxBytes(t *testing.T) { // Broadcast a tx, which is beyond the max size // => ensure it's not sent tx2 := tmrand.Bytes(config.Mempool.MaxTxBytes + 1) - _, err = reactors[0].mempool.CheckTxSync(tx2, TxInfo{SenderID: UnknownPeerID}) + err = reactors[0].mempool.CheckTxSync(tx2, nil, mempool.TxInfo{SenderID: mempool.UnknownPeerID}) require.Error(t, err) } @@ -259,7 +260,7 @@ func TestMempoolIDsPanicsIfNodeRequestsOvermaxActiveIDs(t *testing.T) { // 0 is already reserved for UnknownPeerID ids := newMempoolIDs() - for i := 0; i < maxActiveIDs-1; i++ { + for i := 0; i < mempool.MaxActiveIDs-1; i++ { peer := mock.NewPeer(net.IP{127, 0, 0, 1}) ids.ReserveForPeer(peer) } @@ -283,9 +284,9 @@ func TestDontExhaustMaxActiveIDs(t *testing.T) { }() reactor := reactors[0] - for i := 0; i < maxActiveIDs+1; i++ { + for i := 0; i < mempool.MaxActiveIDs+1; i++ { peer := mock.NewPeer(nil) - reactor.Receive(MempoolChannel, peer, []byte{0x1, 0x2, 0x3}) + reactor.Receive(mempool.MempoolChannel, peer, []byte{0x1, 0x2, 0x3}) reactor.AddPeer(peer) } } diff --git a/mempool/v1/mempool.go b/mempool/v1/mempool.go new file mode 100644 index 000000000..96925e219 --- /dev/null +++ b/mempool/v1/mempool.go @@ -0,0 +1,803 @@ +//go:build deprecated + +package v1 + +import ( + "fmt" + "reflect" + "sort" + "sync" + "sync/atomic" + "time" + + abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/config" + "github.com/tendermint/tendermint/libs/clist" + "github.com/tendermint/tendermint/libs/log" + "github.com/tendermint/tendermint/mempool" + "github.com/tendermint/tendermint/proxy" + "github.com/tendermint/tendermint/types" +) + +var _ mempool.Mempool = (*TxMempool)(nil) + +// TxMempoolOption sets an optional parameter on the TxMempool. +type TxMempoolOption func(*TxMempool) + +// TxMempool implemements the Mempool interface and allows the application to +// set priority values on transactions in the CheckTx response. When selecting +// transactions to include in a block, higher-priority transactions are chosen +// first. When evicting transactions from the mempool for size constraints, +// lower-priority transactions are evicted sooner. +// +// Within the mempool, transactions are ordered by time of arrival, and are +// gossiped to the rest of the network based on that order (gossip order does +// not take priority into account). +type TxMempool struct { + // Immutable fields + logger log.Logger + config *config.MempoolConfig + proxyAppConn proxy.AppConnMempool + metrics *mempool.Metrics + cache mempool.TxCache // seen transactions + + // Atomically-updated fields + txsBytes int64 // atomic: the total size of all transactions in the mempool, in bytes + txRecheck int64 // atomic: the number of pending recheck calls + + // Synchronized fields, protected by mtx. + mtx *sync.RWMutex + notifiedTxsAvailable bool + txsAvailable chan struct{} // one value sent per height when mempool is not empty + preCheck mempool.PreCheckFunc + postCheck mempool.PostCheckFunc + height int64 // the latest height passed to Update + + txs *clist.CList // valid transactions (passed CheckTx) + txByKey map[types.TxKey]*clist.CElement + txBySender map[string]*clist.CElement // for sender != "" +} + +// NewTxMempool constructs a new, empty priority mempool at the specified +// initial height and using the given config and options. +func NewTxMempool( + logger log.Logger, + cfg *config.MempoolConfig, + proxyAppConn proxy.AppConnMempool, + height int64, + options ...TxMempoolOption, +) *TxMempool { + + txmp := &TxMempool{ + logger: logger, + config: cfg, + proxyAppConn: proxyAppConn, + metrics: mempool.NopMetrics(), + cache: mempool.NopTxCache{}, + txs: clist.New(), + mtx: new(sync.RWMutex), + height: height, + txByKey: make(map[types.TxKey]*clist.CElement), + txBySender: make(map[string]*clist.CElement), + } + if cfg.CacheSize > 0 { + txmp.cache = mempool.NewLRUTxCache(cfg.CacheSize) + } + + proxyAppConn.SetResponseCallback(txmp.recheckTxCallback) + + for _, opt := range options { + opt(txmp) + } + + return txmp +} + +// WithPreCheck sets a filter for the mempool to reject a transaction if f(tx) +// returns an error. This is executed before CheckTx. It only applies to the +// first created block. After that, Update() overwrites the existing value. +func WithPreCheck(f mempool.PreCheckFunc) TxMempoolOption { + return func(txmp *TxMempool) { txmp.preCheck = f } +} + +// WithPostCheck sets a filter for the mempool to reject a transaction if +// f(tx, resp) returns an error. This is executed after CheckTx. It only applies +// to the first created block. After that, Update overwrites the existing value. +func WithPostCheck(f mempool.PostCheckFunc) TxMempoolOption { + return func(txmp *TxMempool) { txmp.postCheck = f } +} + +// WithMetrics sets the mempool's metrics collector. +func WithMetrics(metrics *mempool.Metrics) TxMempoolOption { + return func(txmp *TxMempool) { txmp.metrics = metrics } +} + +// Lock obtains a write-lock on the mempool. A caller must be sure to explicitly +// release the lock when finished. +func (txmp *TxMempool) Lock() { txmp.mtx.Lock() } + +// Unlock releases a write-lock on the mempool. +func (txmp *TxMempool) Unlock() { txmp.mtx.Unlock() } + +// Size returns the number of valid transactions in the mempool. It is +// thread-safe. +func (txmp *TxMempool) Size() int { return txmp.txs.Len() } + +// SizeBytes return the total sum in bytes of all the valid transactions in the +// mempool. It is thread-safe. +func (txmp *TxMempool) SizeBytes() int64 { return atomic.LoadInt64(&txmp.txsBytes) } + +// FlushAppConn executes FlushSync on the mempool's proxyAppConn. +// +// The caller must hold an exclusive mempool lock (by calling txmp.Lock) before +// calling FlushAppConn. +func (txmp *TxMempool) FlushAppConn() error { + // N.B.: We have to issue the call outside the lock so that its callback can + // fire. It's safe to do this, the flush will block until complete. + // + // We could just not require the caller to hold the lock at all, but the + // semantics of the Mempool interface require the caller to hold it, and we + // can't change that without disrupting existing use. + txmp.mtx.Unlock() + defer txmp.mtx.Lock() + + return txmp.proxyAppConn.FlushSync() +} + +// EnableTxsAvailable enables the mempool to trigger events when transactions +// are available on a block by block basis. +func (txmp *TxMempool) EnableTxsAvailable() { + txmp.mtx.Lock() + defer txmp.mtx.Unlock() + + txmp.txsAvailable = make(chan struct{}, 1) +} + +// TxsAvailable returns a channel which fires once for every height, and only +// when transactions are available in the mempool. It is thread-safe. +func (txmp *TxMempool) TxsAvailable() <-chan struct{} { return txmp.txsAvailable } + +// CheckTx adds the given transaction to the mempool if it fits and passes the +// application's ABCI CheckTx method. +// +// CheckTx reports an error without adding tx if: +// +// - The size of tx exceeds the configured maximum transaction size. +// - The pre-check hook is defined and reports an error for tx. +// - The transaction already exists in the cache. +// - The proxy connection to the application fails. +// +// If tx passes all of the above conditions, it is passed (asynchronously) to +// the application's ABCI CheckTx method and this CheckTx method returns nil. +// If cb != nil, it is called when the ABCI request completes to report the +// application response. +// +// If the application accepts the transaction and the mempool is full, the +// mempool evicts one or more of the lowest-priority transaction whose priority +// is (strictly) lower than the priority of tx and whose size together exceeds +// the size of tx, and adds tx instead. If no such transactions exist, tx is +// discarded. +func (txmp *TxMempool) CheckTx(tx types.Tx, cb func(*abci.Response), txInfo mempool.TxInfo) error { + + // During the initial phase of CheckTx, we do not need to modify any state. + // A transaction will not actually be added to the mempool until it survives + // a call to the ABCI CheckTx method and size constraint checks. + height, err := func() (int64, error) { + txmp.mtx.RLock() + defer txmp.mtx.RUnlock() + + // Reject transactions in excess of the configured maximum transaction size. + if len(tx) > txmp.config.MaxTxBytes { + return 0, mempool.ErrTxTooLarge{Max: txmp.config.MaxTxBytes, Actual: len(tx)} + } + + // If a precheck hook is defined, call it before invoking the application. + if txmp.preCheck != nil { + if err := txmp.preCheck(tx); err != nil { + return 0, mempool.ErrPreCheck{Reason: err} + } + } + + // Early exit if the proxy connection has an error. + if err := txmp.proxyAppConn.Error(); err != nil { + return 0, err + } + + txKey := tx.Key() + + // Check for the transaction in the cache. + if !txmp.cache.Push(tx) { + // If the cached transaction is also in the pool, record its sender. + if elt, ok := txmp.txByKey[txKey]; ok { + w := elt.Value.(*WrappedTx) + w.SetPeer(txInfo.SenderID) + } + return 0, mempool.ErrTxInCache + } + return txmp.height, nil + }() + if err != nil { + return err + } + + // Initiate an ABCI CheckTx for this transaction. The callback is + // responsible for adding the transaction to the pool if it survives. + // + // N.B.: We have to issue the call outside the lock. In a local client, + // even an "async" call invokes its callback immediately which will make + // the callback deadlock trying to acquire the same lock. This isn't a + // problem with out-of-process calls, but this has to work for both. + reqRes := txmp.proxyAppConn.CheckTxAsync(abci.RequestCheckTx{Tx: tx}) + if err := txmp.proxyAppConn.FlushSync(); err != nil { + return err + } + reqRes.SetCallback(func(res *abci.Response) { + wtx := &WrappedTx{ + tx: tx, + hash: tx.Key(), + timestamp: time.Now().UTC(), + height: height, + } + wtx.SetPeer(txInfo.SenderID) + txmp.initialTxCallback(wtx, res) + if cb != nil { + cb(res) + } + }) + return nil +} + +// RemoveTxByKey removes the transaction with the specified key from the +// mempool. It reports an error if no such transaction exists. This operation +// does not remove the transaction from the cache. +func (txmp *TxMempool) RemoveTxByKey(txKey types.TxKey) error { + txmp.mtx.Lock() + defer txmp.mtx.Unlock() + return txmp.removeTxByKey(txKey) +} + +// removeTxByKey removes the specified transaction key from the mempool. +// The caller must hold txmp.mtx excluxively. +func (txmp *TxMempool) removeTxByKey(key types.TxKey) error { + if elt, ok := txmp.txByKey[key]; ok { + w := elt.Value.(*WrappedTx) + delete(txmp.txByKey, key) + delete(txmp.txBySender, w.sender) + txmp.txs.Remove(elt) + elt.DetachPrev() + elt.DetachNext() + atomic.AddInt64(&txmp.txsBytes, -w.Size()) + return nil + } + return fmt.Errorf("transaction %x not found", key) +} + +// removeTxByElement removes the specified transaction element from the mempool. +// The caller must hold txmp.mtx exclusively. +func (txmp *TxMempool) removeTxByElement(elt *clist.CElement) { + w := elt.Value.(*WrappedTx) + delete(txmp.txByKey, w.tx.Key()) + delete(txmp.txBySender, w.sender) + txmp.txs.Remove(elt) + elt.DetachPrev() + elt.DetachNext() + atomic.AddInt64(&txmp.txsBytes, -w.Size()) +} + +// Flush purges the contents of the mempool and the cache, leaving both empty. +// The current height is not modified by this operation. +func (txmp *TxMempool) Flush() { + txmp.mtx.Lock() + defer txmp.mtx.Unlock() + + // Remove all the transactions in the list explicitly, so that the sizes + // and indexes get updated properly. + cur := txmp.txs.Front() + for cur != nil { + next := cur.Next() + txmp.removeTxByElement(cur) + cur = next + } + txmp.cache.Reset() + + // Discard any pending recheck calls that may be in flight. The calls will + // still complete, but will have no effect on the mempool. + atomic.StoreInt64(&txmp.txRecheck, 0) +} + +// allEntriesSorted returns a slice of all the transactions currently in the +// mempool, sorted in nonincreasing order by priority with ties broken by +// increasing order of arrival time. +func (txmp *TxMempool) allEntriesSorted() []*WrappedTx { + txmp.mtx.RLock() + defer txmp.mtx.RUnlock() + + all := make([]*WrappedTx, 0, len(txmp.txByKey)) + for _, tx := range txmp.txByKey { + all = append(all, tx.Value.(*WrappedTx)) + } + sort.Slice(all, func(i, j int) bool { + if all[i].priority == all[j].priority { + return all[i].timestamp.Before(all[j].timestamp) + } + return all[i].priority > all[j].priority // N.B. higher priorities first + }) + return all +} + +// ReapMaxBytesMaxGas returns a slice of valid transactions that fit within the +// size and gas constraints. The results are ordered by nonincreasing priority, +// with ties broken by increasing order of arrival. Reaping transactions does +// not remove them from the mempool. +// +// If maxBytes < 0, no limit is set on the total size in bytes. +// If maxGas < 0, no limit is set on the total gas cost. +// +// If the mempool is empty or has no transactions fitting within the given +// constraints, the result will also be empty. +func (txmp *TxMempool) ReapMaxBytesMaxGas(maxBytes, maxGas int64) types.Txs { + var totalGas, totalBytes int64 + + var keep []types.Tx //nolint:prealloc + for _, w := range txmp.allEntriesSorted() { + // N.B. When computing byte size, we need to include the overhead for + // encoding as protobuf to send to the application. + totalGas += w.gasWanted + totalBytes += types.ComputeProtoSizeForTxs([]types.Tx{w.tx}) + if (maxGas >= 0 && totalGas > maxGas) || (maxBytes >= 0 && totalBytes > maxBytes) { + break + } + keep = append(keep, w.tx) + } + return keep +} + +// TxsWaitChan returns a channel that is closed when there is at least one +// transaction available to be gossiped. +func (txmp *TxMempool) TxsWaitChan() <-chan struct{} { return txmp.txs.WaitChan() } + +// TxsFront returns the frontmost element of the pending transaction list. +// It will be nil if the mempool is empty. +func (txmp *TxMempool) TxsFront() *clist.CElement { return txmp.txs.Front() } + +// ReapMaxTxs returns up to max transactions from the mempool. The results are +// ordered by nonincreasing priority with ties broken by increasing order of +// arrival. Reaping transactions does not remove them from the mempool. +// +// If max < 0, all transactions in the mempool are reaped. +// +// The result may have fewer than max elements (possibly zero) if the mempool +// does not have that many transactions available. +func (txmp *TxMempool) ReapMaxTxs(max int) types.Txs { + var keep []types.Tx //nolint:prealloc + + for _, w := range txmp.allEntriesSorted() { + if max >= 0 && len(keep) >= max { + break + } + keep = append(keep, w.tx) + } + return keep +} + +// Update removes all the given transactions from the mempool and the cache, +// and updates the current block height. The blockTxs and deliverTxResponses +// must have the same length with each response corresponding to the tx at the +// same offset. +// +// If the configuration enables recheck, Update sends each remaining +// transaction after removing blockTxs to the ABCI CheckTx method. Any +// transactions marked as invalid during recheck are also removed. +// +// The caller must hold an exclusive mempool lock (by calling txmp.Lock) before +// calling Update. +func (txmp *TxMempool) Update( + blockHeight int64, + blockTxs types.Txs, + deliverTxResponses []*abci.ResponseDeliverTx, + newPreFn mempool.PreCheckFunc, + newPostFn mempool.PostCheckFunc, +) error { + // TODO(creachadair): This would be a nice safety check but requires Go 1.18. + // // Safety check: The caller is required to hold the lock. + // if txmp.mtx.TryLock() { + // txmp.mtx.Unlock() + // panic("mempool: Update caller does not hold the lock") + // } + // Safety check: Transactions and responses must match in number. + if len(blockTxs) != len(deliverTxResponses) { + panic(fmt.Sprintf("mempool: got %d transactions but %d DeliverTx responses", + len(blockTxs), len(deliverTxResponses))) + } + + txmp.height = blockHeight + txmp.notifiedTxsAvailable = false + + if newPreFn != nil { + txmp.preCheck = newPreFn + } + if newPostFn != nil { + txmp.postCheck = newPostFn + } + + for i, tx := range blockTxs { + // Add successful committed transactions to the cache (if they are not + // already present). Transactions that failed to commit are removed from + // the cache unless the operator has explicitly requested we keep them. + if deliverTxResponses[i].Code == abci.CodeTypeOK { + _ = txmp.cache.Push(tx) + } else if !txmp.config.KeepInvalidTxsInCache { + txmp.cache.Remove(tx) + } + + // Regardless of success, remove the transaction from the mempool. + _ = txmp.removeTxByKey(tx.Key()) + } + + txmp.purgeExpiredTxs(blockHeight) + + // If there any uncommitted transactions left in the mempool, we either + // initiate re-CheckTx per remaining transaction or notify that remaining + // transactions are left. + size := txmp.Size() + txmp.metrics.Size.Set(float64(size)) + if size > 0 { + if txmp.config.Recheck { + txmp.recheckTransactions() + } else { + txmp.notifyTxsAvailable() + } + } + return nil +} + +// initialTxCallback handles the ABCI CheckTx response for the first time a +// transaction is added to the mempool. A recheck after a block is committed +// goes to the default callback (see recheckTxCallback). +// +// If either the application rejected the transaction or a post-check hook is +// defined and rejects the transaction, it is discarded. +// +// Otherwise, if the mempool is full, check for lower-priority transactions +// that can be evicted to make room for the new one. If no such transactions +// exist, this transaction is logged and dropped; otherwise the selected +// transactions are evicted. +// +// Finally, the new transaction is added and size stats updated. +func (txmp *TxMempool) initialTxCallback(wtx *WrappedTx, res *abci.Response) { + checkTxRes, ok := res.Value.(*abci.Response_CheckTx) + if !ok { + txmp.logger.Error("mempool: received incorrect result type in CheckTx callback", + "expected", reflect.TypeOf(&abci.Response_CheckTx{}).Name(), + "got", reflect.TypeOf(res.Value).Name(), + ) + return + } + + txmp.mtx.Lock() + defer txmp.mtx.Unlock() + + var err error + if txmp.postCheck != nil { + err = txmp.postCheck(wtx.tx, checkTxRes.CheckTx) + } + + if err != nil || checkTxRes.CheckTx.Code != abci.CodeTypeOK { + txmp.logger.Info( + "rejected bad transaction", + "priority", wtx.Priority(), + "tx", fmt.Sprintf("%X", wtx.tx.Hash()), + "peer_id", wtx.peers, + "code", checkTxRes.CheckTx.Code, + "post_check_err", err, + ) + + txmp.metrics.FailedTxs.Add(1) + + // Remove the invalid transaction from the cache, unless the operator has + // instructed us to keep invalid transactions. + if !txmp.config.KeepInvalidTxsInCache { + txmp.cache.Remove(wtx.tx) + } + + // If there was a post-check error, record its text in the result for + // debugging purposes. + if err != nil { + checkTxRes.CheckTx.MempoolError = err.Error() + } + return + } + + priority := checkTxRes.CheckTx.Priority + sender := checkTxRes.CheckTx.Sender + + // Disallow multiple concurrent transactions from the same sender assigned + // by the ABCI application. As a special case, an empty sender is not + // restricted. + if sender != "" { + elt, ok := txmp.txBySender[sender] + if ok { + w := elt.Value.(*WrappedTx) + txmp.logger.Debug( + "rejected valid incoming transaction; tx already exists for sender", + "tx", fmt.Sprintf("%X", w.tx.Hash()), + "sender", sender, + ) + checkTxRes.CheckTx.MempoolError = + fmt.Sprintf("rejected valid incoming transaction; tx already exists for sender %q (%X)", + sender, w.tx.Hash()) + txmp.metrics.RejectedTxs.Add(1) + return + } + } + + // At this point the application has ruled the transaction valid, but the + // mempool might be full. If so, find the lowest-priority items with lower + // priority than the application assigned to this new one, and evict as many + // of them as necessary to make room for tx. If no such items exist, we + // discard tx. + + if err := txmp.canAddTx(wtx); err != nil { + var victims []*clist.CElement // eligible transactions for eviction + var victimBytes int64 // total size of victims + for cur := txmp.txs.Front(); cur != nil; cur = cur.Next() { + cw := cur.Value.(*WrappedTx) + if cw.priority < priority { + victims = append(victims, cur) + victimBytes += cw.Size() + } + } + + // If there are no suitable eviction candidates, or the total size of + // those candidates is not enough to make room for the new transaction, + // drop the new one. + if len(victims) == 0 || victimBytes < wtx.Size() { + txmp.cache.Remove(wtx.tx) + txmp.logger.Error( + "rejected valid incoming transaction; mempool is full", + "tx", fmt.Sprintf("%X", wtx.tx.Hash()), + "err", err.Error(), + ) + checkTxRes.CheckTx.MempoolError = + fmt.Sprintf("rejected valid incoming transaction; mempool is full (%X)", + wtx.tx.Hash()) + txmp.metrics.RejectedTxs.Add(1) + return + } + + txmp.logger.Debug("evicting lower-priority transactions", + "new_tx", fmt.Sprintf("%X", wtx.tx.Hash()), + "new_priority", priority, + ) + + // Sort lowest priority items first so they will be evicted first. Break + // ties in favor of newer items (to maintain FIFO semantics in a group). + sort.Slice(victims, func(i, j int) bool { + iw := victims[i].Value.(*WrappedTx) + jw := victims[j].Value.(*WrappedTx) + if iw.Priority() == jw.Priority() { + return iw.timestamp.After(jw.timestamp) + } + return iw.Priority() < jw.Priority() + }) + + // Evict as many of the victims as necessary to make room. + var evictedBytes int64 + for _, vic := range victims { + w := vic.Value.(*WrappedTx) + + txmp.logger.Debug( + "evicted valid existing transaction; mempool full", + "old_tx", fmt.Sprintf("%X", w.tx.Hash()), + "old_priority", w.priority, + ) + txmp.removeTxByElement(vic) + txmp.cache.Remove(w.tx) + txmp.metrics.EvictedTxs.Add(1) + + // We may not need to evict all the eligible transactions. Bail out + // early if we have made enough room. + evictedBytes += w.Size() + if evictedBytes >= wtx.Size() { + break + } + } + } + + wtx.SetGasWanted(checkTxRes.CheckTx.GasWanted) + wtx.SetPriority(priority) + wtx.SetSender(sender) + txmp.insertTx(wtx) + + txmp.metrics.TxSizeBytes.Observe(float64(wtx.Size())) + txmp.metrics.Size.Set(float64(txmp.Size())) + txmp.logger.Debug( + "inserted new valid transaction", + "priority", wtx.Priority(), + "tx", fmt.Sprintf("%X", wtx.tx.Hash()), + "height", txmp.height, + "num_txs", txmp.Size(), + ) + txmp.notifyTxsAvailable() +} + +func (txmp *TxMempool) insertTx(wtx *WrappedTx) { + elt := txmp.txs.PushBack(wtx) + txmp.txByKey[wtx.tx.Key()] = elt + if s := wtx.Sender(); s != "" { + txmp.txBySender[s] = elt + } + + atomic.AddInt64(&txmp.txsBytes, wtx.Size()) +} + +// recheckTxCallback handles the responses from ABCI CheckTx calls issued +// during the recheck phase of a block Update. It updates the recheck counter +// and removes any transactions invalidated by the application. +// +// This callback is NOT executed for the initial CheckTx on a new transaction; +// that case is handled by initialTxCallback instead. +func (txmp *TxMempool) recheckTxCallback(req *abci.Request, res *abci.Response) { + checkTxRes, ok := res.Value.(*abci.Response_CheckTx) + if !ok { + // Don't log this; this is the default callback and other response types + // can safely be ignored. + return + } + + // Check whether we are expecting recheck responses at this point. + // If not, we will ignore the response, this usually means the mempool was Flushed. + // If this is the "last" pending recheck, trigger a notification when it's been processed. + numLeft := atomic.AddInt64(&txmp.txRecheck, -1) + if numLeft == 0 { + defer txmp.notifyTxsAvailable() // notify waiters on return, if mempool is non-empty + } else if numLeft < 0 { + return + } + + txmp.metrics.RecheckTimes.Add(1) + tx := types.Tx(req.GetCheckTx().Tx) + + txmp.mtx.Lock() + defer txmp.mtx.Unlock() + + // Find the transaction reported by the ABCI callback. It is possible the + // transaction was evicted during the recheck, in which case the transaction + // will be gone. + elt, ok := txmp.txByKey[tx.Key()] + if !ok { + return + } + wtx := elt.Value.(*WrappedTx) + + // If a postcheck hook is defined, call it before checking the result. + var err error + if txmp.postCheck != nil { + err = txmp.postCheck(tx, checkTxRes.CheckTx) + } + + if checkTxRes.CheckTx.Code == abci.CodeTypeOK && err == nil { + wtx.SetPriority(checkTxRes.CheckTx.Priority) + return // N.B. Size of mempool did not change + } + + txmp.logger.Debug( + "existing transaction no longer valid; failed re-CheckTx callback", + "priority", wtx.Priority(), + "tx", fmt.Sprintf("%X", wtx.tx.Hash()), + "err", err, + "code", checkTxRes.CheckTx.Code, + ) + txmp.removeTxByElement(elt) + txmp.metrics.FailedTxs.Add(1) + if !txmp.config.KeepInvalidTxsInCache { + txmp.cache.Remove(wtx.tx) + } + txmp.metrics.Size.Set(float64(txmp.Size())) +} + +// recheckTransactions initiates re-CheckTx ABCI calls for all the transactions +// currently in the mempool. It reports the number of recheck calls that were +// successfully initiated. +// +// Precondition: The mempool is not empty. +// The caller must hold txmp.mtx exclusively. +func (txmp *TxMempool) recheckTransactions() { + if txmp.Size() == 0 { + panic("mempool: cannot run recheck on an empty mempool") + } + txmp.logger.Debug( + "executing re-CheckTx for all remaining transactions", + "num_txs", txmp.Size(), + "height", txmp.height, + ) + // N.B.: We have to issue the calls outside the lock. In a local client, + // even an "async" call invokes its callback immediately which will make the + // callback deadlock trying to acquire the same lock. This isn't a problem + // with out-of-process calls, but this has to work for both. + txmp.mtx.Unlock() + defer txmp.mtx.Lock() + + atomic.StoreInt64(&txmp.txRecheck, int64(txmp.txs.Len())) + for e := txmp.txs.Front(); e != nil; e = e.Next() { + wtx := e.Value.(*WrappedTx) + + // The response for this CheckTx is handled by the default recheckTxCallback. + _ = txmp.proxyAppConn.CheckTxAsync(abci.RequestCheckTx{ + Tx: wtx.tx, + Type: abci.CheckTxType_Recheck, + }) + if err := txmp.proxyAppConn.FlushSync(); err != nil { + atomic.AddInt64(&txmp.txRecheck, -1) + txmp.logger.Error("mempool: error flushing re-CheckTx", "key", wtx.tx.Key(), "err", err) + } + } + + txmp.proxyAppConn.FlushAsync() +} + +// canAddTx returns an error if we cannot insert the provided *WrappedTx into +// the mempool due to mempool configured constraints. Otherwise, nil is +// returned and the transaction can be inserted into the mempool. +func (txmp *TxMempool) canAddTx(wtx *WrappedTx) error { + numTxs := txmp.Size() + txBytes := txmp.SizeBytes() + + if numTxs >= txmp.config.Size || wtx.Size()+txBytes > txmp.config.MaxTxsBytes { + return mempool.ErrMempoolIsFull{ + NumTxs: numTxs, + MaxTxs: txmp.config.Size, + TxsBytes: txBytes, + MaxTxsBytes: txmp.config.MaxTxsBytes, + } + } + + return nil +} + +// purgeExpiredTxs removes all transactions from the mempool that have exceeded +// their respective height or time-based limits as of the given blockHeight. +// Transactions removed by this operation are not removed from the cache. +// +// The caller must hold txmp.mtx exclusively. +func (txmp *TxMempool) purgeExpiredTxs(blockHeight int64) { + if txmp.config.TTLNumBlocks == 0 && txmp.config.TTLDuration == 0 { + return // nothing to do + } + + now := time.Now() + cur := txmp.txs.Front() + for cur != nil { + // N.B. Grab the next element first, since if we remove cur its successor + // will be invalidated. + next := cur.Next() + + w := cur.Value.(*WrappedTx) + if txmp.config.TTLNumBlocks > 0 && (blockHeight-w.height) > txmp.config.TTLNumBlocks { + txmp.removeTxByElement(cur) + txmp.cache.Remove(w.tx) + txmp.metrics.EvictedTxs.Add(1) + } else if txmp.config.TTLDuration > 0 && now.Sub(w.timestamp) > txmp.config.TTLDuration { + txmp.removeTxByElement(cur) + txmp.cache.Remove(w.tx) + txmp.metrics.EvictedTxs.Add(1) + } + cur = next + } +} + +func (txmp *TxMempool) notifyTxsAvailable() { + if txmp.Size() == 0 { + return // nothing to do + } + + if txmp.txsAvailable != nil && !txmp.notifiedTxsAvailable { + // channel cap is 1, so this will send once + txmp.notifiedTxsAvailable = true + + select { + case txmp.txsAvailable <- struct{}{}: + default: + } + } +} diff --git a/mempool/v1/mempool_bench_test.go b/mempool/v1/mempool_bench_test.go new file mode 100644 index 000000000..8a407ce17 --- /dev/null +++ b/mempool/v1/mempool_bench_test.go @@ -0,0 +1,33 @@ +//go:build deprecated + +package v1 + +import ( + "fmt" + "math/rand" + "testing" + "time" + + "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/mempool" +) + +func BenchmarkTxMempool_CheckTx(b *testing.B) { + txmp := setup(b, 10000) + rng := rand.New(rand.NewSource(time.Now().UnixNano())) + + b.ResetTimer() + + for n := 0; n < b.N; n++ { + b.StopTimer() + prefix := make([]byte, 20) + _, err := rng.Read(prefix) + require.NoError(b, err) + + priority := int64(rng.Intn(9999-1000) + 1000) + tx := []byte(fmt.Sprintf("%X=%d", prefix, priority)) + b.StartTimer() + + require.NoError(b, txmp.CheckTx(tx, nil, mempool.TxInfo{})) + } +} diff --git a/mempool/v1/mempool_test.go b/mempool/v1/mempool_test.go new file mode 100644 index 000000000..7be1dd2fe --- /dev/null +++ b/mempool/v1/mempool_test.go @@ -0,0 +1,656 @@ +//go:build deprecated + +package v1 + +import ( + "bytes" + "errors" + "fmt" + "math/rand" + "os" + "sort" + "strconv" + "strings" + "sync" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/tendermint/tendermint/abci/example/code" + "github.com/tendermint/tendermint/abci/example/kvstore" + abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/config" + "github.com/tendermint/tendermint/libs/log" + "github.com/tendermint/tendermint/mempool" + "github.com/tendermint/tendermint/proxy" + "github.com/tendermint/tendermint/types" +) + +// application extends the KV store application by overriding CheckTx to provide +// transaction priority based on the value in the key/value pair. +type application struct { + *kvstore.Application +} + +type testTx struct { + tx types.Tx + priority int64 +} + +func (app *application) CheckTx(req abci.RequestCheckTx) abci.ResponseCheckTx { + var ( + priority int64 + sender string + ) + + // infer the priority from the raw transaction value (sender=key=value) + parts := bytes.Split(req.Tx, []byte("=")) + if len(parts) == 3 { + v, err := strconv.ParseInt(string(parts[2]), 10, 64) + if err != nil { + return abci.ResponseCheckTx{ + Priority: priority, + Code: 100, + GasWanted: 1, + } + } + + priority = v + sender = string(parts[0]) + } else { + return abci.ResponseCheckTx{ + Priority: priority, + Code: 101, + GasWanted: 1, + } + } + + return abci.ResponseCheckTx{ + Priority: priority, + Sender: sender, + Code: code.CodeTypeOK, + GasWanted: 1, + } +} + +func setup(t testing.TB, cacheSize int, options ...TxMempoolOption) *TxMempool { + t.Helper() + + app := &application{kvstore.NewApplication()} + cc := proxy.NewLocalClientCreator(app) + + cfg := config.ResetTestRoot(strings.ReplaceAll(t.Name(), "/", "|")) + cfg.Mempool.CacheSize = cacheSize + + appConnMem, err := cc.NewABCIClient() + require.NoError(t, err) + require.NoError(t, appConnMem.Start()) + + t.Cleanup(func() { + os.RemoveAll(cfg.RootDir) + require.NoError(t, appConnMem.Stop()) + }) + + return NewTxMempool(log.TestingLogger().With("test", t.Name()), cfg.Mempool, appConnMem, 0, options...) +} + +// mustCheckTx invokes txmp.CheckTx for the given transaction and waits until +// its callback has finished executing. It fails t if CheckTx fails. +func mustCheckTx(t *testing.T, txmp *TxMempool, spec string) { + done := make(chan struct{}) + if err := txmp.CheckTx([]byte(spec), func(*abci.Response) { + close(done) + }, mempool.TxInfo{}); err != nil { + t.Fatalf("CheckTx for %q failed: %v", spec, err) + } + <-done +} + +func checkTxs(t *testing.T, txmp *TxMempool, numTxs int, peerID uint16) []testTx { + txs := make([]testTx, numTxs) + txInfo := mempool.TxInfo{SenderID: peerID} + + rng := rand.New(rand.NewSource(time.Now().UnixNano())) + + for i := 0; i < numTxs; i++ { + prefix := make([]byte, 20) + _, err := rng.Read(prefix) + require.NoError(t, err) + + priority := int64(rng.Intn(9999-1000) + 1000) + + txs[i] = testTx{ + tx: []byte(fmt.Sprintf("sender-%d-%d=%X=%d", i, peerID, prefix, priority)), + priority: priority, + } + require.NoError(t, txmp.CheckTx(txs[i].tx, nil, txInfo)) + } + + return txs +} + +func TestTxMempool_TxsAvailable(t *testing.T) { + txmp := setup(t, 0) + txmp.EnableTxsAvailable() + + ensureNoTxFire := func() { + timer := time.NewTimer(500 * time.Millisecond) + select { + case <-txmp.TxsAvailable(): + require.Fail(t, "unexpected transactions event") + case <-timer.C: + } + } + + ensureTxFire := func() { + timer := time.NewTimer(500 * time.Millisecond) + select { + case <-txmp.TxsAvailable(): + case <-timer.C: + require.Fail(t, "expected transactions event") + } + } + + // ensure no event as we have not executed any transactions yet + ensureNoTxFire() + + // Execute CheckTx for some transactions and ensure TxsAvailable only fires + // once. + txs := checkTxs(t, txmp, 100, 0) + ensureTxFire() + ensureNoTxFire() + + rawTxs := make([]types.Tx, len(txs)) + for i, tx := range txs { + rawTxs[i] = tx.tx + } + + responses := make([]*abci.ResponseDeliverTx, len(rawTxs[:50])) + for i := 0; i < len(responses); i++ { + responses[i] = &abci.ResponseDeliverTx{Code: abci.CodeTypeOK} + } + + // commit half the transactions and ensure we fire an event + txmp.Lock() + require.NoError(t, txmp.Update(1, rawTxs[:50], responses, nil, nil)) + txmp.Unlock() + ensureTxFire() + ensureNoTxFire() + + // Execute CheckTx for more transactions and ensure we do not fire another + // event as we're still on the same height (1). + _ = checkTxs(t, txmp, 100, 0) + ensureNoTxFire() +} + +func TestTxMempool_Size(t *testing.T) { + txmp := setup(t, 0) + txs := checkTxs(t, txmp, 100, 0) + require.Equal(t, len(txs), txmp.Size()) + require.Equal(t, int64(5690), txmp.SizeBytes()) + + rawTxs := make([]types.Tx, len(txs)) + for i, tx := range txs { + rawTxs[i] = tx.tx + } + + responses := make([]*abci.ResponseDeliverTx, len(rawTxs[:50])) + for i := 0; i < len(responses); i++ { + responses[i] = &abci.ResponseDeliverTx{Code: abci.CodeTypeOK} + } + + txmp.Lock() + require.NoError(t, txmp.Update(1, rawTxs[:50], responses, nil, nil)) + txmp.Unlock() + + require.Equal(t, len(rawTxs)/2, txmp.Size()) + require.Equal(t, int64(2850), txmp.SizeBytes()) +} + +func TestTxMempool_Eviction(t *testing.T) { + txmp := setup(t, 1000) + txmp.config.Size = 5 + txmp.config.MaxTxsBytes = 60 + txExists := func(spec string) bool { + txmp.Lock() + defer txmp.Unlock() + key := types.Tx(spec).Key() + _, ok := txmp.txByKey[key] + return ok + } + + // A transaction bigger than the mempool should be rejected even when there + // are slots available. + mustCheckTx(t, txmp, "big=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef=1") + require.Equal(t, 0, txmp.Size()) + + // Nearly-fill the mempool with a low-priority transaction, to show that it + // is evicted even when slots are available for a higher-priority tx. + const bigTx = "big=0123456789abcdef0123456789abcdef0123456789abcdef01234=2" + mustCheckTx(t, txmp, bigTx) + require.Equal(t, 1, txmp.Size()) // bigTx is the only element + require.True(t, txExists(bigTx)) + require.Equal(t, int64(len(bigTx)), txmp.SizeBytes()) + + // The next transaction should evict bigTx, because it is higher priority + // but does not fit on size. + mustCheckTx(t, txmp, "key1=0000=25") + require.True(t, txExists("key1=0000=25")) + require.False(t, txExists(bigTx)) + require.False(t, txmp.cache.Has([]byte(bigTx))) + require.Equal(t, int64(len("key1=0000=25")), txmp.SizeBytes()) + + // Now fill up the rest of the slots with other transactions. + mustCheckTx(t, txmp, "key2=0001=5") + mustCheckTx(t, txmp, "key3=0002=10") + mustCheckTx(t, txmp, "key4=0003=3") + mustCheckTx(t, txmp, "key5=0004=3") + + // A new transaction with low priority should be discarded. + mustCheckTx(t, txmp, "key6=0005=1") + require.False(t, txExists("key6=0005=1")) + + // A new transaction with higher priority should evict key5, which is the + // newest of the two transactions with lowest priority. + mustCheckTx(t, txmp, "key7=0006=7") + require.True(t, txExists("key7=0006=7")) // new transaction added + require.False(t, txExists("key5=0004=3")) // newest low-priority tx evicted + require.True(t, txExists("key4=0003=3")) // older low-priority tx retained + + // Another new transaction evicts the other low-priority element. + mustCheckTx(t, txmp, "key8=0007=20") + require.True(t, txExists("key8=0007=20")) + require.False(t, txExists("key4=0003=3")) + + // Now the lowest-priority tx is 5, so that should be the next to go. + mustCheckTx(t, txmp, "key9=0008=9") + require.True(t, txExists("key9=0008=9")) + require.False(t, txExists("k3y2=0001=5")) + + // Add a transaction that requires eviction of multiple lower-priority + // entries, in order to fit the size of the element. + mustCheckTx(t, txmp, "key10=0123456789abcdef=11") // evict 10, 9, 7; keep 25, 20, 11 + require.True(t, txExists("key1=0000=25")) + require.True(t, txExists("key8=0007=20")) + require.True(t, txExists("key10=0123456789abcdef=11")) + require.False(t, txExists("key3=0002=10")) + require.False(t, txExists("key9=0008=9")) + require.False(t, txExists("key7=0006=7")) +} + +func TestTxMempool_Flush(t *testing.T) { + txmp := setup(t, 0) + txs := checkTxs(t, txmp, 100, 0) + require.Equal(t, len(txs), txmp.Size()) + require.Equal(t, int64(5690), txmp.SizeBytes()) + + rawTxs := make([]types.Tx, len(txs)) + for i, tx := range txs { + rawTxs[i] = tx.tx + } + + responses := make([]*abci.ResponseDeliverTx, len(rawTxs[:50])) + for i := 0; i < len(responses); i++ { + responses[i] = &abci.ResponseDeliverTx{Code: abci.CodeTypeOK} + } + + txmp.Lock() + require.NoError(t, txmp.Update(1, rawTxs[:50], responses, nil, nil)) + txmp.Unlock() + + txmp.Flush() + require.Zero(t, txmp.Size()) + require.Equal(t, int64(0), txmp.SizeBytes()) +} + +func TestTxMempool_ReapMaxBytesMaxGas(t *testing.T) { + txmp := setup(t, 0) + tTxs := checkTxs(t, txmp, 100, 0) // all txs request 1 gas unit + require.Equal(t, len(tTxs), txmp.Size()) + require.Equal(t, int64(5690), txmp.SizeBytes()) + + txMap := make(map[types.TxKey]testTx) + priorities := make([]int64, len(tTxs)) + for i, tTx := range tTxs { + txMap[tTx.tx.Key()] = tTx + priorities[i] = tTx.priority + } + + sort.Slice(priorities, func(i, j int) bool { + // sort by priority, i.e. decreasing order + return priorities[i] > priorities[j] + }) + + ensurePrioritized := func(reapedTxs types.Txs) { + reapedPriorities := make([]int64, len(reapedTxs)) + for i, rTx := range reapedTxs { + reapedPriorities[i] = txMap[rTx.Key()].priority + } + + require.Equal(t, priorities[:len(reapedPriorities)], reapedPriorities) + } + + // reap by gas capacity only + reapedTxs := txmp.ReapMaxBytesMaxGas(-1, 50) + ensurePrioritized(reapedTxs) + require.Equal(t, len(tTxs), txmp.Size()) + require.Equal(t, int64(5690), txmp.SizeBytes()) + require.Len(t, reapedTxs, 50) + + // reap by transaction bytes only + reapedTxs = txmp.ReapMaxBytesMaxGas(1000, -1) + ensurePrioritized(reapedTxs) + require.Equal(t, len(tTxs), txmp.Size()) + require.Equal(t, int64(5690), txmp.SizeBytes()) + require.GreaterOrEqual(t, len(reapedTxs), 16) + + // Reap by both transaction bytes and gas, where the size yields 31 reaped + // transactions and the gas limit reaps 25 transactions. + reapedTxs = txmp.ReapMaxBytesMaxGas(1500, 30) + ensurePrioritized(reapedTxs) + require.Equal(t, len(tTxs), txmp.Size()) + require.Equal(t, int64(5690), txmp.SizeBytes()) + require.Len(t, reapedTxs, 25) +} + +func TestTxMempool_ReapMaxTxs(t *testing.T) { + txmp := setup(t, 0) + tTxs := checkTxs(t, txmp, 100, 0) + require.Equal(t, len(tTxs), txmp.Size()) + require.Equal(t, int64(5690), txmp.SizeBytes()) + + txMap := make(map[types.TxKey]testTx) + priorities := make([]int64, len(tTxs)) + for i, tTx := range tTxs { + txMap[tTx.tx.Key()] = tTx + priorities[i] = tTx.priority + } + + sort.Slice(priorities, func(i, j int) bool { + // sort by priority, i.e. decreasing order + return priorities[i] > priorities[j] + }) + + ensurePrioritized := func(reapedTxs types.Txs) { + reapedPriorities := make([]int64, len(reapedTxs)) + for i, rTx := range reapedTxs { + reapedPriorities[i] = txMap[rTx.Key()].priority + } + + require.Equal(t, priorities[:len(reapedPriorities)], reapedPriorities) + } + + // reap all transactions + reapedTxs := txmp.ReapMaxTxs(-1) + ensurePrioritized(reapedTxs) + require.Equal(t, len(tTxs), txmp.Size()) + require.Equal(t, int64(5690), txmp.SizeBytes()) + require.Len(t, reapedTxs, len(tTxs)) + + // reap a single transaction + reapedTxs = txmp.ReapMaxTxs(1) + ensurePrioritized(reapedTxs) + require.Equal(t, len(tTxs), txmp.Size()) + require.Equal(t, int64(5690), txmp.SizeBytes()) + require.Len(t, reapedTxs, 1) + + // reap half of the transactions + reapedTxs = txmp.ReapMaxTxs(len(tTxs) / 2) + ensurePrioritized(reapedTxs) + require.Equal(t, len(tTxs), txmp.Size()) + require.Equal(t, int64(5690), txmp.SizeBytes()) + require.Len(t, reapedTxs, len(tTxs)/2) +} + +func TestTxMempool_CheckTxExceedsMaxSize(t *testing.T) { + txmp := setup(t, 0) + + rng := rand.New(rand.NewSource(time.Now().UnixNano())) + tx := make([]byte, txmp.config.MaxTxBytes+1) + _, err := rng.Read(tx) + require.NoError(t, err) + + require.Error(t, txmp.CheckTx(tx, nil, mempool.TxInfo{SenderID: 0})) + + tx = make([]byte, txmp.config.MaxTxBytes-1) + _, err = rng.Read(tx) + require.NoError(t, err) + + require.NoError(t, txmp.CheckTx(tx, nil, mempool.TxInfo{SenderID: 0})) +} + +func TestTxMempool_CheckTxSamePeer(t *testing.T) { + txmp := setup(t, 100) + peerID := uint16(1) + rng := rand.New(rand.NewSource(time.Now().UnixNano())) + + prefix := make([]byte, 20) + _, err := rng.Read(prefix) + require.NoError(t, err) + + tx := []byte(fmt.Sprintf("sender-0=%X=%d", prefix, 50)) + + require.NoError(t, txmp.CheckTx(tx, nil, mempool.TxInfo{SenderID: peerID})) + require.Error(t, txmp.CheckTx(tx, nil, mempool.TxInfo{SenderID: peerID})) +} + +func TestTxMempool_CheckTxSameSender(t *testing.T) { + txmp := setup(t, 100) + peerID := uint16(1) + rng := rand.New(rand.NewSource(time.Now().UnixNano())) + + prefix1 := make([]byte, 20) + _, err := rng.Read(prefix1) + require.NoError(t, err) + + prefix2 := make([]byte, 20) + _, err = rng.Read(prefix2) + require.NoError(t, err) + + tx1 := []byte(fmt.Sprintf("sender-0=%X=%d", prefix1, 50)) + tx2 := []byte(fmt.Sprintf("sender-0=%X=%d", prefix2, 50)) + + require.NoError(t, txmp.CheckTx(tx1, nil, mempool.TxInfo{SenderID: peerID})) + require.Equal(t, 1, txmp.Size()) + require.NoError(t, txmp.CheckTx(tx2, nil, mempool.TxInfo{SenderID: peerID})) + require.Equal(t, 1, txmp.Size()) +} + +func TestTxMempool_ConcurrentTxs(t *testing.T) { + txmp := setup(t, 100) + rng := rand.New(rand.NewSource(time.Now().UnixNano())) + checkTxDone := make(chan struct{}) + + var wg sync.WaitGroup + + wg.Add(1) + go func() { + for i := 0; i < 20; i++ { + _ = checkTxs(t, txmp, 100, 0) + dur := rng.Intn(1000-500) + 500 + time.Sleep(time.Duration(dur) * time.Millisecond) + } + + wg.Done() + close(checkTxDone) + }() + + wg.Add(1) + go func() { + ticker := time.NewTicker(time.Second) + defer ticker.Stop() + defer wg.Done() + + var height int64 = 1 + + for range ticker.C { + reapedTxs := txmp.ReapMaxTxs(200) + if len(reapedTxs) > 0 { + responses := make([]*abci.ResponseDeliverTx, len(reapedTxs)) + for i := 0; i < len(responses); i++ { + var code uint32 + + if i%10 == 0 { + code = 100 + } else { + code = abci.CodeTypeOK + } + + responses[i] = &abci.ResponseDeliverTx{Code: code} + } + + txmp.Lock() + require.NoError(t, txmp.Update(height, reapedTxs, responses, nil, nil)) + txmp.Unlock() + + height++ + } else { + // only return once we know we finished the CheckTx loop + select { + case <-checkTxDone: + return + default: + } + } + } + }() + + wg.Wait() + require.Zero(t, txmp.Size()) + require.Zero(t, txmp.SizeBytes()) +} + +func TestTxMempool_ExpiredTxs_Timestamp(t *testing.T) { + txmp := setup(t, 5000) + txmp.config.TTLDuration = 5 * time.Millisecond + + added1 := checkTxs(t, txmp, 10, 0) + require.Equal(t, len(added1), txmp.Size()) + + // Wait a while, then add some more transactions that should not be expired + // when the first batch TTLs out. + // + // ms: 0 1 2 3 4 5 6 + // ^ ^ ^ ^ + // | | | +-- Update (triggers pruning) + // | | +------ first batch expires + // | +-------------- second batch added + // +-------------------------- first batch added + // + // The exact intervals are not important except that the delta should be + // large relative to the cost of CheckTx (ms vs. ns is fine here). + time.Sleep(3 * time.Millisecond) + added2 := checkTxs(t, txmp, 10, 1) + + // Wait a while longer, so that the first batch will expire. + time.Sleep(3 * time.Millisecond) + + // Trigger an update so that pruning will occur. + txmp.Lock() + defer txmp.Unlock() + require.NoError(t, txmp.Update(txmp.height+1, nil, nil, nil, nil)) + + // All the transactions in the original set should have been purged. + for _, tx := range added1 { + if _, ok := txmp.txByKey[tx.tx.Key()]; ok { + t.Errorf("Transaction %X should have been purged for TTL", tx.tx.Key()) + } + if txmp.cache.Has(tx.tx) { + t.Errorf("Transaction %X should have been removed from the cache", tx.tx.Key()) + } + } + + // All the transactions added later should still be around. + for _, tx := range added2 { + if _, ok := txmp.txByKey[tx.tx.Key()]; !ok { + t.Errorf("Transaction %X should still be in the mempool, but is not", tx.tx.Key()) + } + } +} + +func TestTxMempool_ExpiredTxs_NumBlocks(t *testing.T) { + txmp := setup(t, 500) + txmp.height = 100 + txmp.config.TTLNumBlocks = 10 + + tTxs := checkTxs(t, txmp, 100, 0) + require.Equal(t, len(tTxs), txmp.Size()) + + // reap 5 txs at the next height -- no txs should expire + reapedTxs := txmp.ReapMaxTxs(5) + responses := make([]*abci.ResponseDeliverTx, len(reapedTxs)) + for i := 0; i < len(responses); i++ { + responses[i] = &abci.ResponseDeliverTx{Code: abci.CodeTypeOK} + } + + txmp.Lock() + require.NoError(t, txmp.Update(txmp.height+1, reapedTxs, responses, nil, nil)) + txmp.Unlock() + + require.Equal(t, 95, txmp.Size()) + + // check more txs at height 101 + _ = checkTxs(t, txmp, 50, 1) + require.Equal(t, 145, txmp.Size()) + + // Reap 5 txs at a height that would expire all the transactions from before + // the previous Update (height 100). + // + // NOTE: When we reap txs below, we do not know if we're picking txs from the + // initial CheckTx calls or from the second round of CheckTx calls. Thus, we + // cannot guarantee that all 95 txs are remaining that should be expired and + // removed. However, we do know that that at most 95 txs can be expired and + // removed. + reapedTxs = txmp.ReapMaxTxs(5) + responses = make([]*abci.ResponseDeliverTx, len(reapedTxs)) + for i := 0; i < len(responses); i++ { + responses[i] = &abci.ResponseDeliverTx{Code: abci.CodeTypeOK} + } + + txmp.Lock() + require.NoError(t, txmp.Update(txmp.height+10, reapedTxs, responses, nil, nil)) + txmp.Unlock() + + require.GreaterOrEqual(t, txmp.Size(), 45) +} + +func TestTxMempool_CheckTxPostCheckError(t *testing.T) { + cases := []struct { + name string + err error + }{ + { + name: "error", + err: errors.New("test error"), + }, + { + name: "no error", + err: nil, + }, + } + for _, tc := range cases { + testCase := tc + t.Run(testCase.name, func(t *testing.T) { + postCheckFn := func(_ types.Tx, _ *abci.ResponseCheckTx) error { + return testCase.err + } + txmp := setup(t, 0, WithPostCheck(postCheckFn)) + rng := rand.New(rand.NewSource(time.Now().UnixNano())) + tx := make([]byte, txmp.config.MaxTxBytes-1) + _, err := rng.Read(tx) + require.NoError(t, err) + + callback := func(res *abci.Response) { + checkTxRes, ok := res.Value.(*abci.Response_CheckTx) + require.True(t, ok) + expectedErrString := "" + if testCase.err != nil { + expectedErrString = testCase.err.Error() + } + require.Equal(t, expectedErrString, checkTxRes.CheckTx.MempoolError) + } + require.NoError(t, txmp.CheckTx(tx, callback, mempool.TxInfo{SenderID: 0})) + }) + } +} diff --git a/mempool/v1/reactor.go b/mempool/v1/reactor.go new file mode 100644 index 000000000..8b78a7f41 --- /dev/null +++ b/mempool/v1/reactor.go @@ -0,0 +1,312 @@ +//go:build deprecated + +package v1 + +import ( + "errors" + "fmt" + "time" + + cfg "github.com/tendermint/tendermint/config" + "github.com/tendermint/tendermint/libs/clist" + "github.com/tendermint/tendermint/libs/log" + tmsync "github.com/tendermint/tendermint/libs/sync" + "github.com/tendermint/tendermint/mempool" + "github.com/tendermint/tendermint/p2p" + protomem "github.com/tendermint/tendermint/proto/tendermint/mempool" + "github.com/tendermint/tendermint/types" +) + +// Reactor handles mempool tx broadcasting amongst peers. +// It maintains a map from peer ID to counter, to prevent gossiping txs to the +// peers you received it from. +type Reactor struct { + p2p.BaseReactor + config *cfg.MempoolConfig + mempool *TxMempool + ids *mempoolIDs +} + +type mempoolIDs struct { + mtx tmsync.RWMutex + peerMap map[p2p.ID]uint16 + nextID uint16 // assumes that a node will never have over 65536 active peers + activeIDs map[uint16]struct{} // used to check if a given peerID key is used, the value doesn't matter +} + +// Reserve searches for the next unused ID and assigns it to the +// peer. +func (ids *mempoolIDs) ReserveForPeer(peer p2p.Peer) { + ids.mtx.Lock() + defer ids.mtx.Unlock() + + curID := ids.nextPeerID() + ids.peerMap[peer.ID()] = curID + ids.activeIDs[curID] = struct{}{} +} + +// nextPeerID returns the next unused peer ID to use. +// This assumes that ids's mutex is already locked. +func (ids *mempoolIDs) nextPeerID() uint16 { + if len(ids.activeIDs) == mempool.MaxActiveIDs { + panic(fmt.Sprintf("node has maximum %d active IDs and wanted to get one more", mempool.MaxActiveIDs)) + } + + _, idExists := ids.activeIDs[ids.nextID] + for idExists { + ids.nextID++ + _, idExists = ids.activeIDs[ids.nextID] + } + curID := ids.nextID + ids.nextID++ + return curID +} + +// Reclaim returns the ID reserved for the peer back to unused pool. +func (ids *mempoolIDs) Reclaim(peer p2p.Peer) { + ids.mtx.Lock() + defer ids.mtx.Unlock() + + removedID, ok := ids.peerMap[peer.ID()] + if ok { + delete(ids.activeIDs, removedID) + delete(ids.peerMap, peer.ID()) + } +} + +// GetForPeer returns an ID reserved for the peer. +func (ids *mempoolIDs) GetForPeer(peer p2p.Peer) uint16 { + ids.mtx.RLock() + defer ids.mtx.RUnlock() + + return ids.peerMap[peer.ID()] +} + +func newMempoolIDs() *mempoolIDs { + return &mempoolIDs{ + peerMap: make(map[p2p.ID]uint16), + activeIDs: map[uint16]struct{}{0: {}}, + nextID: 1, // reserve unknownPeerID(0) for mempoolReactor.BroadcastTx + } +} + +// NewReactor returns a new Reactor with the given config and mempool. +func NewReactor(config *cfg.MempoolConfig, mempool *TxMempool) *Reactor { + memR := &Reactor{ + config: config, + mempool: mempool, + ids: newMempoolIDs(), + } + memR.BaseReactor = *p2p.NewBaseReactor("Mempool", memR) + return memR +} + +// InitPeer implements Reactor by creating a state for the peer. +func (memR *Reactor) InitPeer(peer p2p.Peer) p2p.Peer { + memR.ids.ReserveForPeer(peer) + return peer +} + +// SetLogger sets the Logger on the reactor and the underlying mempool. +func (memR *Reactor) SetLogger(l log.Logger) { + memR.Logger = l +} + +// OnStart implements p2p.BaseReactor. +func (memR *Reactor) OnStart() error { + if !memR.config.Broadcast { + memR.Logger.Info("Tx broadcasting is disabled") + } + return nil +} + +// GetChannels implements Reactor by returning the list of channels for this +// reactor. +func (memR *Reactor) GetChannels() []*p2p.ChannelDescriptor { + largestTx := make([]byte, memR.config.MaxTxBytes) + batchMsg := protomem.Message{ + Sum: &protomem.Message_Txs{ + Txs: &protomem.Txs{Txs: [][]byte{largestTx}}, + }, + } + + return []*p2p.ChannelDescriptor{ + { + ID: mempool.MempoolChannel, + Priority: 5, + RecvMessageCapacity: batchMsg.Size(), + }, + } +} + +// AddPeer implements Reactor. +// It starts a broadcast routine ensuring all txs are forwarded to the given peer. +func (memR *Reactor) AddPeer(peer p2p.Peer) { + if memR.config.Broadcast { + go memR.broadcastTxRoutine(peer) + } +} + +// RemovePeer implements Reactor. +func (memR *Reactor) RemovePeer(peer p2p.Peer, reason interface{}) { + memR.ids.Reclaim(peer) + // broadcast routine checks if peer is gone and returns +} + +// Receive implements Reactor. +// It adds any received transactions to the mempool. +func (memR *Reactor) Receive(chID byte, src p2p.Peer, msgBytes []byte) { + msg, err := memR.decodeMsg(msgBytes) + if err != nil { + memR.Logger.Error("Error decoding message", "src", src, "chId", chID, "err", err) + memR.Switch.StopPeerForError(src, err) + return + } + memR.Logger.Debug("Receive", "src", src, "chId", chID, "msg", msg) + + txInfo := mempool.TxInfo{SenderID: memR.ids.GetForPeer(src)} + if src != nil { + txInfo.SenderP2PID = src.ID() + } + for _, tx := range msg.Txs { + err = memR.mempool.CheckTx(tx, nil, txInfo) + if err == mempool.ErrTxInCache { + memR.Logger.Debug("Tx already exists in cache", "tx", tx.String()) + } else if err != nil { + memR.Logger.Info("Could not check tx", "tx", tx.String(), "err", err) + } + } + // broadcasting happens from go routines per peer +} + +// PeerState describes the state of a peer. +type PeerState interface { + GetHeight() int64 +} + +// Send new mempool txs to peer. +func (memR *Reactor) broadcastTxRoutine(peer p2p.Peer) { + peerID := memR.ids.GetForPeer(peer) + var next *clist.CElement + + for { + // In case of both next.NextWaitChan() and peer.Quit() are variable at the same time + if !memR.IsRunning() || !peer.IsRunning() { + return + } + + // This happens because the CElement we were looking at got garbage + // collected (removed). That is, .NextWait() returned nil. Go ahead and + // start from the beginning. + if next == nil { + select { + case <-memR.mempool.TxsWaitChan(): // Wait until a tx is available + if next = memR.mempool.TxsFront(); next == nil { + continue + } + + case <-peer.Quit(): + return + + case <-memR.Quit(): + return + } + } + + // Make sure the peer is up to date. + peerState, ok := peer.Get(types.PeerStateKey).(PeerState) + if !ok { + // Peer does not have a state yet. We set it in the consensus reactor, but + // when we add peer in Switch, the order we call reactors#AddPeer is + // different every time due to us using a map. Sometimes other reactors + // will be initialized before the consensus reactor. We should wait a few + // milliseconds and retry. + time.Sleep(mempool.PeerCatchupSleepIntervalMS * time.Millisecond) + continue + } + + // Allow for a lag of 1 block. + memTx := next.Value.(*WrappedTx) + if peerState.GetHeight() < memTx.height-1 { + time.Sleep(mempool.PeerCatchupSleepIntervalMS * time.Millisecond) + continue + } + + // NOTE: Transaction batching was disabled due to + // https://github.com/tendermint/tendermint/issues/5796 + if !memTx.HasPeer(peerID) { + msg := protomem.Message{ + Sum: &protomem.Message_Txs{ + Txs: &protomem.Txs{Txs: [][]byte{memTx.tx}}, + }, + } + + bz, err := msg.Marshal() + if err != nil { + panic(err) + } + + success := peer.Send(mempool.MempoolChannel, bz) + if !success { + time.Sleep(mempool.PeerCatchupSleepIntervalMS * time.Millisecond) + continue + } + } + + select { + case <-next.NextWaitChan(): + // see the start of the for loop for nil check + next = next.Next() + + case <-peer.Quit(): + return + + case <-memR.Quit(): + return + } + } +} + +//----------------------------------------------------------------------------- +// Messages + +func (memR *Reactor) decodeMsg(bz []byte) (TxsMessage, error) { + msg := protomem.Message{} + err := msg.Unmarshal(bz) + if err != nil { + return TxsMessage{}, err + } + + var message TxsMessage + + if i, ok := msg.Sum.(*protomem.Message_Txs); ok { + txs := i.Txs.GetTxs() + + if len(txs) == 0 { + return message, errors.New("empty TxsMessage") + } + + decoded := make([]types.Tx, len(txs)) + for j, tx := range txs { + decoded[j] = types.Tx(tx) + } + + message = TxsMessage{ + Txs: decoded, + } + return message, nil + } + return message, fmt.Errorf("msg type: %T is not supported", msg) +} + +//------------------------------------- + +// TxsMessage is a Message containing transactions. +type TxsMessage struct { + Txs []types.Tx +} + +// String returns a string representation of the TxsMessage. +func (m *TxsMessage) String() string { + return fmt.Sprintf("[TxsMessage %v]", m.Txs) +} diff --git a/mempool/v1/reactor_test.go b/mempool/v1/reactor_test.go new file mode 100644 index 000000000..5d5ef92c9 --- /dev/null +++ b/mempool/v1/reactor_test.go @@ -0,0 +1,188 @@ +//go:build deprecated + +package v1 + +import ( + "encoding/hex" + "os" + "sync" + "testing" + "time" + + "github.com/go-kit/log/term" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/tendermint/tendermint/abci/example/kvstore" + + cfg "github.com/tendermint/tendermint/config" + + "github.com/tendermint/tendermint/libs/log" + "github.com/tendermint/tendermint/mempool" + "github.com/tendermint/tendermint/p2p" + memproto "github.com/tendermint/tendermint/proto/tendermint/mempool" + "github.com/tendermint/tendermint/proxy" + "github.com/tendermint/tendermint/types" +) + +const ( + numTxs = 1000 + timeout = 120 * time.Second // ridiculously high because CircleCI is slow +) + +type peerState struct { + height int64 +} + +func (ps peerState) GetHeight() int64 { + return ps.height +} + +// Send a bunch of txs to the first reactor's mempool and wait for them all to +// be received in the others. +func TestReactorBroadcastTxsMessage(t *testing.T) { + config := cfg.TestConfig() + // if there were more than two reactors, the order of transactions could not be + // asserted in waitForTxsOnReactors (due to transactions gossiping). If we + // replace Connect2Switches (full mesh) with a func, which connects first + // reactor to others and nothing else, this test should also pass with >2 reactors. + const N = 2 + reactors := makeAndConnectReactors(config, N) + defer func() { + for _, r := range reactors { + if err := r.Stop(); err != nil { + assert.NoError(t, err) + } + } + }() + for _, r := range reactors { + for _, peer := range r.Switch.Peers().List() { + peer.Set(types.PeerStateKey, peerState{1}) + } + } + + txs := checkTxs(t, reactors[0].mempool, numTxs, mempool.UnknownPeerID) + transactions := make(types.Txs, len(txs)) + for idx, tx := range txs { + transactions[idx] = tx.tx + } + + waitForTxsOnReactors(t, transactions, reactors) +} + +func TestMempoolVectors(t *testing.T) { + testCases := []struct { + testName string + tx []byte + expBytes string + }{ + {"tx 1", []byte{123}, "0a030a017b"}, + {"tx 2", []byte("proto encoding in mempool"), "0a1b0a1970726f746f20656e636f64696e6720696e206d656d706f6f6c"}, + } + + for _, tc := range testCases { + tc := tc + + msg := memproto.Message{ + Sum: &memproto.Message_Txs{ + Txs: &memproto.Txs{Txs: [][]byte{tc.tx}}, + }, + } + bz, err := msg.Marshal() + require.NoError(t, err, tc.testName) + + require.Equal(t, tc.expBytes, hex.EncodeToString(bz), tc.testName) + } +} + +func makeAndConnectReactors(config *cfg.Config, n int) []*Reactor { + reactors := make([]*Reactor, n) + logger := mempoolLogger() + for i := 0; i < n; i++ { + app := kvstore.NewApplication() + cc := proxy.NewLocalClientCreator(app) + mempool, cleanup := newMempoolWithApp(cc) + defer cleanup() + + reactors[i] = NewReactor(config.Mempool, mempool) // so we dont start the consensus states + reactors[i].SetLogger(logger.With("validator", i)) + } + + p2p.MakeConnectedSwitches(config.P2P, n, func(i int, s *p2p.Switch) *p2p.Switch { + s.AddReactor("MEMPOOL", reactors[i]) + return s + + }, p2p.Connect2Switches) + return reactors +} + +// mempoolLogger is a TestingLogger which uses a different +// color for each validator ("validator" key must exist). +func mempoolLogger() log.Logger { + return log.TestingLoggerWithColorFn(func(keyvals ...interface{}) term.FgBgColor { + for i := 0; i < len(keyvals)-1; i += 2 { + if keyvals[i] == "validator" { + return term.FgBgColor{Fg: term.Color(uint8(keyvals[i+1].(int) + 1))} + } + } + return term.FgBgColor{} + }) +} + +func newMempoolWithApp(cc proxy.ClientCreator) (*TxMempool, func()) { + conf := cfg.ResetTestRoot("mempool_test") + + mp, cu := newMempoolWithAppAndConfig(cc, conf) + return mp, cu +} + +func newMempoolWithAppAndConfig(cc proxy.ClientCreator, conf *cfg.Config) (*TxMempool, func()) { + appConnMem, _ := cc.NewABCIClient() + appConnMem.SetLogger(log.TestingLogger().With("module", "abci-client", "connection", "mempool")) + err := appConnMem.Start() + if err != nil { + panic(err) + } + + mp := NewTxMempool(log.TestingLogger(), conf.Mempool, appConnMem, 0) + + return mp, func() { os.RemoveAll(conf.RootDir) } +} + +func waitForTxsOnReactors(t *testing.T, txs types.Txs, reactors []*Reactor) { + // wait for the txs in all mempools + wg := new(sync.WaitGroup) + for i, reactor := range reactors { + wg.Add(1) + go func(r *Reactor, reactorIndex int) { + defer wg.Done() + waitForTxsOnReactor(t, txs, r, reactorIndex) + }(reactor, i) + } + + done := make(chan struct{}) + go func() { + wg.Wait() + close(done) + }() + + timer := time.After(timeout) + select { + case <-timer: + t.Fatal("Timed out waiting for txs") + case <-done: + } +} + +func waitForTxsOnReactor(t *testing.T, txs types.Txs, reactor *Reactor, reactorIndex int) { + mempool := reactor.mempool + for mempool.Size() < len(txs) { + time.Sleep(time.Millisecond * 100) + } + + reapedTxs := mempool.ReapMaxTxs(len(txs)) + for i, tx := range txs { + assert.Equalf(t, tx, reapedTxs[i], + "txs at index %d on reactor %d don't match: %v vs %v", i, reactorIndex, tx, reapedTxs[i]) + } +} diff --git a/mempool/v1/tx.go b/mempool/v1/tx.go new file mode 100644 index 000000000..1cb24b7eb --- /dev/null +++ b/mempool/v1/tx.go @@ -0,0 +1,89 @@ +//go:build deprecated + +package v1 + +import ( + "sync" + "time" + + "github.com/tendermint/tendermint/types" +) + +// WrappedTx defines a wrapper around a raw transaction with additional metadata +// that is used for indexing. +type WrappedTx struct { + tx types.Tx // the original transaction data + hash types.TxKey // the transaction hash + height int64 // height when this transaction was initially checked (for expiry) + timestamp time.Time // time when transaction was entered (for TTL) + + mtx sync.Mutex + gasWanted int64 // app: gas required to execute this transaction + priority int64 // app: priority value for this transaction + sender string // app: assigned sender label + peers map[uint16]bool // peer IDs who have sent us this transaction +} + +// Size reports the size of the raw transaction in bytes. +func (w *WrappedTx) Size() int64 { return int64(len(w.tx)) } + +// SetPeer adds the specified peer ID as a sender of w. +func (w *WrappedTx) SetPeer(id uint16) { + w.mtx.Lock() + defer w.mtx.Unlock() + if w.peers == nil { + w.peers = map[uint16]bool{id: true} + } else { + w.peers[id] = true + } +} + +// HasPeer reports whether the specified peer ID is a sender of w. +func (w *WrappedTx) HasPeer(id uint16) bool { + w.mtx.Lock() + defer w.mtx.Unlock() + _, ok := w.peers[id] + return ok +} + +// SetGasWanted sets the application-assigned gas requirement of w. +func (w *WrappedTx) SetGasWanted(gas int64) { + w.mtx.Lock() + defer w.mtx.Unlock() + w.gasWanted = gas +} + +// GasWanted reports the application-assigned gas requirement of w. +func (w *WrappedTx) GasWanted() int64 { + w.mtx.Lock() + defer w.mtx.Unlock() + return w.gasWanted +} + +// SetSender sets the application-assigned sender of w. +func (w *WrappedTx) SetSender(sender string) { + w.mtx.Lock() + defer w.mtx.Unlock() + w.sender = sender +} + +// Sender reports the application-assigned sender of w. +func (w *WrappedTx) Sender() string { + w.mtx.Lock() + defer w.mtx.Unlock() + return w.sender +} + +// SetPriority sets the application-assigned priority of w. +func (w *WrappedTx) SetPriority(p int64) { + w.mtx.Lock() + defer w.mtx.Unlock() + w.priority = p +} + +// Priority reports the application-assigned priority of w. +func (w *WrappedTx) Priority() int64 { + w.mtx.Lock() + defer w.mtx.Unlock() + return w.priority +} diff --git a/node/node.go b/node/node.go index d2c2fae1a..48c42dd52 100644 --- a/node/node.go +++ b/node/node.go @@ -29,6 +29,9 @@ import ( "github.com/Finschia/ostracon/libs/service" "github.com/Finschia/ostracon/light" mempl "github.com/Finschia/ostracon/mempool" + mempoolv0 "github.com/Finschia/ostracon/mempool/v0" + + //mempoolv1 "github.com/Finschia/ostracon/mempool/v1" "github.com/Finschia/ostracon/p2p" "github.com/Finschia/ostracon/p2p/pex" "github.com/Finschia/ostracon/privval" @@ -230,7 +233,7 @@ type Node struct { stateStore sm.Store blockStore *store.BlockStore // store the blockchain to disk bcReactor p2p.Reactor // for fast-syncing - mempoolReactor *mempl.Reactor // for gossipping transactions + mempoolReactor p2p.Reactor // for gossipping transactions mempool mempl.Mempool stateSync bool // whether the node should state sync on startup stateSyncReactor *statesync.Reactor // for hosting and restoring state sync snapshots @@ -384,25 +387,68 @@ func onlyValidatorIsUs(state sm.State, pubKey crypto.PubKey) bool { return bytes.Equal(pubKey.Address(), addr) } -func createMempoolAndMempoolReactor(config *cfg.Config, proxyApp proxy.AppConns, - state sm.State, memplMetrics *mempl.Metrics, logger log.Logger) (*mempl.Reactor, *mempl.CListMempool) { +func createMempoolAndMempoolReactor( + config *cfg.Config, + proxyApp proxy.AppConns, + state sm.State, + memplMetrics *mempl.Metrics, + logger log.Logger, +) (mempl.Mempool, p2p.Reactor) { + + switch config.Mempool.Version { + case cfg.MempoolV1: // XXX Deprecated MempoolV1 + panic("Deprecated MempoolV1") + /* + // TODO(thane): Remove log once https://github.com/tendermint/tendermint/issues/8775 is resolved. + logger.Error("While the prioritized mempool API is stable, there is a critical bug in it that is currently under investigation. See https://github.com/tendermint/tendermint/issues/8775 for details") + mp := mempoolv1.NewTxMempool( + logger, + config.Mempool, + proxyApp.Mempool(), + state.LastBlockHeight, + mempoolv1.WithMetrics(memplMetrics), + mempoolv1.WithPreCheck(sm.TxPreCheck(state)), + mempoolv1.WithPostCheck(sm.TxPostCheck(state)), + ) + + reactor := mempoolv1.NewReactor( + config.Mempool, + mp, + ) + if config.Consensus.WaitForTxs() { + mp.EnableTxsAvailable() + } - mempool := mempl.NewCListMempool( - config.Mempool, - proxyApp.Mempool(), - state.LastBlockHeight, - mempl.WithMetrics(memplMetrics), - mempl.WithPreCheck(sm.TxPreCheck(state)), - mempl.WithPostCheck(sm.TxPostCheck(state)), - ) - mempoolLogger := logger.With("module", "mempool") - mempoolReactor := mempl.NewReactor(config.Mempool, config.P2P.RecvAsync, config.P2P.MempoolRecvBufSize, mempool) - mempoolReactor.SetLogger(mempoolLogger) + return mp, reactor + */ + case cfg.MempoolV0: + mp := mempoolv0.NewCListMempool( + config.Mempool, + proxyApp.Mempool(), + state.LastBlockHeight, + mempoolv0.WithMetrics(memplMetrics), + mempoolv0.WithPreCheck(sm.TxPreCheck(state)), + mempoolv0.WithPostCheck(sm.TxPostCheck(state)), + ) + + mp.SetLogger(logger) + + reactor := mempoolv0.NewReactor( + config.Mempool, + config.P2P.RecvAsync, + config.P2P.MempoolRecvBufSize, + mp, + ) - if config.Consensus.WaitForTxs() { - mempool.EnableTxsAvailable() + if config.Consensus.WaitForTxs() { + mp.EnableTxsAvailable() + } + + return mp, reactor + + default: + return nil, nil } - return mempoolReactor, mempool } func createEvidenceReactor(config *cfg.Config, dbProvider DBProvider, @@ -450,7 +496,7 @@ func createConsensusReactor(config *cfg.Config, state sm.State, blockExec *sm.BlockExecutor, blockStore sm.BlockStore, - mempool *mempl.CListMempool, + mempool mempl.Mempool, evidencePool *evidence.Pool, privValidator types.PrivValidator, csMetrics *cs.Metrics, @@ -553,7 +599,7 @@ func createSwitch(config *cfg.Config, transport p2p.Transport, p2pMetrics *p2p.Metrics, peerFilters []p2p.PeerFilterFunc, - mempoolReactor *mempl.Reactor, + mempoolReactor p2p.Reactor, bcReactor p2p.Reactor, stateSyncReactor *statesync.Reactor, consensusReactor *cs.Reactor, @@ -787,7 +833,7 @@ func NewNode(config *cfg.Config, csMetrics, p2pMetrics, memplMetrics, smMetrics := metricsProvider(genDoc.ChainID) // Make MempoolReactor - mempoolReactor, mempool := createMempoolAndMempoolReactor(config, proxyApp, state, memplMetrics, logger) + mempool, mempoolReactor := createMempoolAndMempoolReactor(config, proxyApp, state, memplMetrics, logger) // Make Evidence Reactor evidenceReactor, evidencePool, err := createEvidenceReactor(config, dbProvider, stateDB, blockStore, logger) @@ -965,13 +1011,6 @@ func (n *Node) OnStart() error { n.isListening = true - if n.config.Mempool.WalEnabled() { - err = n.mempool.InitWAL() - if err != nil { - return fmt.Errorf("init mempool WAL: %w", err) - } - } - // Start the switch (the P2P server). err = n.sw.Start() if err != nil { @@ -1019,11 +1058,6 @@ func (n *Node) OnStop() { n.Logger.Error("Error closing switch", "err", err) } - // stop mempool WAL - if n.config.Mempool.WalEnabled() { - n.mempool.CloseWAL() - } - if err := n.transport.Close(); err != nil { n.Logger.Error("Error closing transport", "err", err) } @@ -1262,7 +1296,7 @@ func (n *Node) ConsensusReactor() *cs.Reactor { } // MempoolReactor returns the Node's mempool reactor. -func (n *Node) MempoolReactor() *mempl.Reactor { +func (n *Node) MempoolReactor() p2p.Reactor { return n.mempoolReactor } diff --git a/node/node_test.go b/node/node_test.go index 2ca318cc5..3a8217f88 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -25,6 +25,9 @@ import ( "github.com/Finschia/ostracon/libs/log" tmrand "github.com/Finschia/ostracon/libs/rand" mempl "github.com/Finschia/ostracon/mempool" + mempoolv0 "github.com/Finschia/ostracon/mempool/v0" + + //mempoolv1 "github.com/Finschia/ostracon/mempool/v1" "github.com/Finschia/ostracon/p2p" "github.com/Finschia/ostracon/p2p/conn" p2pmock "github.com/Finschia/ostracon/p2p/mock" @@ -266,16 +269,30 @@ func TestCreateProposalBlock(t *testing.T) { proposerAddr, _ := state.Validators.GetByIndex(0) // Make Mempool - memplMetrics := mempl.PrometheusMetrics("node_test_1") - mempool := mempl.NewCListMempool( - config.Mempool, - proxyApp.Mempool(), - state.LastBlockHeight, - mempl.WithMetrics(memplMetrics), - mempl.WithPreCheck(sm.TxPreCheck(state)), - mempl.WithPostCheck(sm.TxPostCheck(state)), - ) - mempool.SetLogger(logger) + memplMetrics := mempl.NopMetrics() + var mempool mempl.Mempool + + switch config.Mempool.Version { + case cfg.MempoolV0: + mempool = mempoolv0.NewCListMempool(config.Mempool, + proxyApp.Mempool(), + state.LastBlockHeight, + mempoolv0.WithMetrics(memplMetrics), + mempoolv0.WithPreCheck(sm.TxPreCheck(state)), + mempoolv0.WithPostCheck(sm.TxPostCheck(state))) + case cfg.MempoolV1: // XXX Deprecated MempoolV1 + panic("Deprecated MempoolV1") + /* + mempool = mempoolv1.NewTxMempool(logger, + config.Mempool, + proxyApp.Mempool(), + state.LastBlockHeight, + mempoolv1.WithMetrics(memplMetrics), + mempoolv1.WithPreCheck(sm.TxPreCheck(state)), + mempoolv1.WithPostCheck(sm.TxPostCheck(state)), + ) + */ + } // Make EvidencePool evidenceDB := dbm.NewMemDB() @@ -303,7 +320,7 @@ func TestCreateProposalBlock(t *testing.T) { txLength := 100 for i := 0; i <= maxBytes/txLength; i++ { tx := tmrand.Bytes(txLength) - _, err := mempool.CheckTxSync(tx, mempl.TxInfo{}) + err := mempool.CheckTxSync(tx, nil, mempl.TxInfo{}) assert.NoError(t, err) } @@ -363,21 +380,33 @@ func TestMaxProposalBlockSize(t *testing.T) { proposerAddr, _ := state.Validators.GetByIndex(0) // Make Mempool - memplMetrics := mempl.PrometheusMetrics("node_test_2") - mempool := mempl.NewCListMempool( - config.Mempool, - proxyApp.Mempool(), - state.LastBlockHeight, - mempl.WithMetrics(memplMetrics), - mempl.WithPreCheck(sm.TxPreCheck(state)), - mempl.WithPostCheck(sm.TxPostCheck(state)), - ) - mempool.SetLogger(logger) + memplMetrics := mempl.NopMetrics() + var mempool mempl.Mempool + switch config.Mempool.Version { + case cfg.MempoolV0: + mempool = mempoolv0.NewCListMempool(config.Mempool, + proxyApp.Mempool(), + state.LastBlockHeight, + mempoolv0.WithMetrics(memplMetrics), + mempoolv0.WithPreCheck(sm.TxPreCheck(state)), + mempoolv0.WithPostCheck(sm.TxPostCheck(state))) + case cfg.MempoolV1: // XXX Deprecated + /* + mempool = mempoolv1.NewTxMempool(logger, + config.Mempool, + proxyApp.Mempool(), + state.LastBlockHeight, + mempoolv1.WithMetrics(memplMetrics), + mempoolv1.WithPreCheck(sm.TxPreCheck(state)), + mempoolv1.WithPostCheck(sm.TxPostCheck(state)), + ) + */ + } // fill the mempool with one txs just below the maximum size txLength := int(types.MaxDataBytesNoEvidence(maxBytes, 1)) tx := tmrand.Bytes(txLength - 4) // to account for the varint - _, err = mempool.CheckTxSync(tx, mempl.TxInfo{}) + err = mempool.CheckTxSync(tx, nil, mempl.TxInfo{}) assert.NoError(t, err) blockExec := sm.NewBlockExecutor( diff --git a/p2p/conn/connection.go b/p2p/conn/connection.go index a9ace878e..d4f684a11 100644 --- a/p2p/conn/connection.go +++ b/p2p/conn/connection.go @@ -359,7 +359,7 @@ func (c *MConnection) Send(chID byte, msgBytes []byte) bool { return false } - c.Logger.Debug("Send", "channel", chID, "conn", c, "msgBytes", fmt.Sprintf("%X", msgBytes)) + c.Logger.Debug("Send", "channel", chID, "conn", c, "msgBytes", log.NewLazySprintf("%X", msgBytes)) // Send message to channel. channel, ok := c.channelsIdx[chID] @@ -376,7 +376,7 @@ func (c *MConnection) Send(chID byte, msgBytes []byte) bool { default: } } else { - c.Logger.Debug("Send failed", "channel", chID, "conn", c, "msgBytes", fmt.Sprintf("%X", msgBytes)) + c.Logger.Debug("Send failed", "channel", chID, "conn", c, "msgBytes", log.NewLazySprintf("%X", msgBytes)) } return success } @@ -388,7 +388,7 @@ func (c *MConnection) TrySend(chID byte, msgBytes []byte) bool { return false } - c.Logger.Debug("TrySend", "channel", chID, "conn", c, "msgBytes", fmt.Sprintf("%X", msgBytes)) + c.Logger.Debug("TrySend", "channel", chID, "conn", c, "msgBytes", log.NewLazySprintf("%X", msgBytes)) // Send message to channel. channel, ok := c.channelsIdx[chID] diff --git a/p2p/mocks/node_info.go b/p2p/mocks/node_info.go index 1e2b2039d..2009bee9a 100644 --- a/p2p/mocks/node_info.go +++ b/p2p/mocks/node_info.go @@ -80,13 +80,12 @@ func (_m *NodeInfo) Validate() error { return r0 } -type mockConstructorTestingTNewNodeInfo interface { +// NewNodeInfo creates a new instance of NodeInfo. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewNodeInfo(t interface { mock.TestingT Cleanup(func()) -} - -// NewNodeInfo creates a new instance of NodeInfo. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewNodeInfo(t mockConstructorTestingTNewNodeInfo) *NodeInfo { +}) *NodeInfo { mock := &NodeInfo{} mock.Mock.Test(t) diff --git a/p2p/mocks/peer.go b/p2p/mocks/peer.go index 509f7d5b9..4f79499f0 100644 --- a/p2p/mocks/peer.go +++ b/p2p/mocks/peer.go @@ -330,13 +330,12 @@ func (_m *Peer) TrySend(_a0 byte, _a1 []byte) bool { return r0 } -type mockConstructorTestingTNewPeer interface { +// NewPeer creates a new instance of Peer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewPeer(t interface { mock.TestingT Cleanup(func()) -} - -// NewPeer creates a new instance of Peer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewPeer(t mockConstructorTestingTNewPeer) *Peer { +}) *Peer { mock := &Peer{} mock.Mock.Test(t) diff --git a/p2p/pex/addrbook.go b/p2p/pex/addrbook.go index 11272d0a6..51813500d 100644 --- a/p2p/pex/addrbook.go +++ b/p2p/pex/addrbook.go @@ -16,6 +16,7 @@ import ( "github.com/minio/highwayhash" "github.com/Finschia/ostracon/crypto" + "github.com/Finschia/ostracon/libs/log" tmmath "github.com/Finschia/ostracon/libs/math" tmrand "github.com/Finschia/ostracon/libs/rand" "github.com/Finschia/ostracon/libs/service" @@ -740,7 +741,7 @@ func (a *addrBook) expireNew(bucketIdx int) { for addrStr, ka := range a.bucketsNew[bucketIdx] { // If an entry is bad, throw it away if ka.isBad() { - a.Logger.Info(fmt.Sprintf("expiring bad address %v", addrStr)) + a.Logger.Info("expire new", "msg", log.NewLazySprintf("expiring bad address %v", addrStr)) a.removeFromBucket(ka, bucketTypeNew, bucketIdx) return } diff --git a/p2p/switch.go b/p2p/switch.go index 40f70e456..679699367 100644 --- a/p2p/switch.go +++ b/p2p/switch.go @@ -8,6 +8,7 @@ import ( "github.com/Finschia/ostracon/config" "github.com/Finschia/ostracon/libs/cmap" + "github.com/Finschia/ostracon/libs/log" "github.com/Finschia/ostracon/libs/rand" "github.com/Finschia/ostracon/libs/service" "github.com/Finschia/ostracon/p2p/conn" @@ -262,7 +263,7 @@ func (sw *Switch) OnStop() { // // NOTE: Broadcast uses goroutines, so order of broadcast may not be preserved. func (sw *Switch) Broadcast(chID byte, msgBytes []byte) chan bool { - sw.Logger.Debug("Broadcast", "channel", chID, "msgBytes", fmt.Sprintf("%X", msgBytes)) + sw.Logger.Debug("Broadcast", "channel", chID, "msgBytes", log.NewLazySprintf("%X", msgBytes)) peers := sw.peers.List() var wg sync.WaitGroup diff --git a/p2p/upnp/probe.go b/p2p/upnp/probe.go index f48db735e..23473babf 100644 --- a/p2p/upnp/probe.go +++ b/p2p/upnp/probe.go @@ -18,19 +18,19 @@ func makeUPNPListener(intPort int, extPort int, logger log.Logger) (NAT, net.Lis if err != nil { return nil, nil, nil, fmt.Errorf("nat upnp could not be discovered: %v", err) } - logger.Info(fmt.Sprintf("ourIP: %v", nat.(*upnpNAT).ourIP)) + logger.Info("make upnp listener", "msg", log.NewLazySprintf("ourIP: %v", nat.(*upnpNAT).ourIP)) ext, err := nat.GetExternalAddress() if err != nil { return nat, nil, nil, fmt.Errorf("external address error: %v", err) } - logger.Info(fmt.Sprintf("External address: %v", ext)) + logger.Info("make upnp listener", "msg", log.NewLazySprintf("External address: %v", ext)) port, err := nat.AddPortMapping("tcp", extPort, intPort, "Ostracon UPnP Probe", 0) if err != nil { return nat, nil, ext, fmt.Errorf("port mapping error: %v", err) } - logger.Info(fmt.Sprintf("Port mapping mapped: %v", port)) + logger.Info("make upnp listener", "msg", log.NewLazySprintf("Port mapping mapped: %v", port)) // also run the listener, open for all remote addresses. listener, err := net.Listen("tcp", fmt.Sprintf(":%v", intPort)) @@ -45,17 +45,23 @@ func testHairpin(listener net.Listener, extAddr string, logger log.Logger) (supp go func() { inConn, err := listener.Accept() if err != nil { - logger.Info(fmt.Sprintf("Listener.Accept() error: %v", err)) + logger.Info("test hair pin", "msg", log.NewLazySprintf("Listener.Accept() error: %v", err)) return } - logger.Info(fmt.Sprintf("Accepted incoming connection: %v -> %v", inConn.LocalAddr(), inConn.RemoteAddr())) + logger.Info("test hair pin", + "msg", + log.NewLazySprintf("Accepted incoming connection: %v -> %v", inConn.LocalAddr(), inConn.RemoteAddr())) buf := make([]byte, 1024) n, err := inConn.Read(buf) if err != nil { - logger.Info(fmt.Sprintf("Incoming connection read error: %v", err)) + logger.Info("test hair pin", + "msg", + log.NewLazySprintf("Incoming connection read error: %v", err)) return } - logger.Info(fmt.Sprintf("Incoming connection read %v bytes: %X", n, buf)) + logger.Info("test hair pin", + "msg", + log.NewLazySprintf("Incoming connection read %v bytes: %X", n, buf)) if string(buf) == "test data" { supportsHairpin = true return @@ -65,16 +71,16 @@ func testHairpin(listener net.Listener, extAddr string, logger log.Logger) (supp // Establish outgoing outConn, err := net.Dial("tcp", extAddr) if err != nil { - logger.Info(fmt.Sprintf("Outgoing connection dial error: %v", err)) + logger.Info("test hair pin", "msg", log.NewLazySprintf("Outgoing connection dial error: %v", err)) return } n, err := outConn.Write([]byte("test data")) if err != nil { - logger.Info(fmt.Sprintf("Outgoing connection write error: %v", err)) + logger.Info("test hair pin", "msg", log.NewLazySprintf("Outgoing connection write error: %v", err)) return } - logger.Info(fmt.Sprintf("Outgoing connection wrote %v bytes", n)) + logger.Info("test hair pin", "msg", log.NewLazySprintf("Outgoing connection wrote %v bytes", n)) // Wait for data receipt time.Sleep(1 * time.Second) diff --git a/proto/README.md b/proto/README.md new file mode 100644 index 000000000..1317ee761 --- /dev/null +++ b/proto/README.md @@ -0,0 +1,16 @@ +# Using buf build +https://buf.build/ + +```script +go run github.com/bufbuild/buf/cmd/buf help +``` + +## buf.yaml +See: +- https://buf.build/docs/lint/overview/ +- https://buf.build/docs/lint/rules/ + +## if you update `buf.yaml`, should also update `buf.lock` +```script +cd proto && go run github.com/bufbuild/buf/cmd/buf mod update && cd .. +``` diff --git a/proto/buf.lock b/proto/buf.lock new file mode 100644 index 000000000..768ad21ce --- /dev/null +++ b/proto/buf.lock @@ -0,0 +1,8 @@ +# Generated by buf. DO NOT EDIT. +version: v1 +deps: + - remote: buf.build + owner: gogo + repository: protobuf + commit: 5461a3dfa9d941da82028ab185dc2a0e + digest: shake256:37c7c75224982038cb1abf45b481ef06716c1f806ffaa162018d0df092bd11a2a9b62c2d0dc0a2ae43beff86b6014fc0eb8c594ffd84d52ade4b08fca901eadc diff --git a/proto/buf.yaml b/proto/buf.yaml new file mode 100644 index 000000000..af1671e6b --- /dev/null +++ b/proto/buf.yaml @@ -0,0 +1,11 @@ +version: v1 +deps: + - buf.build/gogo/protobuf +# - buf.build/tendermint/tendermint # don't use since can't specify tendermint-v0.34.19 +breaking: + use: + - FILE +lint: + use: + - BASIC + - UNARY_RPC diff --git a/proto/ostracon/abci/types.proto b/proto/ostracon/abci/types.proto index 145b1ad72..158fb4b6b 100644 --- a/proto/ostracon/abci/types.proto +++ b/proto/ostracon/abci/types.proto @@ -5,13 +5,9 @@ option go_package = "github.com/Finschia/ostracon/abci/types"; // For more information on gogo.proto, see: // https://github.com/gogo/protobuf/blob/master/extensions.md -import "tendermint/crypto/proof.proto"; -import "tendermint/types/params.proto"; import "tendermint/abci/types.proto"; import "tendermint/types/types.proto"; import "ostracon/types/types.proto"; -import "tendermint/crypto/keys.proto"; -import "google/protobuf/timestamp.proto"; import "gogoproto/gogo.proto"; // This file is copied from http://github.com/tendermint/abci diff --git a/proto/ostracon/privval/types.pb.go b/proto/ostracon/privval/types.pb.go index 0e0d33721..8bc5614ee 100644 --- a/proto/ostracon/privval/types.pb.go +++ b/proto/ostracon/privval/types.pb.go @@ -5,11 +5,8 @@ package privval import ( fmt "fmt" - _ "github.com/gogo/protobuf/gogoproto" proto "github.com/gogo/protobuf/proto" - _ "github.com/tendermint/tendermint/proto/tendermint/crypto" privval "github.com/tendermint/tendermint/proto/tendermint/privval" - _ "github.com/tendermint/tendermint/proto/tendermint/types" io "io" math "math" math_bits "math/bits" @@ -322,41 +319,39 @@ func init() { func init() { proto.RegisterFile("ostracon/privval/types.proto", fileDescriptor_abbbbe5131a55005) } var fileDescriptor_abbbbe5131a55005 = []byte{ - // 538 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x94, 0xc1, 0x6e, 0xd3, 0x30, - 0x18, 0xc7, 0x13, 0x46, 0x1b, 0xe4, 0x76, 0xb4, 0x33, 0x05, 0x55, 0xd5, 0x14, 0x4a, 0x11, 0x30, + // 508 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x94, 0x41, 0x6f, 0xd3, 0x30, + 0x14, 0xc7, 0x13, 0x46, 0x17, 0xf4, 0xda, 0xd1, 0xce, 0x0c, 0x54, 0x21, 0x14, 0x4a, 0x11, 0x30, 0x81, 0x94, 0x48, 0xdb, 0x91, 0xdb, 0x04, 0x63, 0xd2, 0x34, 0x54, 0x32, 0x69, 0x87, 0x49, 0xa8, - 0x4a, 0xdb, 0xaf, 0x59, 0xb4, 0x25, 0x36, 0xb6, 0x13, 0x29, 0x6f, 0xc1, 0x63, 0x71, 0xdc, 0x11, - 0x6e, 0xa8, 0xbd, 0xc0, 0x5b, 0x4c, 0x71, 0xdc, 0x24, 0xed, 0xd2, 0xde, 0xe2, 0xbf, 0x3f, 0xff, - 0xbe, 0x9f, 0x15, 0xdb, 0x68, 0x9f, 0x70, 0xc1, 0xdc, 0x09, 0x09, 0x6d, 0xca, 0xfc, 0x38, 0x76, - 0x6f, 0x6d, 0x91, 0x50, 0xe0, 0x16, 0x65, 0x44, 0x10, 0xdc, 0x5e, 0xce, 0x5a, 0x6a, 0xb6, 0xb7, - 0x2f, 0x20, 0x9c, 0x02, 0x0b, 0xfc, 0x50, 0xd8, 0x13, 0x96, 0x50, 0x41, 0xec, 0x1b, 0x48, 0x54, - 0x7d, 0xaf, 0xe3, 0x11, 0x8f, 0xc8, 0x4f, 0x3b, 0xfd, 0x52, 0x69, 0x79, 0x8d, 0xa4, 0x97, 0x7b, - 0xf4, 0xcc, 0xd2, 0x6c, 0x85, 0xc3, 0xe0, 0x03, 0x6a, 0x5d, 0x3a, 0x27, 0x43, 0x46, 0xc8, 0xcc, - 0x81, 0x1f, 0x11, 0x70, 0x81, 0xbb, 0xc8, 0x08, 0x80, 0x73, 0xd7, 0x83, 0xae, 0xde, 0xd7, 0x0f, - 0x9a, 0xce, 0x72, 0x38, 0x00, 0xd4, 0x2e, 0x8a, 0x39, 0x25, 0x21, 0x07, 0xdc, 0x41, 0x35, 0x9a, - 0x06, 0xaa, 0x36, 0x1b, 0xe0, 0x8f, 0xa8, 0x06, 0x8c, 0x11, 0xd6, 0x7d, 0xd4, 0xd7, 0x0f, 0x1a, - 0x87, 0x6f, 0xac, 0x42, 0x63, 0xb9, 0x59, 0xcb, 0x81, 0x80, 0x08, 0xb8, 0xf0, 0xbd, 0x10, 0xd8, - 0xe7, 0xb4, 0xd8, 0xc9, 0xd6, 0x0c, 0xfe, 0xd4, 0x91, 0x71, 0x9e, 0xb5, 0xc4, 0x67, 0xa8, 0x45, - 0xa3, 0xf1, 0xe8, 0x06, 0x92, 0x11, 0xcb, 0xfc, 0x64, 0xa3, 0xc6, 0xe1, 0xab, 0x2a, 0xe4, 0x30, - 0x1a, 0x9f, 0x41, 0xa2, 0x36, 0x72, 0xaa, 0x39, 0xbb, 0xb4, 0x1c, 0xe0, 0xaf, 0xa8, 0x5d, 0xc0, - 0x32, 0x7f, 0x25, 0x38, 0xd8, 0x46, 0xcb, 0x2a, 0x4f, 0x35, 0xe7, 0x29, 0x5d, 0x49, 0xf0, 0x37, - 0xb4, 0xc7, 0x7d, 0x2f, 0x1c, 0xc5, 0x44, 0x40, 0xae, 0xb7, 0x23, 0x81, 0xaf, 0xab, 0x80, 0xe9, - 0x5e, 0x2f, 0x89, 0x80, 0x42, 0xb0, 0xc5, 0x57, 0x23, 0x7c, 0x85, 0x3a, 0x69, 0x04, 0xd3, 0x25, - 0x54, 0x69, 0x3e, 0x96, 0xd4, 0xb7, 0x9b, 0xa8, 0x30, 0xcd, 0x20, 0xb9, 0x2a, 0xe6, 0x0f, 0x52, - 0xfc, 0x1d, 0x3d, 0x97, 0xba, 0x94, 0x11, 0x4a, 0xb8, 0x7b, 0x9b, 0x2b, 0xd7, 0x24, 0xfc, 0xdd, - 0x26, 0xf8, 0x50, 0xd5, 0x17, 0xda, 0xcf, 0xf8, 0xc3, 0x18, 0xcf, 0x50, 0x57, 0xa9, 0x97, 0x1a, - 0x28, 0xfd, 0xba, 0xec, 0xf0, 0x7e, 0xb3, 0x7e, 0x01, 0xcb, 0xb7, 0xf0, 0x82, 0x57, 0xce, 0xe0, - 0x4f, 0xa8, 0x49, 0xfd, 0xd0, 0xcb, 0xed, 0x0d, 0xc9, 0x7e, 0x59, 0xf9, 0x07, 0xfd, 0xd0, 0x2b, - 0xac, 0x1b, 0xb4, 0x18, 0xe2, 0x2f, 0x68, 0x57, 0x51, 0x94, 0xe2, 0x13, 0x89, 0xe9, 0x6f, 0xc6, - 0xe4, 0x62, 0x4d, 0x5a, 0x1a, 0xe3, 0x21, 0xda, 0x8b, 0xd9, 0x6c, 0x24, 0xcf, 0x7d, 0xee, 0xf4, - 0xcf, 0x50, 0x87, 0x74, 0xfd, 0x8a, 0x5b, 0x6b, 0xb7, 0x2d, 0x3d, 0x03, 0x31, 0x9b, 0xad, 0x5c, - 0xc0, 0x0b, 0x84, 0xcb, 0x44, 0xe5, 0xf7, 0xdf, 0x50, 0x27, 0x75, 0x0b, 0x32, 0x57, 0x6c, 0x17, - 0xcc, 0x2c, 0x3b, 0xae, 0xa1, 0x1d, 0x1e, 0x05, 0xc7, 0xe7, 0xbf, 0xe6, 0xa6, 0x7e, 0x37, 0x37, - 0xf5, 0xbf, 0x73, 0x53, 0xff, 0xb9, 0x30, 0xb5, 0xbb, 0x85, 0xa9, 0xfd, 0x5e, 0x98, 0xda, 0xd5, - 0x91, 0xe7, 0x8b, 0xeb, 0x68, 0x6c, 0x4d, 0x48, 0x60, 0x9f, 0xf8, 0x21, 0x9f, 0x5c, 0xfb, 0xae, - 0x5d, 0x7a, 0xbf, 0xd2, 0x67, 0x67, 0xfd, 0x39, 0x1b, 0xd7, 0x65, 0x7e, 0x74, 0x1f, 0x00, 0x00, - 0xff, 0xff, 0x04, 0x18, 0x8f, 0xf9, 0xe9, 0x04, 0x00, 0x00, + 0x4a, 0xdb, 0xd7, 0x2c, 0x62, 0x89, 0x8d, 0xed, 0x44, 0xea, 0xb7, 0xe0, 0x63, 0x71, 0xdc, 0x11, + 0x6e, 0xa8, 0xbd, 0xc0, 0xb7, 0x40, 0x71, 0xdc, 0x24, 0xed, 0xd2, 0x1d, 0xfd, 0xf7, 0xcb, 0xef, + 0xfd, 0xac, 0x3c, 0x1b, 0x9e, 0x51, 0x21, 0xb9, 0x3f, 0xa6, 0xb1, 0xcb, 0x78, 0x98, 0xa6, 0xfe, + 0xb5, 0x2b, 0x67, 0x0c, 0x85, 0xc3, 0x38, 0x95, 0x94, 0x74, 0x96, 0xbb, 0x8e, 0xde, 0x7d, 0x6a, + 0x4b, 0x8c, 0x27, 0xc8, 0xa3, 0x30, 0x96, 0x75, 0x5f, 0xf4, 0xdf, 0x41, 0xfb, 0xc2, 0x3b, 0x1e, + 0x70, 0x4a, 0xa7, 0x1e, 0x7e, 0x4f, 0x50, 0x48, 0xd2, 0x05, 0x2b, 0x42, 0x21, 0xfc, 0x00, 0xbb, + 0x66, 0xcf, 0xdc, 0x6f, 0x79, 0xcb, 0x65, 0x1f, 0xa1, 0x53, 0x16, 0x0b, 0x46, 0x63, 0x81, 0x64, + 0x0f, 0x1a, 0x2c, 0x0b, 0x74, 0x6d, 0xbe, 0x20, 0xef, 0xa1, 0x81, 0x9c, 0x53, 0xde, 0xbd, 0xd7, + 0x33, 0xf7, 0x9b, 0x07, 0xaf, 0x9c, 0x52, 0x63, 0xa9, 0xe6, 0x78, 0x18, 0x51, 0x89, 0xe7, 0x61, + 0x10, 0x23, 0xff, 0x98, 0x15, 0x7b, 0xf9, 0x37, 0xfd, 0xdf, 0xdb, 0x60, 0x9d, 0xe5, 0x2d, 0xc9, + 0x29, 0xb4, 0x59, 0x32, 0x1a, 0x7e, 0xc3, 0xd9, 0x90, 0xe7, 0x7e, 0xaa, 0x51, 0xf3, 0xe0, 0x45, + 0x1d, 0x72, 0x90, 0x8c, 0x4e, 0x71, 0xa6, 0x0f, 0x72, 0x62, 0x78, 0x3b, 0xac, 0x1a, 0x90, 0xcf, + 0xd0, 0x29, 0x61, 0xb9, 0xbf, 0x16, 0xec, 0xdf, 0x45, 0xcb, 0x2b, 0x4f, 0x0c, 0xef, 0x21, 0x5b, + 0x49, 0xc8, 0x17, 0xd8, 0x15, 0x61, 0x10, 0x0f, 0x53, 0x2a, 0xb1, 0xd0, 0xdb, 0x52, 0xc0, 0x97, + 0x75, 0xc0, 0xec, 0xac, 0x17, 0x54, 0x62, 0x29, 0xd8, 0x16, 0xab, 0x11, 0xb9, 0x84, 0xbd, 0x2c, + 0xc2, 0xc9, 0x12, 0xaa, 0x35, 0xef, 0x2b, 0xea, 0xeb, 0x4d, 0x54, 0x9c, 0xe4, 0x90, 0x42, 0x95, + 0x88, 0x5b, 0x29, 0xf9, 0x0a, 0x8f, 0x95, 0x2e, 0xe3, 0x94, 0x51, 0xe1, 0x5f, 0x17, 0xca, 0x0d, + 0x05, 0x7f, 0xb3, 0x09, 0x3e, 0xd0, 0xf5, 0xa5, 0xf6, 0x23, 0x71, 0x3b, 0x26, 0x53, 0xe8, 0x6a, + 0xf5, 0x4a, 0x03, 0xad, 0xbf, 0xad, 0x3a, 0xbc, 0xdd, 0xac, 0x5f, 0xc2, 0x8a, 0x23, 0x3c, 0x11, + 0xb5, 0x3b, 0xe4, 0x03, 0xb4, 0x58, 0x18, 0x07, 0x85, 0xbd, 0xa5, 0xd8, 0xcf, 0x6b, 0xff, 0x60, + 0x18, 0x07, 0xa5, 0x75, 0x93, 0x95, 0x4b, 0xf2, 0x09, 0x76, 0x34, 0x45, 0x2b, 0x3e, 0x50, 0x98, + 0xde, 0x66, 0x4c, 0x21, 0xd6, 0x62, 0x95, 0x35, 0x19, 0xc0, 0x6e, 0xca, 0xa7, 0x43, 0x35, 0xf7, + 0x85, 0xd3, 0x5f, 0x4b, 0x0f, 0xe9, 0xfa, 0x85, 0x74, 0xd6, 0x6e, 0x5b, 0x36, 0x03, 0x29, 0x9f, + 0xae, 0x5c, 0xc0, 0x73, 0x20, 0x55, 0xa2, 0xf6, 0xfb, 0x67, 0xe9, 0x49, 0xbd, 0x03, 0x59, 0x28, + 0x76, 0x4a, 0x66, 0x9e, 0x1d, 0x35, 0x60, 0x4b, 0x24, 0xd1, 0xd1, 0xd9, 0xcf, 0xb9, 0x6d, 0xde, + 0xcc, 0x6d, 0xf3, 0xcf, 0xdc, 0x36, 0x7f, 0x2c, 0x6c, 0xe3, 0x66, 0x61, 0x1b, 0xbf, 0x16, 0xb6, + 0x71, 0x79, 0x18, 0x84, 0xf2, 0x2a, 0x19, 0x39, 0x63, 0x1a, 0xb9, 0xc7, 0x61, 0x2c, 0xc6, 0x57, + 0xa1, 0xef, 0x56, 0x5e, 0x1b, 0x2a, 0xa9, 0xbb, 0xfe, 0xf8, 0x8c, 0xb6, 0x55, 0x7e, 0xf8, 0x3f, + 0x00, 0x00, 0xff, 0xff, 0x26, 0x1b, 0x30, 0x10, 0x97, 0x04, 0x00, 0x00, } func (m *VRFProofRequest) Marshal() (dAtA []byte, err error) { diff --git a/proto/ostracon/privval/types.proto b/proto/ostracon/privval/types.proto index f377a2fe1..45a5aa74b 100644 --- a/proto/ostracon/privval/types.proto +++ b/proto/ostracon/privval/types.proto @@ -1,9 +1,6 @@ syntax = "proto3"; package ostracon.privval; -import "tendermint/crypto/keys.proto"; -import "gogoproto/gogo.proto"; -import "tendermint/types/types.proto"; import "tendermint/privval/types.proto"; option go_package = "github.com/Finschia/ostracon/proto/ostracon/privval"; diff --git a/proto/ostracon/state/types.pb.go b/proto/ostracon/state/types.pb.go index 3be0b0934..273381acb 100644 --- a/proto/ostracon/state/types.pb.go +++ b/proto/ostracon/state/types.pb.go @@ -5,8 +5,6 @@ package state import ( fmt "fmt" - _ "github.com/Finschia/ostracon/abci/types" - _ "github.com/Finschia/ostracon/proto/ostracon/types" _ "github.com/gogo/protobuf/gogoproto" proto "github.com/gogo/protobuf/proto" _ "github.com/gogo/protobuf/types" @@ -14,7 +12,6 @@ import ( types "github.com/tendermint/tendermint/abci/types" state "github.com/tendermint/tendermint/proto/tendermint/state" types1 "github.com/tendermint/tendermint/proto/tendermint/types" - _ "github.com/tendermint/tendermint/proto/tendermint/version" io "io" math "math" math_bits "math/bits" @@ -273,52 +270,51 @@ func init() { func init() { proto.RegisterFile("ostracon/state/types.proto", fileDescriptor_898987a4421067cd) } var fileDescriptor_898987a4421067cd = []byte{ - // 708 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x94, 0x4f, 0x6f, 0xd3, 0x3e, - 0x18, 0xc7, 0x9b, 0x5f, 0xb7, 0xb5, 0x73, 0xd6, 0xf6, 0x47, 0xe0, 0x90, 0x75, 0x90, 0x96, 0xf1, - 0xaf, 0xe2, 0x90, 0x8a, 0x71, 0xe2, 0x82, 0x44, 0x5a, 0x60, 0x15, 0x13, 0x9a, 0xb2, 0x69, 0x07, - 0x2e, 0x91, 0x93, 0x78, 0x89, 0x45, 0x1a, 0x47, 0xb1, 0x3b, 0x8d, 0xb7, 0xc0, 0x69, 0x2f, 0x6b, - 0xc7, 0x1d, 0x11, 0x87, 0x81, 0xba, 0x0b, 0x2f, 0x03, 0xd9, 0x8e, 0xd3, 0x6c, 0x65, 0xd2, 0x6e, - 0xce, 0xf3, 0xfd, 0x3e, 0x1f, 0x7d, 0x6d, 0x3f, 0x31, 0xe8, 0x12, 0xca, 0x72, 0x18, 0x90, 0x74, - 0x48, 0x19, 0x64, 0x68, 0xc8, 0xbe, 0x65, 0x88, 0xda, 0x59, 0x4e, 0x18, 0x31, 0xda, 0x4a, 0xb3, - 0x85, 0xd6, 0x7d, 0x10, 0x91, 0x88, 0x08, 0x69, 0xc8, 0x57, 0xd2, 0xd5, 0xdd, 0x2c, 0x09, 0xd0, - 0x0f, 0x70, 0x15, 0xd0, 0x5d, 0xc0, 0x45, 0xf5, 0x9a, 0xd6, 0x67, 0x28, 0x0d, 0x51, 0x3e, 0xc5, - 0x29, 0x2b, 0xd4, 0x13, 0x98, 0xe0, 0x10, 0x32, 0x92, 0x17, 0x8e, 0x47, 0x4b, 0x8e, 0x0c, 0xe6, - 0x70, 0xaa, 0x00, 0x0f, 0x97, 0xe4, 0x2a, 0xde, 0xaa, 0xa8, 0x27, 0x28, 0xa7, 0x58, 0x85, 0x28, - 0xf4, 0x5e, 0x44, 0x48, 0x94, 0xa0, 0xa1, 0xf8, 0xf2, 0x67, 0xc7, 0x43, 0x86, 0xa7, 0x88, 0x32, - 0x38, 0xcd, 0xfe, 0x81, 0x5f, 0x3a, 0x9a, 0xee, 0x56, 0x45, 0xbd, 0xb9, 0xed, 0xed, 0x9f, 0x1a, - 0x68, 0xbd, 0x73, 0x46, 0x13, 0x17, 0xd1, 0x8c, 0xa4, 0x14, 0x51, 0x63, 0x04, 0xf4, 0x10, 0x25, - 0xf8, 0x04, 0xe5, 0x1e, 0x3b, 0xa5, 0xa6, 0xd6, 0xaf, 0x0f, 0xf4, 0x9d, 0x6d, 0x7b, 0x01, 0xb1, - 0x39, 0xc4, 0x56, 0x0d, 0x63, 0xe9, 0x3d, 0x3c, 0x75, 0x41, 0xa8, 0x96, 0xd4, 0x78, 0x0b, 0xd6, - 0x51, 0x1a, 0x7a, 0x7e, 0x42, 0x82, 0xaf, 0xe6, 0x7f, 0x7d, 0x6d, 0xa0, 0xef, 0x3c, 0xbe, 0x15, - 0xf1, 0x3e, 0x0d, 0x1d, 0x6e, 0x74, 0x9b, 0xa8, 0x58, 0x19, 0x63, 0xa0, 0xfb, 0x28, 0xc2, 0x69, - 0x41, 0xa8, 0x0b, 0xc2, 0x93, 0x5b, 0x09, 0x0e, 0xf7, 0x4a, 0x06, 0xf0, 0xcb, 0xf5, 0xf6, 0xf7, - 0x06, 0x58, 0x3d, 0xe0, 0xe7, 0x61, 0xbc, 0x01, 0x8d, 0xe2, 0x64, 0x4d, 0x4d, 0xb0, 0x36, 0xab, - 0x2c, 0x71, 0x66, 0xf6, 0x91, 0x34, 0x38, 0x2b, 0xe7, 0x97, 0xbd, 0x9a, 0xab, 0xfc, 0xc6, 0x73, - 0xd0, 0x0c, 0x62, 0x88, 0x53, 0x0f, 0x87, 0x62, 0x27, 0xeb, 0x8e, 0x3e, 0xbf, 0xec, 0x35, 0x46, - 0xbc, 0x36, 0x19, 0xbb, 0x0d, 0x21, 0x4e, 0x42, 0xe3, 0x19, 0x68, 0xe3, 0x14, 0x33, 0x0c, 0x13, - 0x2f, 0x46, 0x38, 0x8a, 0x99, 0xd9, 0xee, 0x6b, 0x83, 0xba, 0xdb, 0x2a, 0xaa, 0xbb, 0xa2, 0x68, - 0xbc, 0x04, 0xf7, 0x12, 0x48, 0x99, 0xdc, 0x98, 0x72, 0xd6, 0x85, 0xb3, 0xc3, 0x05, 0x91, 0xbc, - 0xf0, 0xba, 0xa0, 0x55, 0xf1, 0xe2, 0xd0, 0x5c, 0x59, 0xce, 0x2e, 0x2f, 0x53, 0x74, 0x4d, 0xc6, - 0xce, 0x7d, 0x9e, 0x7d, 0x7e, 0xd9, 0xd3, 0xf7, 0x14, 0x6a, 0x32, 0x76, 0xf5, 0x92, 0x3b, 0x09, - 0x8d, 0x3d, 0xd0, 0xa9, 0x30, 0xf9, 0x24, 0x99, 0xab, 0x82, 0xda, 0xb5, 0xe5, 0x98, 0xd9, 0x6a, - 0xcc, 0xec, 0x43, 0x35, 0x66, 0x4e, 0x93, 0x63, 0xcf, 0x7e, 0xf5, 0x34, 0xb7, 0x55, 0xb2, 0xb8, - 0x6a, 0x7c, 0x04, 0x9d, 0x14, 0x9d, 0x32, 0xaf, 0xfc, 0x1f, 0xa8, 0xb9, 0x26, 0x68, 0xd6, 0x72, - 0xc6, 0x23, 0xe5, 0x39, 0x40, 0xcc, 0x6d, 0xf3, 0xb6, 0xb2, 0xc2, 0x07, 0x06, 0x54, 0x18, 0x8d, - 0x3b, 0x31, 0x2a, 0x1d, 0x3c, 0x88, 0xd8, 0x56, 0x05, 0xd2, 0xbc, 0x5b, 0x10, 0xde, 0x56, 0x09, - 0x32, 0x02, 0x96, 0x00, 0xc9, 0x9b, 0xa9, 0xf0, 0xbc, 0x20, 0x86, 0x69, 0x84, 0x42, 0x73, 0x5d, - 0x5c, 0xd6, 0x16, 0x77, 0xc9, 0x7b, 0x5a, 0x74, 0x8f, 0xa4, 0xc5, 0x70, 0xc1, 0xff, 0x01, 0x9f, - 0xcb, 0x94, 0xce, 0xa8, 0x27, 0x5f, 0x02, 0x13, 0x2c, 0xff, 0x05, 0x32, 0xce, 0x48, 0x39, 0xf7, - 0x85, 0xb1, 0x98, 0xbf, 0x4e, 0x70, 0xbd, 0x6c, 0x7c, 0x06, 0x4f, 0xab, 0xc1, 0x6e, 0xf2, 0xcb, - 0x78, 0xba, 0x88, 0xd7, 0x5f, 0xc4, 0xbb, 0xc1, 0x57, 0x19, 0xd5, 0x20, 0xe6, 0x88, 0xce, 0x12, - 0x46, 0xbd, 0x18, 0xd2, 0xd8, 0xdc, 0xe8, 0x6b, 0x83, 0x0d, 0x39, 0x88, 0xae, 0xac, 0xef, 0x42, - 0x1a, 0x1b, 0x9b, 0xa0, 0x09, 0xb3, 0x4c, 0x5a, 0x5a, 0xc2, 0xd2, 0x80, 0x59, 0x26, 0xa4, 0x17, - 0xc5, 0xc1, 0x67, 0x39, 0x21, 0xc7, 0xd2, 0xf1, 0xa7, 0x21, 0x2c, 0x62, 0x54, 0xf6, 0x79, 0x99, - 0x1b, 0x9d, 0x4f, 0xe7, 0x73, 0x4b, 0xbb, 0x98, 0x5b, 0xda, 0xef, 0xb9, 0xa5, 0x9d, 0x5d, 0x59, - 0xb5, 0x8b, 0x2b, 0xab, 0xf6, 0xe3, 0xca, 0xaa, 0x7d, 0x79, 0x15, 0x61, 0x16, 0xcf, 0x7c, 0x3b, - 0x20, 0xd3, 0xe1, 0x07, 0x9c, 0xd2, 0x20, 0xc6, 0x70, 0x58, 0x3e, 0xc7, 0xf2, 0x11, 0xbf, 0xfe, - 0xf4, 0xfb, 0x6b, 0xa2, 0xfa, 0xfa, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x37, 0xe8, 0x57, 0xa5, - 0x13, 0x06, 0x00, 0x00, + // 694 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x94, 0x4f, 0x4f, 0xdb, 0x48, + 0x18, 0xc6, 0xe3, 0x0d, 0x90, 0x30, 0x26, 0xc9, 0xae, 0x77, 0x0f, 0x26, 0x6c, 0x9d, 0x94, 0xfe, + 0x8b, 0x7a, 0xb0, 0x55, 0x7a, 0xea, 0xa5, 0x52, 0x9d, 0xb4, 0x25, 0x2a, 0xaa, 0x90, 0x41, 0x1c, + 0x7a, 0xb1, 0xc6, 0xf6, 0x60, 0x8f, 0xea, 0xcc, 0x58, 0x9e, 0x09, 0xa2, 0x5f, 0xa1, 0x27, 0x3e, + 0x16, 0x47, 0x8e, 0x55, 0x0f, 0xb4, 0x0a, 0x97, 0x7e, 0x8c, 0x6a, 0x66, 0x6c, 0x63, 0x48, 0x91, + 0xb8, 0x4d, 0xde, 0xf7, 0x79, 0x7f, 0x79, 0x66, 0xe6, 0xf1, 0x80, 0x3e, 0x65, 0x3c, 0x87, 0x21, + 0x25, 0x0e, 0xe3, 0x90, 0x23, 0x87, 0x7f, 0xc9, 0x10, 0xb3, 0xb3, 0x9c, 0x72, 0x6a, 0x74, 0xcb, + 0x9e, 0x2d, 0x7b, 0xfd, 0xff, 0x62, 0x1a, 0x53, 0xd9, 0x72, 0xc4, 0x4a, 0xa9, 0xfa, 0x43, 0x8e, + 0x48, 0x84, 0xf2, 0x19, 0x26, 0x5c, 0x4d, 0x3b, 0x27, 0x30, 0xc5, 0x11, 0xe4, 0x34, 0x2f, 0x14, + 0x0f, 0x96, 0x14, 0x19, 0xcc, 0xe1, 0xac, 0xf8, 0x9b, 0xfe, 0xff, 0x4b, 0xed, 0x9a, 0x89, 0xfe, + 0x20, 0xa6, 0x34, 0x4e, 0x91, 0x23, 0x7f, 0x05, 0xf3, 0x63, 0x87, 0xe3, 0x19, 0x62, 0x1c, 0xce, + 0xb2, 0x3f, 0x8c, 0x2f, 0xed, 0xa1, 0xbf, 0x55, 0xeb, 0xc2, 0x20, 0xc4, 0xf5, 0xe6, 0xf6, 0x77, + 0x0d, 0x74, 0xde, 0xb8, 0xe3, 0xa9, 0x87, 0x58, 0x46, 0x09, 0x43, 0xcc, 0x18, 0x03, 0x3d, 0x42, + 0x29, 0x3e, 0x41, 0xb9, 0xcf, 0x4f, 0x99, 0xa9, 0x0d, 0x9b, 0x23, 0x7d, 0x67, 0xdb, 0xbe, 0x86, + 0xd8, 0x02, 0x62, 0x97, 0x03, 0x13, 0xa5, 0x3d, 0x3c, 0xf5, 0x40, 0x54, 0x2e, 0x99, 0xf1, 0x1a, + 0xac, 0x23, 0x12, 0xf9, 0x41, 0x4a, 0xc3, 0xcf, 0xe6, 0x5f, 0x43, 0x6d, 0xa4, 0xef, 0x3c, 0xbc, + 0x13, 0xf1, 0x96, 0x44, 0xae, 0x10, 0x7a, 0x6d, 0x54, 0xac, 0x8c, 0x09, 0xd0, 0x03, 0x14, 0x63, + 0x52, 0x10, 0x9a, 0x92, 0xf0, 0xe8, 0x4e, 0x82, 0x2b, 0xb4, 0x8a, 0x01, 0x82, 0x6a, 0xbd, 0xfd, + 0xb5, 0x05, 0x56, 0x0f, 0xc4, 0x79, 0x18, 0xaf, 0x40, 0xeb, 0x04, 0xe5, 0x0c, 0x53, 0x62, 0x6a, + 0x92, 0xb5, 0x59, 0x67, 0xc9, 0x33, 0xb3, 0x8f, 0x94, 0xc0, 0x5d, 0x39, 0xbf, 0x1c, 0x34, 0xbc, + 0x52, 0x6f, 0x3c, 0x05, 0xed, 0x30, 0x81, 0x98, 0xf8, 0x38, 0x92, 0x3b, 0x59, 0x77, 0xf5, 0xc5, + 0xe5, 0xa0, 0x35, 0x16, 0xb5, 0xe9, 0xc4, 0x6b, 0xc9, 0xe6, 0x34, 0x32, 0x9e, 0x80, 0x2e, 0x26, + 0x98, 0x63, 0x98, 0xfa, 0x09, 0xc2, 0x71, 0xc2, 0xcd, 0xee, 0x50, 0x1b, 0x35, 0xbd, 0x4e, 0x51, + 0xdd, 0x95, 0x45, 0xe3, 0x39, 0xf8, 0x27, 0x85, 0x8c, 0xab, 0x8d, 0x95, 0xca, 0xa6, 0x54, 0xf6, + 0x44, 0x43, 0x3a, 0x2f, 0xb4, 0x1e, 0xe8, 0xd4, 0xb4, 0x38, 0x32, 0x57, 0x96, 0xbd, 0xab, 0xcb, + 0x94, 0x53, 0xd3, 0x89, 0xfb, 0xaf, 0xf0, 0xbe, 0xb8, 0x1c, 0xe8, 0x7b, 0x25, 0x6a, 0x3a, 0xf1, + 0xf4, 0x8a, 0x3b, 0x8d, 0x8c, 0x3d, 0xd0, 0xab, 0x31, 0x45, 0x92, 0xcc, 0x55, 0x49, 0xed, 0xdb, + 0x2a, 0x66, 0x76, 0x19, 0x33, 0xfb, 0xb0, 0x8c, 0x99, 0xdb, 0x16, 0xd8, 0xb3, 0x1f, 0x03, 0xcd, + 0xeb, 0x54, 0x2c, 0xd1, 0x35, 0xde, 0x83, 0x1e, 0x41, 0xa7, 0xdc, 0xaf, 0xf2, 0xce, 0xcc, 0x35, + 0x49, 0xb3, 0x96, 0x3d, 0x1e, 0x95, 0x9a, 0x03, 0xc4, 0xbd, 0xae, 0x18, 0xab, 0x2a, 0x22, 0x30, + 0xa0, 0xc6, 0x68, 0xdd, 0x8b, 0x51, 0x9b, 0x10, 0x46, 0xe4, 0xb6, 0x6a, 0x90, 0xf6, 0xfd, 0x8c, + 0x88, 0xb1, 0x9a, 0x91, 0x31, 0xb0, 0x24, 0x48, 0xdd, 0x4c, 0x8d, 0xe7, 0x87, 0x09, 0x24, 0x31, + 0x8a, 0xcc, 0x75, 0x79, 0x59, 0x5b, 0x42, 0xa5, 0xee, 0xe9, 0x7a, 0x7a, 0xac, 0x24, 0x86, 0x07, + 0xfe, 0x0e, 0x45, 0x2e, 0x09, 0x9b, 0x33, 0x5f, 0x7d, 0xe9, 0x26, 0x58, 0xfe, 0x0a, 0x94, 0x9d, + 0x71, 0xa9, 0xdc, 0x97, 0xc2, 0x22, 0x7f, 0xbd, 0xf0, 0x66, 0xd9, 0xf8, 0x08, 0x1e, 0xd7, 0x8d, + 0xdd, 0xe6, 0x57, 0xf6, 0x74, 0x69, 0x6f, 0x78, 0x6d, 0xef, 0x16, 0xbf, 0xf4, 0x58, 0x06, 0x31, + 0x47, 0x6c, 0x9e, 0x72, 0xe6, 0x27, 0x90, 0x25, 0xe6, 0xc6, 0x50, 0x1b, 0x6d, 0xa8, 0x20, 0x7a, + 0xaa, 0xbe, 0x0b, 0x59, 0x62, 0x6c, 0x82, 0x36, 0xcc, 0x32, 0x25, 0xe9, 0x48, 0x49, 0x0b, 0x66, + 0x99, 0x6c, 0x3d, 0x2b, 0x0e, 0x3e, 0xcb, 0x29, 0x3d, 0x56, 0x8a, 0x5f, 0x2d, 0x29, 0x91, 0x51, + 0xd9, 0x17, 0x65, 0x21, 0x74, 0x3f, 0x9c, 0x2f, 0x2c, 0xed, 0x62, 0x61, 0x69, 0x3f, 0x17, 0x96, + 0x76, 0x76, 0x65, 0x35, 0x2e, 0xae, 0xac, 0xc6, 0xb7, 0x2b, 0xab, 0xf1, 0xe9, 0x45, 0x8c, 0x79, + 0x32, 0x0f, 0xec, 0x90, 0xce, 0x9c, 0x77, 0x98, 0xb0, 0x30, 0xc1, 0xd0, 0xa9, 0x1e, 0x65, 0xf5, + 0xda, 0xde, 0x7c, 0xa3, 0x83, 0x35, 0x59, 0x7d, 0xf9, 0x3b, 0x00, 0x00, 0xff, 0xff, 0x20, 0x46, + 0x0f, 0x5a, 0xbc, 0x05, 0x00, 0x00, } func (m *ABCIResponses) Marshal() (dAtA []byte, err error) { diff --git a/proto/ostracon/state/types.proto b/proto/ostracon/state/types.proto index 123588a3b..b192aed5f 100644 --- a/proto/ostracon/state/types.proto +++ b/proto/ostracon/state/types.proto @@ -4,12 +4,9 @@ package ostracon.state; option go_package = "github.com/Finschia/ostracon/proto/ostracon/state"; import "gogoproto/gogo.proto"; -import "ostracon/abci/types.proto"; -import "ostracon/types/types.proto"; import "tendermint/types/validator.proto"; import "tendermint/types/params.proto"; import "tendermint/types/types.proto"; -import "tendermint/version/types.proto"; import "google/protobuf/timestamp.proto"; import "tendermint/state/types.proto"; import "tendermint/abci/types.proto"; diff --git a/proxy/mocks/app_conn_consensus.go b/proxy/mocks/app_conn_consensus.go index 25b97a4ac..9e21d7154 100644 --- a/proxy/mocks/app_conn_consensus.go +++ b/proxy/mocks/app_conn_consensus.go @@ -155,13 +155,12 @@ func (_m *AppConnConsensus) SetGlobalCallback(_a0 abcicli.GlobalCallback) { _m.Called(_a0) } -type mockConstructorTestingTNewAppConnConsensus interface { +// NewAppConnConsensus creates a new instance of AppConnConsensus. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewAppConnConsensus(t interface { mock.TestingT Cleanup(func()) -} - -// NewAppConnConsensus creates a new instance of AppConnConsensus. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewAppConnConsensus(t mockConstructorTestingTNewAppConnConsensus) *AppConnConsensus { +}) *AppConnConsensus { mock := &AppConnConsensus{} mock.Mock.Test(t) diff --git a/proxy/mocks/app_conn_mempool.go b/proxy/mocks/app_conn_mempool.go index 42e8c2832..0e3d3958e 100644 --- a/proxy/mocks/app_conn_mempool.go +++ b/proxy/mocks/app_conn_mempool.go @@ -171,13 +171,12 @@ func (_m *AppConnMempool) SetGlobalCallback(_a0 abcicli.GlobalCallback) { _m.Called(_a0) } -type mockConstructorTestingTNewAppConnMempool interface { +// NewAppConnMempool creates a new instance of AppConnMempool. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewAppConnMempool(t interface { mock.TestingT Cleanup(func()) -} - -// NewAppConnMempool creates a new instance of AppConnMempool. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewAppConnMempool(t mockConstructorTestingTNewAppConnMempool) *AppConnMempool { +}) *AppConnMempool { mock := &AppConnMempool{} mock.Mock.Test(t) diff --git a/proxy/mocks/app_conn_query.go b/proxy/mocks/app_conn_query.go index 88ba96f8d..2fcd62802 100644 --- a/proxy/mocks/app_conn_query.go +++ b/proxy/mocks/app_conn_query.go @@ -105,13 +105,12 @@ func (_m *AppConnQuery) QuerySync(_a0 types.RequestQuery) (*types.ResponseQuery, return r0, r1 } -type mockConstructorTestingTNewAppConnQuery interface { +// NewAppConnQuery creates a new instance of AppConnQuery. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewAppConnQuery(t interface { mock.TestingT Cleanup(func()) -} - -// NewAppConnQuery creates a new instance of AppConnQuery. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewAppConnQuery(t mockConstructorTestingTNewAppConnQuery) *AppConnQuery { +}) *AppConnQuery { mock := &AppConnQuery{} mock.Mock.Test(t) diff --git a/proxy/mocks/app_conn_snapshot.go b/proxy/mocks/app_conn_snapshot.go index fab90afd4..5faa02689 100644 --- a/proxy/mocks/app_conn_snapshot.go +++ b/proxy/mocks/app_conn_snapshot.go @@ -131,13 +131,12 @@ func (_m *AppConnSnapshot) OfferSnapshotSync(_a0 types.RequestOfferSnapshot) (*t return r0, r1 } -type mockConstructorTestingTNewAppConnSnapshot interface { +// NewAppConnSnapshot creates a new instance of AppConnSnapshot. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewAppConnSnapshot(t interface { mock.TestingT Cleanup(func()) -} - -// NewAppConnSnapshot creates a new instance of AppConnSnapshot. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewAppConnSnapshot(t mockConstructorTestingTNewAppConnSnapshot) *AppConnSnapshot { +}) *AppConnSnapshot { mock := &AppConnSnapshot{} mock.Mock.Test(t) diff --git a/proxy/mocks/client_creator.go b/proxy/mocks/client_creator.go index 3c762a228..3e3869699 100644 --- a/proxy/mocks/client_creator.go +++ b/proxy/mocks/client_creator.go @@ -38,13 +38,12 @@ func (_m *ClientCreator) NewABCIClient() (abcicli.Client, error) { return r0, r1 } -type mockConstructorTestingTNewClientCreator interface { +// NewClientCreator creates a new instance of ClientCreator. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewClientCreator(t interface { mock.TestingT Cleanup(func()) -} - -// NewClientCreator creates a new instance of ClientCreator. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewClientCreator(t mockConstructorTestingTNewClientCreator) *ClientCreator { +}) *ClientCreator { mock := &ClientCreator{} mock.Mock.Test(t) diff --git a/rpc/client/mocks/client.go b/rpc/client/mocks/client.go index 6b49fc4e7..82ffc9de6 100644 --- a/rpc/client/mocks/client.go +++ b/rpc/client/mocks/client.go @@ -909,13 +909,12 @@ func (_m *Client) Validators(ctx context.Context, height *int64, page *int, perP return r0, r1 } -type mockConstructorTestingTNewClient interface { +// NewClient creates a new instance of Client. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewClient(t interface { mock.TestingT Cleanup(func()) -} - -// NewClient creates a new instance of Client. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewClient(t mockConstructorTestingTNewClient) *Client { +}) *Client { mock := &Client{} mock.Mock.Test(t) diff --git a/rpc/client/mocks/remote_client.go b/rpc/client/mocks/remote_client.go index 656202116..6fde92349 100644 --- a/rpc/client/mocks/remote_client.go +++ b/rpc/client/mocks/remote_client.go @@ -923,13 +923,12 @@ func (_m *RemoteClient) Validators(ctx context.Context, height *int64, page *int return r0, r1 } -type mockConstructorTestingTNewRemoteClient interface { +// NewRemoteClient creates a new instance of RemoteClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewRemoteClient(t interface { mock.TestingT Cleanup(func()) -} - -// NewRemoteClient creates a new instance of RemoteClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewRemoteClient(t mockConstructorTestingTNewRemoteClient) *RemoteClient { +}) *RemoteClient { mock := &RemoteClient{} mock.Mock.Test(t) diff --git a/rpc/client/rpc_test.go b/rpc/client/rpc_test.go index a0512296c..91c701d0e 100644 --- a/rpc/client/rpc_test.go +++ b/rpc/client/rpc_test.go @@ -391,7 +391,7 @@ func TestUnconfirmedTxs(t *testing.T) { assert.Equal(t, 1, res.Count) assert.Equal(t, 1, res.Total) - assert.Equal(t, mempool.TxsBytes(), res.TotalBytes) + assert.Equal(t, mempool.SizeBytes(), res.TotalBytes) assert.Exactly(t, types.Txs{tx}, types.Txs(res.Txs)) } @@ -425,7 +425,7 @@ func TestNumUnconfirmedTxs(t *testing.T) { assert.Equal(t, mempoolSize, res.Count) assert.Equal(t, mempoolSize, res.Total) - assert.Equal(t, mempool.TxsBytes(), res.TotalBytes) + assert.Equal(t, mempool.SizeBytes(), res.TotalBytes) } mempool.Flush() diff --git a/rpc/core/events.go b/rpc/core/events.go index 2a3cdcd07..ce70ef82c 100644 --- a/rpc/core/events.go +++ b/rpc/core/events.go @@ -12,6 +12,12 @@ import ( rpctypes "github.com/Finschia/ostracon/rpc/jsonrpc/types" ) +const ( + // maxQueryLength is the maximum length of a query string that will be + // accepted. This is just a safety check to avoid outlandish queries. + maxQueryLength = 512 +) + // Subscribe for events via WebSocket. // More: https://docs.tendermint.com/master/rpc/#/Websocket/subscribe func Subscribe(ctx *rpctypes.Context, query string) (*ctypes.ResultSubscribe, error) { @@ -21,6 +27,8 @@ func Subscribe(ctx *rpctypes.Context, query string) (*ctypes.ResultSubscribe, er return nil, fmt.Errorf("max_subscription_clients %d reached", env.Config.MaxSubscriptionClients) } else if env.EventBus.NumClientSubscriptions(addr) >= env.Config.MaxSubscriptionsPerClient { return nil, fmt.Errorf("max_subscriptions_per_client %d reached", env.Config.MaxSubscriptionsPerClient) + } else if len(query) > maxQueryLength { + return nil, errors.New("maximum query length exceeded") } env.Logger.Info("Subscribe to query", "remote", addr, "query", query) diff --git a/rpc/core/mempool.go b/rpc/core/mempool.go index 0555389f8..10ae27f24 100644 --- a/rpc/core/mempool.go +++ b/rpc/core/mempool.go @@ -38,19 +38,31 @@ func BroadcastTxAsync(ctx *rpctypes.Context, tx types.Tx) (*ctypes.ResultBroadca // DeliverTx result. // More: https://docs.tendermint.com/master/rpc/#/Tx/broadcast_tx_sync func BroadcastTxSync(ctx *rpctypes.Context, tx types.Tx) (*ctypes.ResultBroadcastTx, error) { - res, err := env.Mempool.CheckTxSync(tx, mempl.TxInfo{}) + resCh := make(chan *ocabci.Response, 1) + err := env.Mempool.CheckTxSync(tx, func(res *ocabci.Response) { + select { + case <-ctx.Context().Done(): + case resCh <- res: + } + + }, mempl.TxInfo{}) if err != nil { return nil, err } - r := res.GetCheckTx() - return &ctypes.ResultBroadcastTx{ - Code: r.Code, - Data: r.Data, - Log: r.Log, - Codespace: r.Codespace, - MempoolError: r.MempoolError, - Hash: tx.Hash(), - }, nil + + select { + case <-ctx.Context().Done(): + return nil, fmt.Errorf("broadcast confirmation not received: %w", ctx.Context().Err()) + case res := <-resCh: + r := res.GetCheckTx() + return &ctypes.ResultBroadcastTx{ + Code: r.Code, + Data: r.Data, + Log: r.Log, + Codespace: r.Codespace, + Hash: tx.Hash(), + }, nil + } } // BroadcastTxCommit returns with the responses from CheckTx and DeliverTx. @@ -80,53 +92,64 @@ func BroadcastTxCommit(ctx *rpctypes.Context, tx types.Tx) (*ctypes.ResultBroadc } }() - // Broadcast tx and check tx - checkTxResMsg, err := env.Mempool.CheckTxSync(tx, mempl.TxInfo{}) + // Broadcast tx and wait for CheckTx result + checkTxResCh := make(chan *ocabci.Response, 1) + err = env.Mempool.CheckTxSync(tx, func(res *ocabci.Response) { + select { + case <-ctx.Context().Done(): + case checkTxResCh <- res: + } + }, mempl.TxInfo{}) if err != nil { env.Logger.Error("Error on broadcastTxCommit", "err", err) return nil, fmt.Errorf("error on broadcastTxCommit: %v", err) } - checkTxRes := checkTxResMsg.GetCheckTx() - if checkTxRes.Code != ocabci.CodeTypeOK { - return &ctypes.ResultBroadcastTxCommit{ - CheckTx: *checkTxRes, - DeliverTx: abci.ResponseDeliverTx{}, - Hash: tx.Hash(), - }, nil - } - - // Wait for the tx to be included in a block or timeout. select { - case msg := <-deliverTxSub.Out(): // The tx was included in a block. - deliverTxRes := msg.Data().(types.EventDataTx) - return &ctypes.ResultBroadcastTxCommit{ - CheckTx: *checkTxRes, - DeliverTx: deliverTxRes.Result, - Hash: tx.Hash(), - Height: deliverTxRes.Height, - }, nil - case <-deliverTxSub.Cancelled(): - var reason string - if deliverTxSub.Err() == nil { - reason = "Ostracon exited" - } else { - reason = deliverTxSub.Err().Error() + case <-ctx.Context().Done(): + return nil, fmt.Errorf("broadcast confirmation not received: %w", ctx.Context().Err()) + case checkTxResMsg := <-checkTxResCh: + checkTxRes := checkTxResMsg.GetCheckTx() + if checkTxRes.Code != abci.CodeTypeOK { + return &ctypes.ResultBroadcastTxCommit{ + CheckTx: *checkTxRes, + DeliverTx: abci.ResponseDeliverTx{}, + Hash: tx.Hash(), + }, nil + } + + // Wait for the tx to be included in a block or timeout. + select { + case msg := <-deliverTxSub.Out(): // The tx was included in a block. + deliverTxRes := msg.Data().(types.EventDataTx) + return &ctypes.ResultBroadcastTxCommit{ + CheckTx: *checkTxRes, + DeliverTx: deliverTxRes.Result, + Hash: tx.Hash(), + Height: deliverTxRes.Height, + }, nil + case <-deliverTxSub.Cancelled(): + var reason string + if deliverTxSub.Err() == nil { + reason = "Tendermint exited" + } else { + reason = deliverTxSub.Err().Error() + } + err = fmt.Errorf("deliverTxSub was cancelled (reason: %s)", reason) + env.Logger.Error("Error on broadcastTxCommit", "err", err) + return &ctypes.ResultBroadcastTxCommit{ + CheckTx: *checkTxRes, + DeliverTx: abci.ResponseDeliverTx{}, + Hash: tx.Hash(), + }, err + case <-time.After(env.Config.TimeoutBroadcastTxCommit): + err = errors.New("timed out waiting for tx to be included in a block") + env.Logger.Error("Error on broadcastTxCommit", "err", err) + return &ctypes.ResultBroadcastTxCommit{ + CheckTx: *checkTxRes, + DeliverTx: abci.ResponseDeliverTx{}, + Hash: tx.Hash(), + }, err } - err = fmt.Errorf("deliverTxSub was cancelled (reason: %s)", reason) - env.Logger.Error("Error on broadcastTxCommit", "err", err) - return &ctypes.ResultBroadcastTxCommit{ - CheckTx: *checkTxRes, - DeliverTx: abci.ResponseDeliverTx{}, - Hash: tx.Hash(), - }, err - case <-time.After(env.Config.TimeoutBroadcastTxCommit): - err = errors.New("timed out waiting for tx to be included in a block") - env.Logger.Error("Error on broadcastTxCommit", "err", err) - return &ctypes.ResultBroadcastTxCommit{ - CheckTx: *checkTxRes, - DeliverTx: abci.ResponseDeliverTx{}, - Hash: tx.Hash(), - }, err } } @@ -141,7 +164,7 @@ func UnconfirmedTxs(ctx *rpctypes.Context, limitPtr *int) (*ctypes.ResultUnconfi return &ctypes.ResultUnconfirmedTxs{ Count: len(txs), Total: env.Mempool.Size(), - TotalBytes: env.Mempool.TxsBytes(), + TotalBytes: env.Mempool.SizeBytes(), Txs: txs}, nil } @@ -151,7 +174,7 @@ func NumUnconfirmedTxs(ctx *rpctypes.Context) (*ctypes.ResultUnconfirmedTxs, err return &ctypes.ResultUnconfirmedTxs{ Count: env.Mempool.Size(), Total: env.Mempool.Size(), - TotalBytes: env.Mempool.TxsBytes()}, nil + TotalBytes: env.Mempool.SizeBytes()}, nil } // CheckTx checks the transaction without executing it. The transaction won't diff --git a/rpc/core/mempool_test.go b/rpc/core/mempool_test.go new file mode 100644 index 000000000..fd7a9bf4e --- /dev/null +++ b/rpc/core/mempool_test.go @@ -0,0 +1,439 @@ +package core + +import ( + "context" + "errors" + "fmt" + ocabcicli "github.com/Finschia/ostracon/abci/client" + ocabci "github.com/Finschia/ostracon/abci/types" + "github.com/Finschia/ostracon/config" + "github.com/Finschia/ostracon/libs/log" + "github.com/Finschia/ostracon/mempool" + memv0 "github.com/Finschia/ostracon/mempool/v0" + "github.com/Finschia/ostracon/proxy/mocks" + ctypes "github.com/Finschia/ostracon/rpc/core/types" + rpctypes "github.com/Finschia/ostracon/rpc/jsonrpc/types" + "github.com/Finschia/ostracon/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + abci "github.com/tendermint/tendermint/abci/types" + "net/http" + "sync" + "testing" + "time" +) + +type ErrorAssertionFunc func(t assert.TestingT, theError error, contains string, msgAndArgs ...interface{}) bool + +func TestBroadcastTxAsync(t *testing.T) { + type args struct { + ctx *rpctypes.Context + tx types.Tx + } + tx := types.Tx{} + tests := []struct { + name string + args args + want *ctypes.ResultBroadcastTx + wantErr assert.ErrorAssertionFunc + err error + }{ + { + name: "success", + args: args{ + ctx: &rpctypes.Context{}, + tx: tx, + }, + want: &ctypes.ResultBroadcastTx{ + Code: abci.CodeTypeOK, + Data: nil, + Log: "", + Codespace: "", + MempoolError: "", + Hash: tx.Hash(), + }, + wantErr: assert.NoError, + err: nil, + }, + { + name: "failure: tx is same the one before", + args: args{ + ctx: &rpctypes.Context{}, + tx: tx, + }, + want: nil, + wantErr: assert.Error, + err: mempool.ErrTxInCache, + }, + } + env = &Environment{} + mockAppConnMempool := &mocks.AppConnMempool{} + mockAppConnMempool.On("SetGlobalCallback", mock.Anything) + mockAppConnMempool.On("CheckTxAsync", mock.Anything, mock.Anything).Return(&ocabcicli.ReqRes{}) + env.Mempool = memv0.NewCListMempool(config.TestConfig().Mempool, mockAppConnMempool, 0) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + mockAppConnMempool.On("Error").Return(tt.err).Once() + got, err := BroadcastTxAsync(tt.args.ctx, tt.args.tx) + if !tt.wantErr(t, err, fmt.Sprintf("BroadcastTxAsync(%v, %v)", tt.args.ctx, tt.args.tx)) { + return + } + assert.Equal(t, tt.err, err) + assert.Equalf(t, tt.want, got, "BroadcastTxAsync(%v, %v)", tt.args.ctx, tt.args.tx) + }) + } +} + +func TestBroadcastTxSync(t *testing.T) { + type args struct { + ctx *rpctypes.Context + tx types.Tx + } + tx := types.Tx{} + tests := []struct { + name string + args args + want *ctypes.ResultBroadcastTx + wantErr assert.ErrorAssertionFunc + err error + }{ + { + name: "success", + args: args{ + ctx: &rpctypes.Context{}, + tx: tx, + }, + want: &ctypes.ResultBroadcastTx{ + Code: ocabci.CodeTypeOK, + Data: nil, + Log: "", + Codespace: "", + MempoolError: "", + Hash: tx.Hash(), + }, + wantErr: assert.NoError, + err: nil, + }, + { + name: "failure: tx is same the one before", + args: args{ + ctx: &rpctypes.Context{}, + tx: tx, + }, + want: nil, + wantErr: assert.Error, + err: mempool.ErrTxInMap, + }, + } + env = &Environment{} + mockAppConnMempool := &mocks.AppConnMempool{} + mockAppConnMempool.On("SetGlobalCallback", mock.Anything) + mockAppConnMempool.On("CheckTxSync", mock.Anything).Return(&ocabci.ResponseCheckTx{}, nil) + env.Mempool = memv0.NewCListMempool(config.TestConfig().Mempool, mockAppConnMempool, 0) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + mockAppConnMempool.On("Error").Return(tt.err).Once() + got, err := BroadcastTxSync(tt.args.ctx, tt.args.tx) + if !tt.wantErr(t, err, fmt.Sprintf("BroadcastTxSync(%v, %v)", tt.args.ctx, tt.args.tx)) { + return + } + assert.Equal(t, tt.err, err) + assert.Equalf(t, tt.want, got, "BroadcastTxSync(%v, %v)", tt.args.ctx, tt.args.tx) + }) + } +} + +// TestBroadcastTxSyncWithCancelContextForCheckTxSync test in isolation from TestBroadcastTxSync since avoiding coexistence +func TestBroadcastTxSyncWithCancelContextForCheckTxSync(t *testing.T) { + type args struct { + ctx *rpctypes.Context + tx types.Tx + } + errContext, cancel := context.WithCancel(context.Background()) + defer cancel() // for safety to avoid memory leaks + req := &http.Request{} + req = req.WithContext(errContext) + errRpcContext := rpctypes.Context{HTTPReq: req} + tx := types.Tx{} + tests := []struct { + name string + args args + want *ctypes.ResultBroadcastTx + wantErr ErrorAssertionFunc + err error + }{ + { + name: "failure(non-deterministic test, retry please): interrupted by context", + args: args{ + ctx: &errRpcContext, + tx: tx, + }, + want: nil, + wantErr: assert.ErrorContains, + err: fmt.Errorf("broadcast confirmation not received: context canceled"), + }, + } + env = &Environment{} + mockAppConnMempool := &mocks.AppConnMempool{} + mockAppConnMempool.On("SetGlobalCallback", mock.Anything) + mockAppConnMempool.On("CheckTxSync", mock.Anything).Return( + &ocabci.ResponseCheckTx{Code: abci.CodeTypeOK}, nil).WaitUntil( + time.After(1000 * time.Millisecond)) // Wait calling the context cancel + mockAppConnMempool.On("Error").Return(nil) // Not to use tt.err + env.Mempool = memv0.NewCListMempool(config.TestConfig().Mempool, mockAppConnMempool, 0) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // cancel context for while doing `env.Mempool.CheckTxSync` + cancel() + wg := &sync.WaitGroup{} + wg.Add(1) + go func() { + got, err := BroadcastTxSync(tt.args.ctx, tt.args.tx) + if !tt.wantErr(t, err, tt.err.Error(), fmt.Sprintf("BroadcastTxSync(%v, %v)", tt.args.ctx, tt.args.tx)) { + wg.Done() + return + } + assert.Equalf(t, tt.want, got, "BroadcastTxSync(%v, %v)", tt.args.ctx, tt.args.tx) + wg.Done() + }() + wg.Wait() + }) + } +} + +func TestBroadcastTxCommit(t *testing.T) { + type args struct { + ctx *rpctypes.Context + tx types.Tx + } + height := int64(1) + tx := types.Tx{} + tx1 := types.Tx{1} + tests := []struct { + name string + args args + want *ctypes.ResultBroadcastTxCommit + wantErr assert.ErrorAssertionFunc + }{ + { + name: "success", + args: args{ + ctx: &rpctypes.Context{}, + tx: tx, + }, + want: &ctypes.ResultBroadcastTxCommit{ + CheckTx: ocabci.ResponseCheckTx{ + Code: abci.CodeTypeOK, + }, + DeliverTx: abci.ResponseDeliverTx{ + Code: abci.CodeTypeOK, + Data: tx, + }, + Hash: tx.Hash(), + Height: height, + }, + wantErr: assert.NoError, + }, + { + name: "success but CheckTxResponse is not OK", + args: args{ + ctx: &rpctypes.Context{}, + tx: tx1, + }, + want: &ctypes.ResultBroadcastTxCommit{ + CheckTx: ocabci.ResponseCheckTx{ + Code: abci.CodeTypeOK + 1, // Not OK + }, + DeliverTx: abci.ResponseDeliverTx{}, // return empty response + Hash: tx1.Hash(), + Height: 0, // return empty height + }, + wantErr: assert.NoError, + }, + } + env = &Environment{} + env.Logger = log.TestingLogger() + env.Config = *config.TestConfig().RPC + env.EventBus = types.NewEventBus() + err := env.EventBus.OnStart() + defer env.EventBus.OnStop() + assert.NoError(t, err) + mockAppConnMempool := &mocks.AppConnMempool{} + mockAppConnMempool.On("SetGlobalCallback", mock.Anything) + mockAppConnMempool.On("Error").Return(nil) + env.Mempool = memv0.NewCListMempool(config.TestConfig().Mempool, mockAppConnMempool, 0) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + mockAppConnMempool.On("CheckTxSync", mock.Anything).Return(&tt.want.CheckTx, nil).Once() + wg := &sync.WaitGroup{} + wg.Add(1) + go func() { + got, err := BroadcastTxCommit(tt.args.ctx, tt.args.tx) + if !tt.wantErr(t, err, fmt.Sprintf("BroadcastTxCommit(%v, %v)", tt.args.ctx, tt.args.tx)) { + wg.Done() + return + } + assert.Equalf(t, tt.want, got, "BroadcastTxCommit(%v, %v)", tt.args.ctx, tt.args.tx) + wg.Done() + }() + // Wait the time for `env.EventBus.Subscribe` in BroadcastTxCommit + time.Sleep(10 * time.Millisecond) + err := env.EventBus.PublishEventTx(types.EventDataTx{ + TxResult: abci.TxResult{ + Height: height, + Index: 0, + Tx: tt.args.tx, + Result: tt.want.DeliverTx, + }, + }) + assert.NoError(t, err) + wg.Wait() + }) + } +} + +func TestBroadcastTxCommitWithCancelContextForCheckTxSync(t *testing.T) { + type args struct { + ctx *rpctypes.Context + tx types.Tx + } + errContext, cancel := context.WithCancel(context.Background()) + defer cancel() // for safety to avoid memory leaks + req := &http.Request{} + req = req.WithContext(errContext) + errRpcContext := rpctypes.Context{HTTPReq: req} + height := int64(1) + tx := types.Tx{} + resCheckTx := ocabci.ResponseCheckTx{ + Code: abci.CodeTypeOK, + } + resDeliverTx := abci.ResponseDeliverTx{ + Code: abci.CodeTypeOK, + Data: tx, + } + tests := []struct { + name string + args args + want *ctypes.ResultBroadcastTxCommit + wantErr ErrorAssertionFunc + err error + }{ + { + name: "failure(non-deterministic test, retry please): interrupted by context", + args: args{ + ctx: &errRpcContext, + tx: tx, + }, + want: nil, + wantErr: assert.ErrorContains, + err: fmt.Errorf("broadcast confirmation not received: context canceled"), + }, + } + env = &Environment{} + env.Logger = log.TestingLogger() + env.Config = *config.TestConfig().RPC + env.EventBus = types.NewEventBus() + err := env.EventBus.OnStart() + defer env.EventBus.OnStop() + assert.NoError(t, err) + mockAppConnMempool := &mocks.AppConnMempool{} + mockAppConnMempool.On("SetGlobalCallback", mock.Anything) + mockAppConnMempool.On("Error").Return(nil) + mockAppConnMempool.On("CheckTxSync", mock.Anything).Return(&resCheckTx, nil).WaitUntil( + time.After(1 * time.Second)) // Wait calling the context cancel + env.Mempool = memv0.NewCListMempool(config.TestConfig().Mempool, mockAppConnMempool, 0) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + wg := &sync.WaitGroup{} + wg.Add(2) + go func() { + // Wait the time for `env.EventBus.Subscribe` in BroadcastTxCommit + time.Sleep(10 * time.Millisecond) + err := env.EventBus.PublishEventTx(types.EventDataTx{ + TxResult: abci.TxResult{ + Height: height, + Index: 0, + Tx: tx, + Result: resDeliverTx, + }, + }) + assert.NoError(t, err) + // cancel context for while doing `env.Mempool.CheckTxSync` + cancel() + wg.Done() + }() + go func() { + got, err := BroadcastTxCommit(tt.args.ctx, tt.args.tx) + if !tt.wantErr(t, err, tt.err.Error(), fmt.Sprintf("BroadcastTxCommit(%v, %v)", tt.args.ctx, tt.args.tx)) { + wg.Done() + return + } + assert.Equalf(t, tt.want, got, "BroadcastTxCommit(%v, %v)", tt.args.ctx, tt.args.tx) + wg.Done() + }() + wg.Wait() + }) + } +} + +func TestBroadcastTxCommitTimeout(t *testing.T) { + type args struct { + ctx *rpctypes.Context + tx types.Tx + } + tx := types.Tx{} + tests := []struct { + name string + args args + want *ctypes.ResultBroadcastTxCommit + wantErr ErrorAssertionFunc + err error + }{ + { + name: "failure: timeout", + args: args{ + ctx: &rpctypes.Context{}, + tx: tx, + }, + want: &ctypes.ResultBroadcastTxCommit{ + CheckTx: ocabci.ResponseCheckTx{ + Code: abci.CodeTypeOK, + }, + DeliverTx: abci.ResponseDeliverTx{}, // return empty response + Hash: tx.Hash(), + Height: 0, // return empty height + }, + wantErr: assert.ErrorContains, + err: errors.New("timed out waiting for tx to be included in a block"), + }, + } + env = &Environment{} + env.Logger = log.TestingLogger() + env.Config = *config.TestConfig().RPC + env.Config.TimeoutBroadcastTxCommit = 1 // For test + env.EventBus = types.NewEventBus() + err := env.EventBus.OnStart() + defer env.EventBus.OnStop() + assert.NoError(t, err) + mockAppConnMempool := &mocks.AppConnMempool{} + mockAppConnMempool.On("SetGlobalCallback", mock.Anything) + mockAppConnMempool.On("Error").Return(nil) + env.Mempool = memv0.NewCListMempool(config.TestConfig().Mempool, mockAppConnMempool, 0) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + mockAppConnMempool.On("CheckTxSync", mock.Anything).Return(&tt.want.CheckTx, nil).Once() + wg := &sync.WaitGroup{} + wg.Add(1) + go func() { + got, err := BroadcastTxCommit(tt.args.ctx, tt.args.tx) + if !tt.wantErr(t, err, tt.err.Error(), fmt.Sprintf("BroadcastTxCommit(%v, %v)", tt.args.ctx, tt.args.tx)) { + wg.Done() + return + } + assert.Equalf(t, tt.want, got, "BroadcastTxCommit(%v, %v)", tt.args.ctx, tt.args.tx) + wg.Done() + }() + wg.Wait() + }) + } +} diff --git a/rpc/core/tx.go b/rpc/core/tx.go index a80f24e5e..c30c2bb0a 100644 --- a/rpc/core/tx.go +++ b/rpc/core/tx.go @@ -65,6 +65,8 @@ func TxSearch( // if index is disabled, return error if _, ok := env.TxIndexer.(*null.TxIndex); ok { return nil, errors.New("transaction indexing is disabled") + } else if len(query) > maxQueryLength { + return nil, errors.New("maximum query length exceeded") } q, err := tmquery.New(query) diff --git a/rpc/jsonrpc/client/ws_client.go b/rpc/jsonrpc/client/ws_client.go index 03a3c40b6..11e44f065 100644 --- a/rpc/jsonrpc/client/ws_client.go +++ b/rpc/jsonrpc/client/ws_client.go @@ -12,6 +12,7 @@ import ( "github.com/gorilla/websocket" metrics "github.com/rcrowley/go-metrics" + "github.com/Finschia/ostracon/libs/log" tmrand "github.com/Finschia/ostracon/libs/rand" "github.com/Finschia/ostracon/libs/service" tmsync "github.com/Finschia/ostracon/libs/sync" @@ -511,7 +512,7 @@ func (c *WSClient) readRoutine() { // c.wg.Wait() in c.Stop(). Note we rely on Quit being closed so that it sends unlimited Quit signals to stop // both readRoutine and writeRoutine - c.Logger.Info("got response", "id", response.ID, "result", fmt.Sprintf("%X", response.Result)) + c.Logger.Info("got response", "id", response.ID, "result", log.NewLazySprintf("%X", response.Result)) select { case <-c.Quit(): diff --git a/rpc/jsonrpc/server/http_server.go b/rpc/jsonrpc/server/http_server.go index acbc7c67d..926f56a65 100644 --- a/rpc/jsonrpc/server/http_server.go +++ b/rpc/jsonrpc/server/http_server.go @@ -54,7 +54,7 @@ func DefaultConfig() *Config { // // NOTE: This function blocks - you may want to call it in a go-routine. func Serve(listener net.Listener, handler http.Handler, logger log.Logger, config *Config) error { - logger.Info(fmt.Sprintf("Starting RPC HTTP server on %s", listener.Addr())) + logger.Info("serve", "msg", log.NewLazySprintf("Starting RPC HTTP server on %s", listener.Addr())) s := &http.Server{ Handler: RecoverAndLogHandler(maxBytesHandler{h: handler, n: config.MaxBodyBytes}, logger), ReadTimeout: config.ReadTimeout, @@ -79,7 +79,7 @@ func ServeTLS( logger log.Logger, config *Config, ) error { - logger.Info(fmt.Sprintf("Starting RPC HTTPS server on %s (cert: %q, key: %q)", + logger.Info("serve tls", "msg", log.NewLazySprintf("Starting RPC HTTPS server on %s (cert: %q, key: %q)", listener.Addr(), certFile, keyFile)) s := &http.Server{ Handler: RecoverAndLogHandler(maxBytesHandler{h: handler, n: config.MaxBodyBytes}, logger), diff --git a/scripts/proto-gen.sh b/scripts/proto-gen.sh new file mode 100755 index 000000000..06fa07dd9 --- /dev/null +++ b/scripts/proto-gen.sh @@ -0,0 +1,19 @@ +#!/bin/sh +# +# Update the generated code for protocol buffers in the Tendermint repository. +# This must be run from inside a Tendermint working directory. +# +set -euo pipefail + +# Work from the root of the repository. +cd "$(git rev-parse --show-toplevel)" + +# Run inside Docker to install the correct versions of the required tools +# without polluting the local system. +docker run --rm -i -v "$PWD":/w --workdir=/w golang:1.18-alpine sh <<"EOF" +apk add git make + +go install github.com/bufbuild/buf/cmd/buf +go install github.com/gogo/protobuf/protoc-gen-gogofaster@latest +make proto-gen +EOF diff --git a/scripts/protocgen.sh b/scripts/protocgen.sh deleted file mode 100755 index 50e0c8f8c..000000000 --- a/scripts/protocgen.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash - -set -eo pipefail - -proto_dirs=$(find ./proto -path -prune -o -name '*.proto' -print0 | xargs -0 -n1 dirname | sort | uniq) -for dir in $proto_dirs; do - buf protoc \ - -I "proto" \ - -I "third_party/proto" \ - --gogofaster_out=\ -Mgoogle/protobuf/timestamp.proto=github.com/gogo/protobuf/types,\ -Mgoogle/protobuf/duration.proto=github.com/golang/protobuf/ptypes/duration,\ -plugins=grpc,paths=source_relative:. \ - $(find "${dir}" -maxdepth 1 -name '*.proto') -done - -cp -r ./ostracon/* ./proto/* -rm -rf ostracon - -mv ./proto/ostracon/abci/types.pb.go ./abci/types - -mv ./proto/ostracon/rpc/grpc/types.pb.go ./rpc/grpc diff --git a/state/mocks/block_store.go b/state/mocks/block_store.go index 8c05d338f..892d26818 100644 --- a/state/mocks/block_store.go +++ b/state/mocks/block_store.go @@ -196,13 +196,12 @@ func (_m *BlockStore) Size() int64 { return r0 } -type mockConstructorTestingTNewBlockStore interface { +// NewBlockStore creates a new instance of BlockStore. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewBlockStore(t interface { mock.TestingT Cleanup(func()) -} - -// NewBlockStore creates a new instance of BlockStore. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewBlockStore(t mockConstructorTestingTNewBlockStore) *BlockStore { +}) *BlockStore { mock := &BlockStore{} mock.Mock.Test(t) diff --git a/state/mocks/evidence_pool.go b/state/mocks/evidence_pool.go index 423dfcfbd..5c562c45c 100644 --- a/state/mocks/evidence_pool.go +++ b/state/mocks/evidence_pool.go @@ -73,13 +73,12 @@ func (_m *EvidencePool) Update(_a0 state.State, _a1 types.EvidenceList) { _m.Called(_a0, _a1) } -type mockConstructorTestingTNewEvidencePool interface { +// NewEvidencePool creates a new instance of EvidencePool. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewEvidencePool(t interface { mock.TestingT Cleanup(func()) -} - -// NewEvidencePool creates a new instance of EvidencePool. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewEvidencePool(t mockConstructorTestingTNewEvidencePool) *EvidencePool { +}) *EvidencePool { mock := &EvidencePool{} mock.Mock.Test(t) diff --git a/state/mocks/store.go b/state/mocks/store.go index 584988898..3f29ed535 100644 --- a/state/mocks/store.go +++ b/state/mocks/store.go @@ -261,13 +261,12 @@ func (_m *Store) SaveABCIResponses(_a0 int64, _a1 *ostraconstate.ABCIResponses) return r0 } -type mockConstructorTestingTNewStore interface { +// NewStore creates a new instance of Store. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewStore(t interface { mock.TestingT Cleanup(func()) -} - -// NewStore creates a new instance of Store. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewStore(t mockConstructorTestingTNewStore) *Store { +}) *Store { mock := &Store{} mock.Mock.Test(t) diff --git a/state/txindex/mocks/tx_indexer.go b/state/txindex/mocks/tx_indexer.go index 0217b5c37..8ec713101 100644 --- a/state/txindex/mocks/tx_indexer.go +++ b/state/txindex/mocks/tx_indexer.go @@ -98,13 +98,12 @@ func (_m *TxIndexer) Search(ctx context.Context, q *query.Query) ([]*types.TxRes return r0, r1 } -type mockConstructorTestingTNewTxIndexer interface { +// NewTxIndexer creates a new instance of TxIndexer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewTxIndexer(t interface { mock.TestingT Cleanup(func()) -} - -// NewTxIndexer creates a new instance of TxIndexer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewTxIndexer(t mockConstructorTestingTNewTxIndexer) *TxIndexer { +}) *TxIndexer { mock := &TxIndexer{} mock.Mock.Test(t) diff --git a/statesync/mocks/state_provider.go b/statesync/mocks/state_provider.go index 7a3aedd80..ad29a5e5f 100644 --- a/statesync/mocks/state_provider.go +++ b/statesync/mocks/state_provider.go @@ -92,13 +92,12 @@ func (_m *StateProvider) State(ctx context.Context, height uint64) (state.State, return r0, r1 } -type mockConstructorTestingTNewStateProvider interface { +// NewStateProvider creates a new instance of StateProvider. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewStateProvider(t interface { mock.TestingT Cleanup(func()) -} - -// NewStateProvider creates a new instance of StateProvider. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewStateProvider(t mockConstructorTestingTNewStateProvider) *StateProvider { +}) *StateProvider { mock := &StateProvider{} mock.Mock.Test(t) diff --git a/statesync/syncer.go b/statesync/syncer.go index d87e32be2..36e298e59 100644 --- a/statesync/syncer.go +++ b/statesync/syncer.go @@ -145,7 +145,7 @@ func (s *syncer) SyncAny(discoveryTime time.Duration, retryHook func()) (sm.Stat } if discoveryTime > 0 { - s.logger.Info(fmt.Sprintf("Discovering snapshots for %v", discoveryTime)) + s.logger.Info("sync any", "msg", log.NewLazySprintf("Discovering snapshots for %v", discoveryTime)) time.Sleep(discoveryTime) } @@ -167,7 +167,7 @@ func (s *syncer) SyncAny(discoveryTime time.Duration, retryHook func()) (sm.Stat return sm.State{}, sm.State{}, nil, errNoSnapshots } retryHook() - s.logger.Info(fmt.Sprintf("Discovering snapshots for %v", discoveryTime)) + s.logger.Info("sync any", "msg", log.NewLazySprintf("Discovering snapshots for %v", discoveryTime)) time.Sleep(discoveryTime) continue } diff --git a/test/e2e/generator/generate.go b/test/e2e/generator/generate.go index 6baa3287f..bcdc8a5ee 100644 --- a/test/e2e/generator/generate.go +++ b/test/e2e/generator/generate.go @@ -34,6 +34,7 @@ var ( // FIXME: v2 disabled due to flake nodeFastSyncs = uniformChoice{"v0"} // "v2" nodeStateSyncs = uniformChoice{false, true} + nodeMempools = uniformChoice{"v0", "v1"} nodePersistIntervals = uniformChoice{0, 1, 5} nodeSnapshotIntervals = uniformChoice{0, 3} nodeRetainBlocks = uniformChoice{ @@ -225,6 +226,7 @@ func generateNode( Database: nodeDatabases.Choose(r).(string), PrivvalProtocol: nodePrivvalProtocols.Choose(r).(string), FastSync: nodeFastSyncs.Choose(r).(string), + Mempool: nodeMempools.Choose(r).(string), StateSync: nodeStateSyncs.Choose(r).(bool) && startAt > 0, PersistInterval: ptrUint64(uint64(nodePersistIntervals.Choose(r).(int))), SnapshotInterval: uint64(nodeSnapshotIntervals.Choose(r).(int)), diff --git a/test/e2e/networks/ci.toml b/test/e2e/networks/ci.toml index 0301b7893..5ad599fc8 100644 --- a/test/e2e/networks/ci.toml +++ b/test/e2e/networks/ci.toml @@ -64,7 +64,7 @@ start_at = 1005 # Becomes part of the validator set at 1010 persistent_peers = ["validator01", "full01"] database = "cleveldb" fast_sync = "v0" -mempool_version = "v1" +mempool_version = "v0" # Deprecated mempool-v1 privval_protocol = "tcp" perturb = ["kill", "pause", "disconnect", "restart"] diff --git a/test/e2e/pkg/manifest.go b/test/e2e/pkg/manifest.go index 6dfb7642b..0dab0d708 100644 --- a/test/e2e/pkg/manifest.go +++ b/test/e2e/pkg/manifest.go @@ -111,6 +111,10 @@ type ManifestNode struct { // Defaults to disabled. FastSync string `toml:"fast_sync"` + // Mempool specifies which version of mempool to use. Either "v0" or "v1" + // This defaults to v0. + Mempool string `toml:"mempool_version"` + // StateSync enables state sync. The runner automatically configures trusted // block hashes and RPC servers. At least one node in the network must have // SnapshotInterval set to non-zero, and the state syncing node must have diff --git a/test/e2e/pkg/testnet.go b/test/e2e/pkg/testnet.go index 22dac9de2..d0a7104f9 100644 --- a/test/e2e/pkg/testnet.go +++ b/test/e2e/pkg/testnet.go @@ -88,6 +88,7 @@ type Node struct { StartAt int64 FastSync string StateSync bool + Mempool string Database string ABCIProtocol Protocol PrivvalProtocol Protocol @@ -184,6 +185,7 @@ func LoadTestnet(manifest Manifest, fname string, ifd InfrastructureData) (*Test PrivvalProtocol: ProtocolFile, StartAt: nodeManifest.StartAt, FastSync: nodeManifest.FastSync, + Mempool: nodeManifest.Mempool, StateSync: nodeManifest.StateSync, PersistInterval: 1, SnapshotInterval: nodeManifest.SnapshotInterval, @@ -329,6 +331,12 @@ func (n Node) Validate(testnet Testnet) error { case "", "v0", "v1", "v2": default: return fmt.Errorf("invalid fast sync setting %q", n.FastSync) + + } + switch n.Mempool { + case "", "v0", "v1": + default: + return fmt.Errorf("invalid mempool version %q", n.Mempool) } switch n.Database { case "goleveldb", "cleveldb", "boltdb", "rocksdb", "badgerdb": diff --git a/test/e2e/runner/load.go b/test/e2e/runner/load.go index fff08c924..acd2a8673 100644 --- a/test/e2e/runner/load.go +++ b/test/e2e/runner/load.go @@ -36,7 +36,7 @@ func Load(ctx context.Context, testnet *e2e.Testnet, multiplier int) error { defer cancel() // Spawn job generator and processors. - logger.Info(fmt.Sprintf("Starting transaction load (%v workers)...", concurrency)) + logger.Info("load", "msg", log.NewLazySprintf("Starting transaction load (%v workers)...", concurrency)) started := time.Now() go loadGenerate(ctx, chTx, multiplier) diff --git a/test/e2e/runner/setup.go b/test/e2e/runner/setup.go index d44a9e00f..d50012283 100644 --- a/test/e2e/runner/setup.go +++ b/test/e2e/runner/setup.go @@ -209,6 +209,9 @@ func MakeConfig(node *e2e.Node) (*config.Config, error) { default: return nil, fmt.Errorf("unexpected mode %q", node.Mode) } + if node.Mempool != "" { + cfg.Mempool.Version = node.Mempool + } if node.FastSync == "" { cfg.FastSyncMode = false diff --git a/test/fuzz/mempool/checktx.go b/test/fuzz/mempool/v0/checktx.go similarity index 75% rename from test/fuzz/mempool/checktx.go rename to test/fuzz/mempool/v0/checktx.go index 31c139ee7..eb871b87d 100644 --- a/test/fuzz/mempool/checktx.go +++ b/test/fuzz/mempool/v0/checktx.go @@ -1,9 +1,10 @@ -package checktx +package v0 import ( "github.com/Finschia/ostracon/abci/example/kvstore" "github.com/Finschia/ostracon/config" mempl "github.com/Finschia/ostracon/mempool" + mempoolv0 "github.com/Finschia/ostracon/mempool/v0" "github.com/Finschia/ostracon/proxy" ) @@ -20,12 +21,11 @@ func init() { cfg := config.DefaultMempoolConfig() cfg.Broadcast = false - - mempool = mempl.NewCListMempool(cfg, appConnMem, 0) + mempool = mempoolv0.NewCListMempool(cfg, appConnMem, 0) } func Fuzz(data []byte) int { - _, err := mempool.CheckTxSync(data, mempl.TxInfo{}) + err := mempool.CheckTxSync(data, nil, mempl.TxInfo{}) if err != nil { return 0 } diff --git a/test/fuzz/mempool/v0/fuzz_test.go b/test/fuzz/mempool/v0/fuzz_test.go new file mode 100644 index 000000000..9a32bbf04 --- /dev/null +++ b/test/fuzz/mempool/v0/fuzz_test.go @@ -0,0 +1,34 @@ +package v0_test + +import ( + "io/ioutil" + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/require" + + mempoolv0 "github.com/Finschia/ostracon/test/fuzz/mempool/v0" +) + +const testdataCasesDir = "testdata/cases" + +func TestMempoolTestdataCases(t *testing.T) { + entries, err := os.ReadDir(testdataCasesDir) + require.NoError(t, err) + + for _, e := range entries { + entry := e + t.Run(entry.Name(), func(t *testing.T) { + defer func() { + r := recover() + require.Nilf(t, r, "testdata/cases test panic") + }() + f, err := os.Open(filepath.Join(testdataCasesDir, entry.Name())) + require.NoError(t, err) + input, err := ioutil.ReadAll(f) + require.NoError(t, err) + mempoolv0.Fuzz(input) + }) + } +} diff --git a/test/fuzz/mempool/v0/testdata/cases/empty b/test/fuzz/mempool/v0/testdata/cases/empty new file mode 100644 index 000000000..e69de29bb diff --git a/test/fuzz/mempool/v1/checktx.go b/test/fuzz/mempool/v1/checktx.go new file mode 100644 index 000000000..0e4a66fca --- /dev/null +++ b/test/fuzz/mempool/v1/checktx.go @@ -0,0 +1,39 @@ +//go:build deprecated + +package v1 + +import ( + "github.com/tendermint/tendermint/abci/example/kvstore" + "github.com/tendermint/tendermint/config" + "github.com/tendermint/tendermint/libs/log" + mempl "github.com/tendermint/tendermint/mempool" + "github.com/tendermint/tendermint/proxy" + + mempoolv1 "github.com/tendermint/tendermint/mempool/v1" +) + +var mempool mempl.Mempool + +func init() { + app := kvstore.NewApplication() + cc := proxy.NewLocalClientCreator(app) + appConnMem, _ := cc.NewABCIClient() + err := appConnMem.Start() + if err != nil { + panic(err) + } + cfg := config.DefaultMempoolConfig() + cfg.Broadcast = false + log := log.NewNopLogger() + mempool = mempoolv1.NewTxMempool(log, cfg, appConnMem, 0) +} + +func Fuzz(data []byte) int { + + err := mempool.CheckTx(data, nil, mempl.TxInfo{}) + if err != nil { + return 0 + } + + return 1 +} diff --git a/test/fuzz/mempool/v1/fuzz_test.go b/test/fuzz/mempool/v1/fuzz_test.go new file mode 100644 index 000000000..6371f09a9 --- /dev/null +++ b/test/fuzz/mempool/v1/fuzz_test.go @@ -0,0 +1,35 @@ +//go:build deprecated + +package v1_test + +import ( + "io/ioutil" + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/require" + mempoolv1 "github.com/tendermint/tendermint/test/fuzz/mempool/v1" +) + +const testdataCasesDir = "testdata/cases" + +func TestMempoolTestdataCases(t *testing.T) { + entries, err := os.ReadDir(testdataCasesDir) + require.NoError(t, err) + + for _, e := range entries { + entry := e + t.Run(entry.Name(), func(t *testing.T) { + defer func() { + r := recover() + require.Nilf(t, r, "testdata/cases test panic") + }() + f, err := os.Open(filepath.Join(testdataCasesDir, entry.Name())) + require.NoError(t, err) + input, err := ioutil.ReadAll(f) + require.NoError(t, err) + mempoolv1.Fuzz(input) + }) + } +} diff --git a/test/fuzz/mempool/v1/testdata/cases/empty b/test/fuzz/mempool/v1/testdata/cases/empty new file mode 100644 index 000000000..e69de29bb diff --git a/third_party/proto/README.md b/third_party/proto/README.md new file mode 100644 index 000000000..ae2419cdb --- /dev/null +++ b/third_party/proto/README.md @@ -0,0 +1,16 @@ +# Using buf build +https://buf.build/ + +```script +go run github.com/bufbuild/buf/cmd/buf help +``` + +## if you update `buf.yaml`, should also update `buf.lock` +```script +cd third_party/proto && go run github.com/bufbuild/buf/cmd/buf mod update && cd ../.. +``` + +## NOTE +If tendermint use `BSR: Buf Schema Registry`, can remove `tendermint` +Currently, coping `tendermint-v0.34.19` proto files +See: `go.mod` diff --git a/third_party/proto/buf.lock b/third_party/proto/buf.lock new file mode 100644 index 000000000..768ad21ce --- /dev/null +++ b/third_party/proto/buf.lock @@ -0,0 +1,8 @@ +# Generated by buf. DO NOT EDIT. +version: v1 +deps: + - remote: buf.build + owner: gogo + repository: protobuf + commit: 5461a3dfa9d941da82028ab185dc2a0e + digest: shake256:37c7c75224982038cb1abf45b481ef06716c1f806ffaa162018d0df092bd11a2a9b62c2d0dc0a2ae43beff86b6014fc0eb8c594ffd84d52ade4b08fca901eadc diff --git a/third_party/proto/buf.yaml b/third_party/proto/buf.yaml new file mode 100644 index 000000000..816db10f7 --- /dev/null +++ b/third_party/proto/buf.yaml @@ -0,0 +1,11 @@ +version: v1 +deps: + - buf.build/gogo/protobuf +breaking: + use: + - FILE +lint: + use: + - BASIC + - FILE_LOWER_SNAKE_CASE + - UNARY_RPC diff --git a/third_party/proto/gogoproto/gogo.proto b/third_party/proto/gogoproto/gogo.proto deleted file mode 100644 index 27960ecfb..000000000 --- a/third_party/proto/gogoproto/gogo.proto +++ /dev/null @@ -1,147 +0,0 @@ -// Protocol Buffers for Go with Gadgets -// -// Copied from https://github.com/gogo/protobuf/blob/master/gogoproto/gogo.proto -// -// Copyright (c) 2013, The GoGo Authors. All rights reserved. -// http://github.com/gogo/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -syntax = "proto2"; -package gogoproto; - -import "google/protobuf/descriptor.proto"; - -option java_package = "com.google.protobuf"; -option java_outer_classname = "GoGoProtos"; -option go_package = "github.com/gogo/protobuf/gogoproto"; - -extend google.protobuf.EnumOptions { - optional bool goproto_enum_prefix = 62001; - optional bool goproto_enum_stringer = 62021; - optional bool enum_stringer = 62022; - optional string enum_customname = 62023; - optional bool enumdecl = 62024; -} - -extend google.protobuf.EnumValueOptions { - optional string enumvalue_customname = 66001; -} - -extend google.protobuf.FileOptions { - optional bool goproto_getters_all = 63001; - optional bool goproto_enum_prefix_all = 63002; - optional bool goproto_stringer_all = 63003; - optional bool verbose_equal_all = 63004; - optional bool face_all = 63005; - optional bool gostring_all = 63006; - optional bool populate_all = 63007; - optional bool stringer_all = 63008; - optional bool onlyone_all = 63009; - - optional bool equal_all = 63013; - optional bool description_all = 63014; - optional bool testgen_all = 63015; - optional bool benchgen_all = 63016; - optional bool marshaler_all = 63017; - optional bool unmarshaler_all = 63018; - optional bool stable_marshaler_all = 63019; - - optional bool sizer_all = 63020; - - optional bool goproto_enum_stringer_all = 63021; - optional bool enum_stringer_all = 63022; - - optional bool unsafe_marshaler_all = 63023; - optional bool unsafe_unmarshaler_all = 63024; - - optional bool goproto_extensions_map_all = 63025; - optional bool goproto_unrecognized_all = 63026; - optional bool gogoproto_import = 63027; - optional bool protosizer_all = 63028; - optional bool compare_all = 63029; - optional bool typedecl_all = 63030; - optional bool enumdecl_all = 63031; - - optional bool goproto_registration = 63032; - optional bool messagename_all = 63033; - - optional bool goproto_sizecache_all = 63034; - optional bool goproto_unkeyed_all = 63035; -} - -extend google.protobuf.MessageOptions { - optional bool goproto_getters = 64001; - optional bool goproto_stringer = 64003; - optional bool verbose_equal = 64004; - optional bool face = 64005; - optional bool gostring = 64006; - optional bool populate = 64007; - optional bool stringer = 67008; - optional bool onlyone = 64009; - - optional bool equal = 64013; - optional bool description = 64014; - optional bool testgen = 64015; - optional bool benchgen = 64016; - optional bool marshaler = 64017; - optional bool unmarshaler = 64018; - optional bool stable_marshaler = 64019; - - optional bool sizer = 64020; - - optional bool unsafe_marshaler = 64023; - optional bool unsafe_unmarshaler = 64024; - - optional bool goproto_extensions_map = 64025; - optional bool goproto_unrecognized = 64026; - - optional bool protosizer = 64028; - optional bool compare = 64029; - - optional bool typedecl = 64030; - - optional bool messagename = 64033; - - optional bool goproto_sizecache = 64034; - optional bool goproto_unkeyed = 64035; -} - -extend google.protobuf.FieldOptions { - optional bool nullable = 65001; - optional bool embed = 65002; - optional string customtype = 65003; - optional string customname = 65004; - optional string jsontag = 65005; - optional string moretags = 65006; - optional string casttype = 65007; - optional string castkey = 65008; - optional string castvalue = 65009; - - optional bool stdtime = 65010; - optional bool stdduration = 65011; - optional bool wktpointer = 65012; - - optional string castrepeated = 65013; -} \ No newline at end of file diff --git a/third_party/proto/tendermint/abci/types.proto b/third_party/proto/tendermint/abci/types.proto index 8e3a90936..23a6ec2e3 100644 --- a/third_party/proto/tendermint/abci/types.proto +++ b/third_party/proto/tendermint/abci/types.proto @@ -75,10 +75,10 @@ message RequestQuery { } message RequestBeginBlock { - bytes hash = 1; - tendermint.types.Header header = 2 [(gogoproto.nullable) = false]; - LastCommitInfo last_commit_info = 3 [(gogoproto.nullable) = false]; - repeated Evidence byzantine_validators = 4 [(gogoproto.nullable) = false]; + bytes hash = 1; + tendermint.types.Header header = 2 [(gogoproto.nullable) = false]; + LastCommitInfo last_commit_info = 3 [(gogoproto.nullable) = false]; + repeated Evidence byzantine_validators = 4 [(gogoproto.nullable) = false]; } enum CheckTxType { @@ -102,8 +102,7 @@ message RequestEndBlock { message RequestCommit {} // lists available snapshots -message RequestListSnapshots { -} +message RequestListSnapshots {} // offers a snapshot to the application message RequestOfferSnapshot { @@ -212,6 +211,12 @@ message ResponseCheckTx { repeated Event events = 7 [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; string codespace = 8; + string sender = 9; + int64 priority = 10; + + // mempool_error is set by Tendermint. + // ABCI applictions creating a ResponseCheckTX should not set mempool_error. + string mempool_error = 11; } message ResponseDeliverTx { @@ -221,16 +226,17 @@ message ResponseDeliverTx { string info = 4; // nondeterministic int64 gas_wanted = 5 [json_name = "gas_wanted"]; int64 gas_used = 6 [json_name = "gas_used"]; - repeated Event events = 7 - [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; // nondeterministic + repeated Event events = 7 [ + (gogoproto.nullable) = false, + (gogoproto.jsontag) = "events,omitempty" + ]; // nondeterministic string codespace = 8; } message ResponseEndBlock { - repeated ValidatorUpdate validator_updates = 1 - [(gogoproto.nullable) = false]; - ConsensusParams consensus_param_updates = 2; - repeated Event events = 3 + repeated ValidatorUpdate validator_updates = 1 [(gogoproto.nullable) = false]; + ConsensusParams consensus_param_updates = 2; + repeated Event events = 3 [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; } @@ -364,10 +370,8 @@ message Evidence { // The height when the offense occurred int64 height = 3; // The corresponding time where the offense occurred - google.protobuf.Timestamp time = 4 [ - (gogoproto.nullable) = false, - (gogoproto.stdtime) = true - ]; + google.protobuf.Timestamp time = 4 + [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; // Total voting power of the validator set in case the ABCI application does // not store historical validators. // https://github.com/tendermint/tendermint/issues/4581 @@ -402,6 +406,8 @@ service ABCIApplication { rpc EndBlock(RequestEndBlock) returns (ResponseEndBlock); rpc ListSnapshots(RequestListSnapshots) returns (ResponseListSnapshots); rpc OfferSnapshot(RequestOfferSnapshot) returns (ResponseOfferSnapshot); - rpc LoadSnapshotChunk(RequestLoadSnapshotChunk) returns (ResponseLoadSnapshotChunk); - rpc ApplySnapshotChunk(RequestApplySnapshotChunk) returns (ResponseApplySnapshotChunk); + rpc LoadSnapshotChunk(RequestLoadSnapshotChunk) + returns (ResponseLoadSnapshotChunk); + rpc ApplySnapshotChunk(RequestApplySnapshotChunk) + returns (ResponseApplySnapshotChunk); } diff --git a/types/tx.go b/types/tx.go index b6d767b9a..308a999cd 100644 --- a/types/tx.go +++ b/types/tx.go @@ -2,6 +2,7 @@ package types import ( "bytes" + "crypto/sha256" "errors" "fmt" @@ -12,16 +13,28 @@ import ( tmbytes "github.com/Finschia/ostracon/libs/bytes" ) -// Tx is an arbitrary byte array. -// NOTE: Tx has no types at this level, so when wire encoded it's just length-prefixed. -// Might we want types here ? -type Tx []byte +// TxKeySize is the size of the transaction key index +const TxKeySize = sha256.Size + +type ( + // Tx is an arbitrary byte array. + // NOTE: Tx has no types at this level, so when wire encoded it's just length-prefixed. + // Might we want types here ? + Tx []byte + + // TxKey is the fixed length array key used as an index. + TxKey [TxKeySize]byte +) // Hash computes the OCHASH hash of the wire encoded transaction. func (tx Tx) Hash() []byte { return tmhash.Sum(tx) } +func (tx Tx) Key() TxKey { + return sha256.Sum256(tx) +} + // String returns the hex-encoded transaction as a string. func (tx Tx) String() string { return fmt.Sprintf("Tx{%X}", []byte(tx))