mirror of
https://github.com/planetmint/planetmint-go.git
synced 2025-03-30 15:08:28 +00:00
Compare commits
174 Commits
lib/v0.2.1
...
main
Author | SHA1 | Date | |
---|---|---|---|
![]() |
1dce252617 | ||
![]() |
9ea03441d8 | ||
![]() |
f6c9af77c0 | ||
![]() |
41b5bf545f | ||
![]() |
75cb64de68 | ||
![]() |
aec55171f9 | ||
![]() |
90381166e6 | ||
![]() |
de1546ebe3 | ||
![]() |
8e87cd77db | ||
![]() |
3cf3c67e08 | ||
![]() |
7538de159f | ||
![]() |
94706c8f99 | ||
![]() |
190f24a10b | ||
![]() |
de63f1dddc | ||
![]() |
186cab3356 | ||
![]() |
ae086b9b37 | ||
![]() |
b48432f541 | ||
![]() |
c507a3490e | ||
![]() |
d6570c3e54 | ||
![]() |
fc91345ab9 | ||
![]() |
702b9d6f7e | ||
![]() |
61adbc0a5d | ||
![]() |
6ddc07356e | ||
![]() |
67453107d1 | ||
![]() |
0b0b1206ed | ||
![]() |
bead62bd04 | ||
![]() |
8db682d994 | ||
![]() |
72e36c11eb | ||
![]() |
0bd6964d3e | ||
![]() |
764d1158dc | ||
![]() |
0b17e93e9c | ||
![]() |
2a5b7c49c8 | ||
![]() |
72df3de139 | ||
![]() |
dacd261df4 | ||
![]() |
e404fef08b | ||
![]() |
a7bb114301 | ||
![]() |
975a1005b0 | ||
![]() |
5d84ae6806 | ||
![]() |
c2ef2b5924 | ||
![]() |
4c8427c3b1 | ||
![]() |
e06fc55630 | ||
![]() |
605b6c73d6 | ||
![]() |
197ebe1279 | ||
![]() |
3ffd9f96ef | ||
![]() |
d2def2b453 | ||
![]() |
a4c8c821d0 | ||
![]() |
7d87d662ea | ||
![]() |
bd16b0a151 | ||
![]() |
90d19cea1d | ||
![]() |
640b34ceab | ||
![]() |
7e1bbc9eb4 | ||
![]() |
95036475b4 | ||
![]() |
48ef258ed6 | ||
![]() |
2d73110836 | ||
![]() |
a8109e8273 | ||
![]() |
b2c526941a | ||
![]() |
d055d7f63c | ||
![]() |
8c66ce9ba4 | ||
![]() |
700cfdcd0b | ||
![]() |
468fbb5305 | ||
![]() |
1462b6ee88 | ||
![]() |
dd2621afde | ||
![]() |
e99b614e4a | ||
![]() |
0c05081604 | ||
![]() |
1f2b1702ea | ||
![]() |
ccf491d658 | ||
![]() |
af1483a8ec | ||
![]() |
066c1a7667 | ||
![]() |
b0f8516cd6 | ||
![]() |
937104b3cd | ||
![]() |
b45c381b3b | ||
![]() |
43d152fcf6 | ||
![]() |
5e2b307a70 | ||
![]() |
1983890fb8 | ||
![]() |
0fd12a563c | ||
![]() |
779b1edd48 | ||
![]() |
0ec6fba4ec | ||
![]() |
7d4ec9d56c | ||
![]() |
588a21f76e | ||
![]() |
06e60809ca | ||
![]() |
1e1e19bb19 | ||
![]() |
d5d86997f3 | ||
![]() |
e6f6e43754 | ||
![]() |
8a5e7b5da6 | ||
![]() |
73e27b6145 | ||
![]() |
26457a7a6f | ||
![]() |
f6f10b54b6 | ||
![]() |
31b304f232 | ||
![]() |
f13c54f582 | ||
![]() |
caa795e5f7 | ||
![]() |
4f5b1e5777 | ||
![]() |
838c887a91 | ||
![]() |
55b7065744 | ||
![]() |
75ed13b357 | ||
![]() |
b205c5ff29 | ||
![]() |
b1c4d11ccf | ||
![]() |
ec697840de | ||
![]() |
412e15449b | ||
![]() |
4ab279033c | ||
![]() |
373b2aeab6 | ||
![]() |
951d854891 | ||
![]() |
04e45a7fb2 | ||
![]() |
f6a7a56704 | ||
![]() |
373614e1b2 | ||
![]() |
a38fe781ba | ||
![]() |
a29f394bc4 | ||
![]() |
df264421b4 | ||
![]() |
23648927c3 | ||
![]() |
bfbe9584a1 | ||
![]() |
f6509cfa64 | ||
![]() |
2a9d3d4b47 | ||
![]() |
7aa0c7f6cc | ||
![]() |
8ba6b20357 | ||
![]() |
0e0637a04b | ||
![]() |
8d0e189593 | ||
![]() |
cb230f1615 | ||
![]() |
5d3cd51ba3 | ||
![]() |
ee4089f847 | ||
![]() |
525d6a8da6 | ||
![]() |
6d7a5f1acb | ||
![]() |
d0e269a478 | ||
![]() |
3ca10dfff1 | ||
![]() |
986685d8db | ||
![]() |
461891cde8 | ||
![]() |
2534828fc6 | ||
![]() |
001a472ef9 | ||
![]() |
7e3c0b719b | ||
![]() |
4042968dff | ||
![]() |
fc9e795bd0 | ||
![]() |
2cf9bd4c43 | ||
![]() |
094f547e7a | ||
![]() |
25649be550 | ||
![]() |
6d05f85cbd | ||
![]() |
ae161f11e5 | ||
![]() |
3e23260a9c | ||
![]() |
fa05ec7fff | ||
![]() |
4599bc2c78 | ||
![]() |
6bff8e835d | ||
![]() |
99031fb857 | ||
![]() |
f957f540a1 | ||
![]() |
3ca729c15b | ||
![]() |
e4a57914cd | ||
![]() |
48b3145aaa | ||
![]() |
f812a8c543 | ||
![]() |
a1d6923ca3 | ||
![]() |
926fc76659 | ||
![]() |
1d41d050fe | ||
![]() |
0cab7d5878 | ||
![]() |
c09aab8b38 | ||
![]() |
fd58362a42 | ||
![]() |
00aba3115f | ||
![]() |
379cc761b2 | ||
![]() |
618f8835be | ||
![]() |
94ecb64034 | ||
![]() |
7ac0f31de0 | ||
![]() |
036ce7cbc1 | ||
![]() |
487dc3b93c | ||
![]() |
0d74b81ac9 | ||
![]() |
ff2f2eb386 | ||
![]() |
bb8e055e44 | ||
![]() |
804a8e5be6 | ||
![]() |
3c1a2fa776 | ||
![]() |
7b381f3313 | ||
![]() |
2b19b8194b | ||
![]() |
73b0d1b4c8 | ||
![]() |
ede70b073b | ||
![]() |
363d82d344 | ||
![]() |
df8ece2a30 | ||
![]() |
ff6aab33df | ||
![]() |
0455176123 | ||
![]() |
94830df5fc | ||
![]() |
8a8a3aaaf2 | ||
![]() |
cefd22f448 | ||
![]() |
6a60b78b62 |
186
.github/workflows/audit.yaml
vendored
186
.github/workflows/audit.yaml
vendored
@ -4,62 +4,214 @@ name: Audit
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
audit:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [ '1.20', '1.21' ]
|
||||
directory: [".", "lib"]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v4
|
||||
- name: Checkout dependency
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
repository: rddl-network/bc-slip39-go
|
||||
path: bc-slip39-go
|
||||
|
||||
- name: Build dependency
|
||||
run: |
|
||||
pushd bc-slip39-go
|
||||
./deps.sh
|
||||
popd
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.22"
|
||||
|
||||
- name: Verify dependencies
|
||||
run: go mod verify
|
||||
|
||||
- name: Build
|
||||
run: go build -v ./...
|
||||
run: |
|
||||
pushd ${{ matrix.directory }}
|
||||
go build -v ./...
|
||||
|
||||
proto:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Check proto files
|
||||
run: |
|
||||
if [ "$(find . -name 'query.proto' -exec grep 'option (google.api.http).* = ./planetmint/planetmint-go/' {} \; | wc -l)" -gt 0 ]; then exit 1; fi
|
||||
|
||||
ignite:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Check generated files
|
||||
run: |
|
||||
curl https://get.ignite.com/cli | bash
|
||||
curl https://get.ignite.com/cli@v0.27.1 | bash
|
||||
./ignite chain init --clear-cache --yes
|
||||
rm ignite
|
||||
if [ "$(git diff --stat | wc -l)" -gt 0 ]; then exit 1; fi
|
||||
|
||||
gofmt:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
directory: [".", "lib"]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.22"
|
||||
|
||||
- name: Run gofmt
|
||||
run: if [ "$(gofmt -s -l . | wc -l)" -gt 0 ]; then exit 1; fi
|
||||
run: |
|
||||
pushd ${{ matrix.directory }}
|
||||
if [ "$(gofmt -s -l . | wc -l)" -gt 0 ]; then exit 1; fi
|
||||
|
||||
govet:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
directory: [".", "lib"]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Checkout dependency
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: rddl-network/bc-slip39-go
|
||||
path: bc-slip39-go
|
||||
|
||||
- name: Build dependency
|
||||
run: |
|
||||
pushd bc-slip39-go
|
||||
./deps.sh
|
||||
popd
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.22"
|
||||
|
||||
- name: Run go vet
|
||||
run: go vet ./...
|
||||
run: |
|
||||
pushd ${{ matrix.directory }}
|
||||
go vet ./...
|
||||
|
||||
staticcheck:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
directory: [".", "lib"]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Checkout dependency
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: rddl-network/bc-slip39-go
|
||||
path: bc-slip39-go
|
||||
|
||||
- name: Build dependency
|
||||
run: |
|
||||
pushd bc-slip39-go
|
||||
./deps.sh
|
||||
popd
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.22"
|
||||
|
||||
- name: Install staticcheck
|
||||
run: go install honnef.co/go/tools/cmd/staticcheck@latest
|
||||
|
||||
- name: Run staticcheck
|
||||
env:
|
||||
LINT: "//lint:file-ignore SA1019 Ignore all deprecation errors, it's generated"
|
||||
run: |
|
||||
# Add lint-ignore comment to beginning of files
|
||||
sed -i "1i${LINT}" ./x/asset/types/query.pb.gw.go
|
||||
sed -i "1i${LINT}" ./x/machine/types/query.pb.gw.go
|
||||
sed -i "1i${LINT}" ./x/dao/types/query.pb.gw.go
|
||||
pushd ${{ matrix.directory }}
|
||||
staticcheck ./...
|
||||
|
||||
golangci-lint:
|
||||
strategy:
|
||||
matrix:
|
||||
directory: [".", "lib"]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.22"
|
||||
|
||||
- name: Install golangci-lint
|
||||
run: go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
|
||||
|
||||
- name: Run golangci-lint
|
||||
run: (golangci-lint run && cd lib && golangci-lint run)
|
||||
run: |
|
||||
pushd ${{ matrix.directory }}
|
||||
golangci-lint run
|
||||
|
||||
gotest:
|
||||
strategy:
|
||||
matrix:
|
||||
directory: [".", "lib"]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Checkout dependency
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: rddl-network/bc-slip39-go
|
||||
path: bc-slip39-go
|
||||
|
||||
- name: Build dependency
|
||||
run: |
|
||||
pushd bc-slip39-go
|
||||
./deps.sh
|
||||
popd
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.22"
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
pushd ${{ matrix.directory }}
|
||||
# Exclude generated .pb.go and .pb.gw.go files from test and coverage
|
||||
go test -coverprofile cover.out -race -vet=off -v $(go list ./... | grep -v types)
|
||||
# Print coverage by function
|
||||
|
14
.github/workflows/release.yaml
vendored
14
.github/workflows/release.yaml
vendored
@ -24,7 +24,15 @@ jobs:
|
||||
PRERELEASE: ${{ github.event.inputs.prerelease }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.ref_name }}
|
||||
|
||||
- name: Fetch tags
|
||||
run: |
|
||||
# Cannot use `fetch-tags: true` due to:
|
||||
# https://github.com/actions/checkout/issues/1471
|
||||
git fetch --prune --unshallow --tags
|
||||
|
||||
- name: Tag
|
||||
run: |
|
||||
@ -42,7 +50,9 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v4
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.22"
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
|
2
.github/workflows/sonar.yaml
vendored
2
.github/workflows/sonar.yaml
vendored
@ -11,7 +11,7 @@ jobs:
|
||||
name: Sonar Scan
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
# Shallow clones should be disabled for a better relevancy of analysis
|
||||
fetch-depth: 0
|
||||
|
@ -9,6 +9,7 @@ linters:
|
||||
- bodyclose
|
||||
- containedctx
|
||||
- contextcheck
|
||||
- copyloopvar
|
||||
- decorder
|
||||
- dogsled
|
||||
- dupl
|
||||
@ -18,9 +19,7 @@ linters:
|
||||
- errchkjson
|
||||
- errname
|
||||
- errorlint
|
||||
- execinquery
|
||||
- exhaustive
|
||||
- exportloopref
|
||||
- forbidigo
|
||||
- forcetypeassert
|
||||
- ginkgolinter
|
||||
@ -53,7 +52,6 @@ linters:
|
||||
- noctx
|
||||
- nolintlint
|
||||
- nosprintfhostport
|
||||
- paralleltest
|
||||
- perfsprint
|
||||
- prealloc
|
||||
- predeclared
|
||||
@ -93,12 +91,55 @@ issues:
|
||||
- path: x/.*/types/message.*\.go
|
||||
linters:
|
||||
- dupl
|
||||
- path: x/dao/client/cli/query_.*\.go
|
||||
linters:
|
||||
- dupl
|
||||
- path: x/dao/client/cli/tx_reissue_rddl.*\.go
|
||||
linters:
|
||||
- dupl
|
||||
- path: x/dao/client/cli/*\.go
|
||||
linters:
|
||||
- revive
|
||||
- path: testutil/nullify/nullify\.go
|
||||
linters:
|
||||
- exhaustive
|
||||
- path: x/.*/keeper/query.*\.go
|
||||
linters:
|
||||
- dupl
|
||||
- paralleltest
|
||||
- path: tests/.*/*\.go
|
||||
linters:
|
||||
- paralleltest
|
||||
- path: util/machine_nft_test\.go
|
||||
linters:
|
||||
- paralleltest
|
||||
- path: testutil/network/network.go
|
||||
linters:
|
||||
- gocognit
|
||||
- gocyclo
|
||||
- wastedassign
|
||||
- nestif
|
||||
- path: x/.*/simulation/.*\.go
|
||||
linters:
|
||||
- revive
|
||||
- path: x/.*/module_simulation\.go
|
||||
linters:
|
||||
- revive
|
||||
- path: x/.*/client/cli/query_params\.go
|
||||
linters:
|
||||
- revive
|
||||
- path: x/.*/.*/cli/query_.*\.go
|
||||
linters:
|
||||
- revive
|
||||
- path: docs/docs\.go
|
||||
linters:
|
||||
- revive
|
||||
- path: util/elementsd_connector_test\.go
|
||||
linters:
|
||||
- paralleltest
|
||||
- path: monitor/mqtt_monitor_test\.go
|
||||
linters:
|
||||
- paralleltest
|
||||
- path: monitor/.*\.go
|
||||
linters:
|
||||
- durationcheck
|
||||
|
501
Makefile
Normal file
501
Makefile
Normal file
@ -0,0 +1,501 @@
|
||||
#!/usr/bin/make -f
|
||||
|
||||
PACKAGES_NOSIMULATION=$(shell go list ./... | grep -v '/simulation')
|
||||
PACKAGES_SIMTEST=$(shell go list ./... | grep '/simulation')
|
||||
export VERSION := $(shell echo $(shell git describe --always --match "v*") | sed 's/^v//')
|
||||
export TMVERSION := $(shell go list -m github.com/cometbft/cometbft | sed 's:.* ::')
|
||||
export COMMIT := $(shell git log -1 --format='%H')
|
||||
LEDGER_ENABLED ?= true
|
||||
BINDIR ?= $(GOPATH)/bin
|
||||
BUILDDIR ?= $(CURDIR)/build
|
||||
MOCKS_DIR = $(CURDIR)/tests/mocks
|
||||
HTTPS_GIT := https://github.com/cosmos/cosmos-sdk.git
|
||||
DOCKER := $(shell which docker)
|
||||
PROJECT_NAME = $(shell git remote get-url origin | xargs basename -s .git)
|
||||
DOCS_DOMAIN=docs.cosmos.network
|
||||
|
||||
# process build tags
|
||||
build_tags = netgo
|
||||
ifeq ($(LEDGER_ENABLED),true)
|
||||
ifeq ($(OS),Windows_NT)
|
||||
GCCEXE = $(shell where gcc.exe 2> NUL)
|
||||
ifeq ($(GCCEXE),)
|
||||
$(error gcc.exe not installed for ledger support, please install or set LEDGER_ENABLED=false)
|
||||
else
|
||||
build_tags += ledger
|
||||
endif
|
||||
else
|
||||
UNAME_S = $(shell uname -s)
|
||||
ifeq ($(UNAME_S),OpenBSD)
|
||||
$(warning OpenBSD detected, disabling ledger support (https://github.com/cosmos/cosmos-sdk/issues/1988))
|
||||
else
|
||||
GCC = $(shell command -v gcc 2> /dev/null)
|
||||
ifeq ($(GCC),)
|
||||
$(error gcc not installed for ledger support, please install or set LEDGER_ENABLED=false)
|
||||
else
|
||||
build_tags += ledger
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq (secp,$(findstring secp,$(COSMOS_BUILD_OPTIONS)))
|
||||
build_tags += libsecp256k1_sdk
|
||||
endif
|
||||
|
||||
ifeq (legacy,$(findstring legacy,$(COSMOS_BUILD_OPTIONS)))
|
||||
build_tags += app_v1
|
||||
endif
|
||||
|
||||
whitespace :=
|
||||
whitespace += $(whitespace)
|
||||
comma := ,
|
||||
build_tags_comma_sep := $(subst $(whitespace),$(comma),$(build_tags))
|
||||
|
||||
# process linker flags
|
||||
|
||||
ldflags = -X github.com/cosmos/cosmos-sdk/version.Name=sim \
|
||||
-X github.com/cosmos/cosmos-sdk/version.AppName=simd \
|
||||
-X github.com/cosmos/cosmos-sdk/version.Version=$(VERSION) \
|
||||
-X github.com/cosmos/cosmos-sdk/version.Commit=$(COMMIT) \
|
||||
-X "github.com/cosmos/cosmos-sdk/version.BuildTags=$(build_tags_comma_sep)" \
|
||||
-X github.com/cometbft/cometbft/version.TMCoreSemVer=$(TMVERSION)
|
||||
|
||||
|
||||
# DB backend selection
|
||||
ifeq (cleveldb,$(findstring cleveldb,$(COSMOS_BUILD_OPTIONS)))
|
||||
build_tags += gcc
|
||||
endif
|
||||
ifeq (badgerdb,$(findstring badgerdb,$(COSMOS_BUILD_OPTIONS)))
|
||||
build_tags += badgerdb
|
||||
endif
|
||||
# handle rocksdb
|
||||
ifeq (rocksdb,$(findstring rocksdb,$(COSMOS_BUILD_OPTIONS)))
|
||||
CGO_ENABLED=1
|
||||
build_tags += rocksdb
|
||||
endif
|
||||
# handle boltdb
|
||||
ifeq (boltdb,$(findstring boltdb,$(COSMOS_BUILD_OPTIONS)))
|
||||
build_tags += boltdb
|
||||
endif
|
||||
|
||||
ifeq (,$(findstring nostrip,$(COSMOS_BUILD_OPTIONS)))
|
||||
ldflags += -w -s
|
||||
endif
|
||||
ldflags += $(LDFLAGS)
|
||||
ldflags := $(strip $(ldflags))
|
||||
|
||||
build_tags += $(BUILD_TAGS)
|
||||
build_tags := $(strip $(build_tags))
|
||||
|
||||
BUILD_FLAGS := -tags "$(build_tags)" -ldflags '$(ldflags)'
|
||||
# check for nostrip option
|
||||
ifeq (,$(findstring nostrip,$(COSMOS_BUILD_OPTIONS)))
|
||||
BUILD_FLAGS += -trimpath
|
||||
endif
|
||||
|
||||
# Check for debug option
|
||||
ifeq (debug,$(findstring debug,$(COSMOS_BUILD_OPTIONS)))
|
||||
BUILD_FLAGS += -gcflags "all=-N -l"
|
||||
endif
|
||||
|
||||
all: tools build lint test vulncheck
|
||||
|
||||
# The below include contains the tools and runsim targets.
|
||||
include contrib/devtools/Makefile
|
||||
|
||||
###############################################################################
|
||||
### Build ###
|
||||
###############################################################################
|
||||
|
||||
BUILD_TARGETS := build install
|
||||
|
||||
build: BUILD_ARGS=-o $(BUILDDIR)/
|
||||
|
||||
build-linux-amd64:
|
||||
GOOS=linux GOARCH=amd64 LEDGER_ENABLED=false $(MAKE) build
|
||||
|
||||
build-linux-arm64:
|
||||
GOOS=linux GOARCH=arm64 LEDGER_ENABLED=false $(MAKE) build
|
||||
|
||||
$(BUILD_TARGETS): go.sum $(BUILDDIR)/
|
||||
cd ${CURRENT_DIR}/app && go $@ -mod=readonly $(BUILD_FLAGS) $(BUILD_ARGS) ./...
|
||||
|
||||
$(BUILDDIR)/:
|
||||
mkdir -p $(BUILDDIR)/
|
||||
|
||||
cosmovisor:
|
||||
$(MAKE) -C tools/cosmovisor cosmovisor
|
||||
|
||||
.PHONY: build build-linux-amd64 build-linux-arm64 cosmovisor
|
||||
|
||||
|
||||
mocks: $(MOCKS_DIR)
|
||||
@go install github.com/golang/mock/mockgen@v1.6.0
|
||||
sh ./scripts/mockgen.sh
|
||||
.PHONY: mocks
|
||||
|
||||
|
||||
vulncheck: $(BUILDDIR)/
|
||||
GOBIN=$(BUILDDIR) go install golang.org/x/vuln/cmd/govulncheck@latest
|
||||
$(BUILDDIR)/govulncheck ./...
|
||||
|
||||
$(MOCKS_DIR):
|
||||
mkdir -p $(MOCKS_DIR)
|
||||
|
||||
distclean: clean tools-clean
|
||||
clean:
|
||||
rm -rf \
|
||||
$(BUILDDIR)/ \
|
||||
artifacts/ \
|
||||
tmp-swagger-gen/ \
|
||||
.testnets
|
||||
|
||||
.PHONY: distclean clean
|
||||
|
||||
###############################################################################
|
||||
### Tools & Dependencies ###
|
||||
###############################################################################
|
||||
|
||||
go.sum: go.mod
|
||||
echo "Ensure dependencies have not been modified ..." >&2
|
||||
go mod verify
|
||||
go mod tidy
|
||||
|
||||
###############################################################################
|
||||
### Documentation ###
|
||||
###############################################################################
|
||||
|
||||
update-swagger-docs: statik
|
||||
$(BINDIR)/statik -src=client/docs/swagger-ui -dest=client/docs -f -m
|
||||
@if [ -n "$(git status --porcelain)" ]; then \
|
||||
echo "\033[91mSwagger docs are out of sync!!!\033[0m";\
|
||||
exit 1;\
|
||||
else \
|
||||
echo "\033[92mSwagger docs are in sync\033[0m";\
|
||||
fi
|
||||
.PHONY: update-swagger-docs
|
||||
|
||||
godocs:
|
||||
@echo "--> Wait a few seconds and visit http://localhost:6060/pkg/github.com/cosmos/cosmos-sdk/types"
|
||||
godoc -http=:6060
|
||||
|
||||
# This builds the docs.cosmos.network docs using docusaurus.
|
||||
# Old documentation, which have not been migrated to docusaurus are generated with vuepress.
|
||||
build-docs:
|
||||
@echo "building docusaurus docs"
|
||||
@cd docs && npm ci && npm run build
|
||||
mv docs/build ~/output
|
||||
|
||||
@echo "building old docs"
|
||||
@cd docs && \
|
||||
while read -r branch path_prefix; do \
|
||||
echo "building vuepress $${branch} docs" ; \
|
||||
(git clean -fdx && git reset --hard && git checkout $${branch} && npm install && VUEPRESS_BASE="/$${path_prefix}/" npm run build) ; \
|
||||
mkdir -p ~/output/$${path_prefix} ; \
|
||||
cp -r .vuepress/dist/* ~/output/$${path_prefix}/ ; \
|
||||
done < vuepress_versions ;
|
||||
|
||||
@echo "setup domain"
|
||||
@echo $(DOCS_DOMAIN) > ~/output/CNAME
|
||||
|
||||
.PHONY: build-docs
|
||||
|
||||
###############################################################################
|
||||
### Tests & Simulation ###
|
||||
###############################################################################
|
||||
|
||||
test: test-unit
|
||||
test-e2e:
|
||||
$(MAKE) -C tests test-e2e
|
||||
test-e2e-cov:
|
||||
$(MAKE) -C tests test-e2e-cov
|
||||
test-integration:
|
||||
$(MAKE) -C tests test-integration
|
||||
test-integration-cov:
|
||||
$(MAKE) -C tests test-integration-cov
|
||||
test-all: test-unit test-e2e test-integration test-ledger-mock test-race
|
||||
|
||||
TEST_PACKAGES=./...
|
||||
TEST_TARGETS := test-unit test-unit-amino test-unit-proto test-ledger-mock test-race test-ledger test-race
|
||||
|
||||
# Test runs-specific rules. To add a new test target, just add
|
||||
# a new rule, customise ARGS or TEST_PACKAGES ad libitum, and
|
||||
# append the new rule to the TEST_TARGETS list.
|
||||
test-unit: test_tags += cgo ledger test_ledger_mock norace
|
||||
test-unit-amino: test_tags += ledger test_ledger_mock test_amino norace
|
||||
test-ledger: test_tags += cgo ledger norace
|
||||
test-ledger-mock: test_tags += ledger test_ledger_mock norace
|
||||
test-race: test_tags += cgo ledger test_ledger_mock
|
||||
test-race: ARGS=-race
|
||||
test-race: TEST_PACKAGES=$(PACKAGES_NOSIMULATION)
|
||||
$(TEST_TARGETS): run-tests
|
||||
|
||||
# check-* compiles and collects tests without running them
|
||||
# note: go test -c doesn't support multiple packages yet (https://github.com/golang/go/issues/15513)
|
||||
CHECK_TEST_TARGETS := check-test-unit check-test-unit-amino
|
||||
check-test-unit: test_tags += cgo ledger test_ledger_mock norace
|
||||
check-test-unit-amino: test_tags += ledger test_ledger_mock test_amino norace
|
||||
$(CHECK_TEST_TARGETS): EXTRA_ARGS=-run=none
|
||||
$(CHECK_TEST_TARGETS): run-tests
|
||||
|
||||
ARGS += -tags "$(test_tags)"
|
||||
SUB_MODULES = $(shell find . -type f -name 'go.mod' -print0 | xargs -0 -n1 dirname | sort)
|
||||
CURRENT_DIR = $(shell pwd)
|
||||
run-tests:
|
||||
ifneq (,$(shell which tparse 2>/dev/null))
|
||||
@echo "Starting unit tests"; \
|
||||
finalec=0; \
|
||||
for module in $(SUB_MODULES); do \
|
||||
cd ${CURRENT_DIR}/$$module; \
|
||||
echo "Running unit tests for module $$module"; \
|
||||
go test -mod=readonly -json $(ARGS) $(TEST_PACKAGES) ./... | tparse; \
|
||||
ec=$$?; \
|
||||
if [ "$$ec" -ne '0' ]; then finalec=$$ec; fi; \
|
||||
done; \
|
||||
exit $$finalec
|
||||
else
|
||||
@echo "Starting unit tests"; \
|
||||
finalec=0; \
|
||||
for module in $(SUB_MODULES); do \
|
||||
cd ${CURRENT_DIR}/$$module; \
|
||||
echo "Running unit tests for module $$module"; \
|
||||
go test -mod=readonly $(ARGS) $(TEST_PACKAGES) ./... ; \
|
||||
ec=$$?; \
|
||||
if [ "$$ec" -ne '0' ]; then finalec=$$ec; fi; \
|
||||
done; \
|
||||
exit $$finalec
|
||||
endif
|
||||
|
||||
.PHONY: run-tests test test-all $(TEST_TARGETS)
|
||||
|
||||
test-sim-nondeterminism:
|
||||
@echo "Running non-determinism test..."
|
||||
@cd ${CURRENT_DIR}/app && go test -mod=readonly -run TestAppStateDeterminism -Enabled=true \
|
||||
-NumBlocks=100 -BlockSize=200 -Commit=true -Period=0 -v -timeout 24h
|
||||
|
||||
test-sim-custom-genesis-fast:
|
||||
@echo "Running custom genesis simulation..."
|
||||
@echo "By default, ${HOME}/.gaiad/config/genesis.json will be used."
|
||||
@cd ${CURRENT_DIR}/app && go test -mod=readonly -run TestFullAppSimulation -Genesis=${HOME}/.gaiad/config/genesis.json \
|
||||
-Enabled=true -NumBlocks=100 -BlockSize=200 -Commit=true -Seed=99 -Period=5 -v -timeout 24h
|
||||
|
||||
test-sim-import-export: runsim
|
||||
@echo "Running application import/export simulation. This may take several minutes..."
|
||||
@cd ${CURRENT_DIR}/app && $(BINDIR)/runsim -Jobs=4 -SimAppPkg=. -ExitOnFail 50 5 TestAppImportExport
|
||||
|
||||
test-sim-after-import: runsim
|
||||
@echo "Running application simulation-after-import. This may take several minutes..."
|
||||
@cd ${CURRENT_DIR}/app && $(BINDIR)/runsim -Jobs=4 -SimAppPkg=. -ExitOnFail 50 5 TestAppSimulationAfterImport
|
||||
|
||||
test-sim-custom-genesis-multi-seed: runsim
|
||||
@echo "Running multi-seed custom genesis simulation..."
|
||||
@echo "By default, ${HOME}/.gaiad/config/genesis.json will be used."
|
||||
@cd ${CURRENT_DIR}/app && $(BINDIR)/runsim -Genesis=${HOME}/.gaiad/config/genesis.json -SimAppPkg=. -ExitOnFail 400 5 TestFullAppSimulation
|
||||
|
||||
test-sim-multi-seed-long: runsim
|
||||
@echo "Running long multi-seed application simulation. This may take awhile!"
|
||||
@cd ${CURRENT_DIR}/app && $(BINDIR)/runsim -Jobs=4 -SimAppPkg=. -ExitOnFail 500 50 TestFullAppSimulation
|
||||
|
||||
test-sim-multi-seed-short: runsim
|
||||
@echo "Running short multi-seed application simulation. This may take awhile!"
|
||||
@cd ${CURRENT_DIR}/app && $(BINDIR)/runsim -Jobs=4 -SimAppPkg=. -ExitOnFail 50 10 TestFullAppSimulation
|
||||
|
||||
test-sim-benchmark-invariants:
|
||||
@echo "Running simulation invariant benchmarks..."
|
||||
cd ${CURRENT_DIR}/app && @go test -mod=readonly -benchmem -bench=BenchmarkInvariants -run=^$ \
|
||||
-Enabled=true -NumBlocks=1000 -BlockSize=200 \
|
||||
-Period=1 -Commit=true -Seed=57 -v -timeout 24h
|
||||
|
||||
.PHONY: \
|
||||
test-sim-nondeterminism \
|
||||
test-sim-custom-genesis-fast \
|
||||
test-sim-import-export \
|
||||
test-sim-after-import \
|
||||
test-sim-custom-genesis-multi-seed \
|
||||
test-sim-multi-seed-short \
|
||||
test-sim-multi-seed-long \
|
||||
test-sim-benchmark-invariants
|
||||
|
||||
SIM_NUM_BLOCKS ?= 500
|
||||
SIM_BLOCK_SIZE ?= 200
|
||||
SIM_COMMIT ?= true
|
||||
|
||||
test-sim-benchmark:
|
||||
@echo "Running application benchmark for numBlocks=$(SIM_NUM_BLOCKS), blockSize=$(SIM_BLOCK_SIZE). This may take awhile!"
|
||||
@cd ${CURRENT_DIR}/app && go test -mod=readonly -benchmem -run=^$$ $(.) -bench ^BenchmarkFullAppSimulation$$ \
|
||||
-Enabled=true -NumBlocks=$(SIM_NUM_BLOCKS) -BlockSize=$(SIM_BLOCK_SIZE) -Commit=$(SIM_COMMIT) -timeout 24h
|
||||
|
||||
test-sim-profile:
|
||||
@echo "Running application benchmark for numBlocks=$(SIM_NUM_BLOCKS), blockSize=$(SIM_BLOCK_SIZE). This may take awhile!"
|
||||
@cd ${CURRENT_DIR}/app && go test -mod=readonly -benchmem -run=^$$ $(.) -bench ^BenchmarkFullAppSimulation$$ \
|
||||
-Enabled=true -NumBlocks=$(SIM_NUM_BLOCKS) -BlockSize=$(SIM_BLOCK_SIZE) -Commit=$(SIM_COMMIT) -timeout 24h -cpuprofile cpu.out -memprofile mem.out
|
||||
|
||||
.PHONY: test-sim-profile test-sim-benchmark
|
||||
|
||||
test-rosetta:
|
||||
docker build -t rosetta-ci:latest -f contrib/rosetta/rosetta-ci/Dockerfile .
|
||||
docker-compose -f contrib/rosetta/docker-compose.yaml up --abort-on-container-exit --exit-code-from test_rosetta --build
|
||||
.PHONY: test-rosetta
|
||||
|
||||
benchmark:
|
||||
@go test -mod=readonly -bench=. $(PACKAGES_NOSIMULATION)
|
||||
.PHONY: benchmark
|
||||
|
||||
###############################################################################
|
||||
### Linting ###
|
||||
###############################################################################
|
||||
|
||||
golangci_lint_cmd=golangci-lint
|
||||
golangci_version=v1.50.1
|
||||
|
||||
lint:
|
||||
@echo "--> Running linter"
|
||||
@go install github.com/golangci/golangci-lint/cmd/golangci-lint@$(golangci_version)
|
||||
@$(golangci_lint_cmd) run --timeout=10m
|
||||
|
||||
lint-fix:
|
||||
@echo "--> Running linter"
|
||||
@go install github.com/golangci/golangci-lint/cmd/golangci-lint@$(golangci_version)
|
||||
@$(golangci_lint_cmd) run --fix --out-format=tab --issues-exit-code=0
|
||||
|
||||
.PHONY: lint lint-fix
|
||||
|
||||
format:
|
||||
@go install mvdan.cc/gofumpt@latest
|
||||
@go install github.com/golangci/golangci-lint/cmd/golangci-lint@$(golangci_version)
|
||||
find . -name '*.go' -type f -not -path "./vendor*" -not -path "*.git*" -not -path "./client/docs/statik/statik.go" -not -path "./tests/mocks/*" -not -name "*.pb.go" -not -name "*.pb.gw.go" -not -name "*.pulsar.go" -not -path "./crypto/keys/secp256k1/*" | xargs gofumpt -w -l
|
||||
$(golangci_lint_cmd) run --fix
|
||||
.PHONY: format
|
||||
|
||||
###############################################################################
|
||||
### Devdoc ###
|
||||
###############################################################################
|
||||
|
||||
DEVDOC_SAVE = docker commit `docker ps -a -n 1 -q` devdoc:local
|
||||
|
||||
devdoc-init:
|
||||
$(DOCKER) run -it -v "$(CURDIR):/go/src/github.com/cosmos/cosmos-sdk" -w "/go/src/github.com/cosmos/cosmos-sdk" tendermint/devdoc echo
|
||||
# TODO make this safer
|
||||
$(call DEVDOC_SAVE)
|
||||
|
||||
devdoc:
|
||||
$(DOCKER) run -it -v "$(CURDIR):/go/src/github.com/cosmos/cosmos-sdk" -w "/go/src/github.com/cosmos/cosmos-sdk" devdoc:local bash
|
||||
|
||||
devdoc-save:
|
||||
# TODO make this safer
|
||||
$(call DEVDOC_SAVE)
|
||||
|
||||
devdoc-clean:
|
||||
docker rmi -f $$(docker images -f "dangling=true" -q)
|
||||
|
||||
devdoc-update:
|
||||
docker pull tendermint/devdoc
|
||||
|
||||
.PHONY: devdoc devdoc-clean devdoc-init devdoc-save devdoc-update
|
||||
|
||||
###############################################################################
|
||||
### Protobuf ###
|
||||
###############################################################################
|
||||
|
||||
protoVer=0.13.0
|
||||
protoImageName=ghcr.io/cosmos/proto-builder:$(protoVer)
|
||||
protoImage=$(DOCKER) run --rm -v $(CURDIR):/workspace --workdir /workspace $(protoImageName)
|
||||
|
||||
proto-all: proto-format proto-lint proto-gen
|
||||
|
||||
proto-gen:
|
||||
@echo "Generating Protobuf files"
|
||||
@$(protoImage) sh ./scripts/protocgen.sh
|
||||
|
||||
proto-swagger-gen:
|
||||
@echo "Generating Protobuf Swagger"
|
||||
@$(protoImage) sh ./scripts/protoc-swagger-gen.sh
|
||||
$(MAKE) update-swagger-docs
|
||||
|
||||
proto-format:
|
||||
@$(protoImage) find ./ -name "*.proto" -exec clang-format -i {} \;
|
||||
|
||||
proto-lint:
|
||||
@$(protoImage) buf lint --error-format=json
|
||||
|
||||
proto-check-breaking:
|
||||
@$(protoImage) buf breaking --against $(HTTPS_GIT)#branch=main
|
||||
|
||||
CMT_URL = https://raw.githubusercontent.com/cometbft/cometbft/v0.37.0/proto/tendermint
|
||||
|
||||
TM_CRYPTO_TYPES = proto/tendermint/crypto
|
||||
TM_ABCI_TYPES = proto/tendermint/abci
|
||||
TM_TYPES = proto/tendermint/types
|
||||
TM_VERSION = proto/tendermint/version
|
||||
TM_LIBS = proto/tendermint/libs/bits
|
||||
TM_P2P = proto/tendermint/p2p
|
||||
|
||||
proto-update-deps:
|
||||
@echo "Updating Protobuf dependencies"
|
||||
|
||||
@mkdir -p $(TM_ABCI_TYPES)
|
||||
@curl -sSL $(TM_URL)/abci/types.proto > $(TM_ABCI_TYPES)/types.proto
|
||||
|
||||
@mkdir -p $(TM_VERSION)
|
||||
@curl -sSL $(TM_URL)/version/types.proto > $(TM_VERSION)/types.proto
|
||||
|
||||
@mkdir -p $(TM_TYPES)
|
||||
@curl -sSL $(TM_URL)/types/types.proto > $(TM_TYPES)/types.proto
|
||||
@curl -sSL $(TM_URL)/types/evidence.proto > $(TM_TYPES)/evidence.proto
|
||||
@curl -sSL $(TM_URL)/types/params.proto > $(TM_TYPES)/params.proto
|
||||
@curl -sSL $(TM_URL)/types/validator.proto > $(TM_TYPES)/validator.proto
|
||||
@curl -sSL $(TM_URL)/types/block.proto > $(TM_TYPES)/block.proto
|
||||
|
||||
@mkdir -p $(TM_CRYPTO_TYPES)
|
||||
@curl -sSL $(TM_URL)/crypto/proof.proto > $(TM_CRYPTO_TYPES)/proof.proto
|
||||
@curl -sSL $(TM_URL)/crypto/keys.proto > $(TM_CRYPTO_TYPES)/keys.proto
|
||||
|
||||
@mkdir -p $(TM_LIBS)
|
||||
@curl -sSL $(TM_URL)/libs/bits/types.proto > $(TM_LIBS)/types.proto
|
||||
|
||||
@mkdir -p $(TM_P2P)
|
||||
@curl -sSL $(TM_URL)/p2p/types.proto > $(TM_P2P)/types.proto
|
||||
|
||||
$(DOCKER) run --rm -v $(CURDIR)/proto:/workspace --workdir /workspace $(protoImageName) buf mod update
|
||||
|
||||
.PHONY: proto-all proto-gen proto-swagger-gen proto-format proto-lint proto-check-breaking proto-update-deps
|
||||
|
||||
###############################################################################
|
||||
### Localnet ###
|
||||
###############################################################################
|
||||
|
||||
localnet-build-env:
|
||||
$(MAKE) -C contrib/images simd-env
|
||||
localnet-build-dlv:
|
||||
$(MAKE) -C contrib/images simd-dlv
|
||||
|
||||
localnet-build-nodes:
|
||||
$(DOCKER) run --rm -v $(CURDIR)/.testnets:/data cosmossdk/simd \
|
||||
testnet init-files --v 4 -o /data --starting-ip-address 192.168.10.2 --keyring-backend=test
|
||||
docker-compose up -d
|
||||
|
||||
localnet-stop:
|
||||
docker-compose down
|
||||
|
||||
# localnet-start will run a 4-node testnet locally. The nodes are
|
||||
# based off the docker images in: ./contrib/images/simd-env
|
||||
localnet-start: localnet-stop localnet-build-env localnet-build-nodes
|
||||
|
||||
# localnet-debug will run a 4-node testnet locally in debug mode
|
||||
# you can read more about the debug mode here: ./contrib/images/simd-dlv/README.md
|
||||
localnet-debug: localnet-stop localnet-build-dlv localnet-build-nodes
|
||||
|
||||
.PHONY: localnet-start localnet-stop localnet-debug localnet-build-env localnet-build-dlv localnet-build-nodes
|
||||
|
||||
###############################################################################
|
||||
### rosetta ###
|
||||
###############################################################################
|
||||
# builds rosetta test data dir
|
||||
rosetta-data:
|
||||
-docker container rm data_dir_build
|
||||
docker build -t rosetta-ci:latest -f contrib/rosetta/rosetta-ci/Dockerfile .
|
||||
docker run --name data_dir_build -t rosetta-ci:latest sh /rosetta/data.sh
|
||||
docker cp data_dir_build:/tmp/data.tar.gz "$(CURDIR)/contrib/rosetta/rosetta-ci/data.tar.gz"
|
||||
docker container rm data_dir_build
|
||||
.PHONY: rosetta-data
|
@ -21,6 +21,7 @@ type HandlerOptions struct {
|
||||
TxFeeChecker TxFeeChecker
|
||||
MachineKeeper MachineKeeper
|
||||
DaoKeeper DaoKeeper
|
||||
StakingKeeper StakingKeeper
|
||||
}
|
||||
|
||||
// NewAnteHandler returns an AnteHandler that checks and increments sequence
|
||||
@ -45,16 +46,20 @@ func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
|
||||
if options.DaoKeeper == nil {
|
||||
return nil, errorsmod.Wrap(sdkerrors.ErrLogic, "dao keeper is required for ante builder")
|
||||
}
|
||||
if options.StakingKeeper == nil {
|
||||
return nil, errorsmod.Wrap(sdkerrors.ErrLogic, "staking keeper is required for ante builder")
|
||||
}
|
||||
|
||||
anteDecorators := []sdk.AnteDecorator{
|
||||
ante.NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first
|
||||
NewSetUpContextDecorator(options.DaoKeeper), // outermost AnteDecorator. SetUpContext must be called first
|
||||
ante.NewExtensionOptionsDecorator(options.ExtensionOptionChecker),
|
||||
NewGasKVCostDecorator(options.StakingKeeper),
|
||||
ante.NewValidateBasicDecorator(),
|
||||
ante.NewTxTimeoutHeightDecorator(),
|
||||
ante.NewValidateMemoDecorator(options.AccountKeeper),
|
||||
NewCheckValidatorDecorator(options.StakingKeeper),
|
||||
NewCheckMachineDecorator(options.MachineKeeper),
|
||||
NewCheckMintAddressDecorator(options.DaoKeeper),
|
||||
NewCheckReissuanceDecorator(),
|
||||
ante.NewConsumeGasForTxSizeDecorator(options.AccountKeeper),
|
||||
NewDeductFeeDecorator(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper, options.TxFeeChecker),
|
||||
ante.NewSetPubKeyDecorator(options.AccountKeeper), // SetPubKeyDecorator must be called before all signature verification decorators
|
||||
|
@ -51,21 +51,21 @@ func (cm CheckMachineDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate
|
||||
func (cm CheckMachineDecorator) handleNotarizeAsset(ctx sdk.Context, notarizeMsg *assettypes.MsgNotarizeAsset) (sdk.Context, error) {
|
||||
_, found := cm.mk.GetMachineIndexByAddress(ctx, notarizeMsg.GetCreator())
|
||||
if !found {
|
||||
return ctx, errorsmod.Wrapf(machinetypes.ErrMachineNotFound, "error during CheckTx or ReCheckTx")
|
||||
return ctx, errorsmod.Wrap(machinetypes.ErrMachineNotFound, ErrorAnteContext)
|
||||
}
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
func (cm CheckMachineDecorator) handleAttestMachine(ctx sdk.Context, attestMsg *machinetypes.MsgAttestMachine) (sdk.Context, error) {
|
||||
if attestMsg.GetCreator() != attestMsg.Machine.GetAddress() {
|
||||
return ctx, errorsmod.Wrapf(machinetypes.ErrMachineIsNotCreator, "error during CheckTx or ReCheckTx")
|
||||
return ctx, errorsmod.Wrap(machinetypes.ErrMachineIsNotCreator, ErrorAnteContext)
|
||||
}
|
||||
_, activated, found := cm.mk.GetTrustAnchor(ctx, attestMsg.Machine.MachineId)
|
||||
if !found {
|
||||
return ctx, errorsmod.Wrapf(machinetypes.ErrTrustAnchorNotFound, "error during CheckTx or ReCheckTx")
|
||||
return ctx, errorsmod.Wrap(machinetypes.ErrTrustAnchorNotFound, ErrorAnteContext)
|
||||
}
|
||||
if activated {
|
||||
return ctx, errorsmod.Wrapf(machinetypes.ErrTrustAnchorAlreadyInUse, "error during CheckTx or ReCheckTx")
|
||||
return ctx, errorsmod.Wrap(machinetypes.ErrTrustAnchorAlreadyInUse, ErrorAnteContext)
|
||||
}
|
||||
return ctx, nil
|
||||
}
|
||||
@ -73,7 +73,7 @@ func (cm CheckMachineDecorator) handleAttestMachine(ctx sdk.Context, attestMsg *
|
||||
func (cm CheckMachineDecorator) handlePopResult(ctx sdk.Context, popMsg *daotypes.MsgReportPopResult) (sdk.Context, error) {
|
||||
_, found := cm.mk.GetMachineIndexByAddress(ctx, popMsg.GetCreator())
|
||||
if !found {
|
||||
return ctx, errorsmod.Wrapf(machinetypes.ErrMachineNotFound, "error during CheckTx or ReCheckTx")
|
||||
return ctx, errorsmod.Wrap(machinetypes.ErrMachineNotFound, ErrorAnteContext)
|
||||
}
|
||||
return ctx, nil
|
||||
}
|
||||
|
@ -1,35 +0,0 @@
|
||||
package ante
|
||||
|
||||
import (
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/planetmint/planetmint-go/config"
|
||||
"github.com/planetmint/planetmint-go/util"
|
||||
"github.com/planetmint/planetmint-go/x/dao/keeper"
|
||||
daotypes "github.com/planetmint/planetmint-go/x/dao/types"
|
||||
)
|
||||
|
||||
type CheckReissuanceDecorator struct{}
|
||||
|
||||
func NewCheckReissuanceDecorator() CheckReissuanceDecorator {
|
||||
return CheckReissuanceDecorator{}
|
||||
}
|
||||
|
||||
func (cmad CheckReissuanceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
|
||||
for _, msg := range tx.GetMsgs() {
|
||||
if sdk.MsgTypeURL(msg) == "/planetmintgo.dao.MsgReissueRDDLProposal" {
|
||||
MsgProposal, ok := msg.(*daotypes.MsgReissueRDDLProposal)
|
||||
if ok {
|
||||
util.GetAppLogger().Debug(ctx, "REISSUE: receive Proposal")
|
||||
conf := config.GetConfig()
|
||||
isValid := keeper.IsValidReissuanceCommand(MsgProposal.GetTx(), conf.ReissuanceAsset, MsgProposal.GetBlockHeight())
|
||||
if !isValid {
|
||||
util.GetAppLogger().Info(ctx, "REISSUE: error during CheckTx or ReCheckTx")
|
||||
return ctx, errorsmod.Wrapf(daotypes.ErrReissuanceProposal, "error during CheckTx or ReCheckTx")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
59
app/ante/check_validator_decorator.go
Normal file
59
app/ante/check_validator_decorator.go
Normal file
@ -0,0 +1,59 @@
|
||||
package ante
|
||||
|
||||
import (
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/planetmint/planetmint-go/x/dao/types"
|
||||
)
|
||||
|
||||
type CheckValidatorDecorator struct {
|
||||
sk StakingKeeper
|
||||
}
|
||||
|
||||
func NewCheckValidatorDecorator(sk StakingKeeper) CheckValidatorDecorator {
|
||||
return CheckValidatorDecorator{sk: sk}
|
||||
}
|
||||
|
||||
func (cv CheckValidatorDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (_ sdk.Context, err error) {
|
||||
if simulate || ctx.BlockHeight() == 0 {
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
|
||||
for _, msg := range tx.GetMsgs() {
|
||||
switch sdk.MsgTypeURL(msg) {
|
||||
case "/planetmintgo.dao.MsgInitPop":
|
||||
fallthrough
|
||||
case "/planetmintgo.dao.MsgDistributionRequest":
|
||||
fallthrough
|
||||
case "/planetmintgo.dao.MsgDistributionResult":
|
||||
fallthrough
|
||||
case "/planetmintgo.dao.MsgReissueRDDLProposal":
|
||||
fallthrough
|
||||
case "/planetmintgo.dao.MsgReissueRDDLResult":
|
||||
fallthrough
|
||||
case "/planetmintgo.dao.MsgUpdateRedeemClaim":
|
||||
fallthrough
|
||||
case "/planetmintgo.machine.MsgNotarizeLiquidAsset":
|
||||
fallthrough
|
||||
case "/planetmintgo.machine.MsgRegisterTrustAnchor":
|
||||
ctx, err = cv.handleMsg(ctx, msg)
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return ctx, err
|
||||
}
|
||||
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
|
||||
func (cv CheckValidatorDecorator) handleMsg(ctx sdk.Context, msg sdk.Msg) (_ sdk.Context, err error) {
|
||||
signer := msg.GetSigners()[0]
|
||||
_, found := cv.sk.GetValidator(ctx, sdk.ValAddress(signer))
|
||||
if !found {
|
||||
return ctx, errorsmod.Wrap(types.ErrRestrictedMsg, ErrorAnteContext)
|
||||
}
|
||||
return ctx, nil
|
||||
}
|
@ -40,7 +40,7 @@ func NewDeductFeeDecorator(ak AccountKeeper, bk authtypes.BankKeeper, fk Feegran
|
||||
func checkTxFee(ctx sdk.Context, tx sdk.Tx) (sdk.Coins, error) {
|
||||
feeTx, ok := tx.(sdk.FeeTx)
|
||||
if !ok {
|
||||
return nil, errorsmod.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx")
|
||||
return nil, errorsmod.Wrap(sdkerrors.ErrTxDecode, ErrorTxFeeTx)
|
||||
}
|
||||
|
||||
feeCoins := feeTx.GetFee()
|
||||
@ -74,7 +74,7 @@ func checkTxFee(ctx sdk.Context, tx sdk.Tx) (sdk.Coins, error) {
|
||||
func (dfd DeductFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
|
||||
feeTx, ok := tx.(sdk.FeeTx)
|
||||
if !ok {
|
||||
return ctx, errorsmod.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx")
|
||||
return ctx, errorsmod.Wrap(sdkerrors.ErrTxDecode, ErrorTxFeeTx)
|
||||
}
|
||||
|
||||
if !simulate && ctx.BlockHeight() > 0 && feeTx.GetGas() == 0 {
|
||||
@ -84,6 +84,10 @@ func (dfd DeductFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bo
|
||||
var (
|
||||
err error
|
||||
)
|
||||
msgs := tx.GetMsgs()
|
||||
if len(msgs) == 1 && sdk.MsgTypeURL(msgs[0]) == "/planetmintgo.machine.MsgAttestMachine" {
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
|
||||
fee := feeTx.GetFee()
|
||||
if !simulate {
|
||||
@ -102,7 +106,7 @@ func (dfd DeductFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bo
|
||||
func (dfd DeductFeeDecorator) checkDeductFee(ctx sdk.Context, sdkTx sdk.Tx, fee sdk.Coins) error {
|
||||
feeTx, ok := sdkTx.(sdk.FeeTx)
|
||||
if !ok {
|
||||
return errorsmod.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx")
|
||||
return errorsmod.Wrap(sdkerrors.ErrTxDecode, ErrorTxFeeTx)
|
||||
}
|
||||
|
||||
if addr := dfd.accountKeeper.GetModuleAddress(authtypes.FeeCollectorName); addr == nil {
|
||||
@ -162,7 +166,7 @@ func (dfd DeductFeeDecorator) deductFees(bankKeeper authtypes.BankKeeper, ctx sd
|
||||
|
||||
err := bankKeeper.SendCoinsFromAccountToModule(ctx, acc.GetAddress(), authtypes.FeeCollectorName, fees)
|
||||
if err != nil {
|
||||
return errorsmod.Wrapf(sdkerrors.ErrInsufficientFunds, err.Error())
|
||||
return errorsmod.Wrap(sdkerrors.ErrInsufficientFunds, err.Error())
|
||||
}
|
||||
|
||||
return nil
|
||||
|
6
app/ante/error.go
Normal file
6
app/ante/error.go
Normal file
@ -0,0 +1,6 @@
|
||||
package ante
|
||||
|
||||
var (
|
||||
ErrorAnteContext = "error during CheckTx or ReCheckTx"
|
||||
ErrorTxFeeTx = "Tx must be a FeeTx"
|
||||
)
|
@ -5,6 +5,7 @@ import (
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
daotypes "github.com/planetmint/planetmint-go/x/dao/types"
|
||||
)
|
||||
|
||||
@ -32,9 +33,19 @@ type BankKeeper interface {
|
||||
IsSendEnabledCoins(ctx sdk.Context, coins ...sdk.Coin) error
|
||||
SendCoins(ctx sdk.Context, from, to sdk.AccAddress, amt sdk.Coins) error
|
||||
SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error
|
||||
GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin
|
||||
}
|
||||
|
||||
type DaoKeeper interface {
|
||||
GetMintRequestByHash(ctx sdk.Context, hash string) (val daotypes.MintRequest, found bool)
|
||||
GetMintAddress(ctx sdk.Context) (mintAddress string)
|
||||
GetTxGasLimit(ctx sdk.Context) (txGasLimit uint64)
|
||||
GetClaimAddress(ctx sdk.Context) (claimAddress string)
|
||||
IsValidReissuanceProposal(ctx sdk.Context, msg *daotypes.MsgReissueRDDLProposal) (isValid bool)
|
||||
GetRedeemClaim(ctx sdk.Context, benficiary string, id uint64) (val daotypes.RedeemClaim, found bool)
|
||||
GetParams(ctx sdk.Context) (params daotypes.Params)
|
||||
}
|
||||
|
||||
type StakingKeeper interface {
|
||||
GetValidator(ctx sdk.Context, addr sdk.ValAddress) (validator stakingtypes.Validator, found bool)
|
||||
}
|
||||
|
42
app/ante/gaskv_cost_decorator.go
Normal file
42
app/ante/gaskv_cost_decorator.go
Normal file
@ -0,0 +1,42 @@
|
||||
package ante
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
type GasKVCostDecorator struct {
|
||||
sk StakingKeeper
|
||||
}
|
||||
|
||||
func NewGasKVCostDecorator(sk StakingKeeper) GasKVCostDecorator {
|
||||
return GasKVCostDecorator{sk: sk}
|
||||
}
|
||||
|
||||
func (gc GasKVCostDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (_ sdk.Context, err error) {
|
||||
if simulate || ctx.BlockHeight() == 0 {
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
|
||||
msgs := tx.GetMsgs()
|
||||
signers := msgs[0].GetSigners()
|
||||
signer := signers[0]
|
||||
|
||||
valAddr := sdk.ValAddress(signer)
|
||||
_, found := gc.sk.GetValidator(ctx, valAddr)
|
||||
|
||||
if !found {
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
|
||||
ctx = ctx.WithKVGasConfig(sdk.GasConfig{
|
||||
HasCost: 0,
|
||||
DeleteCost: 0,
|
||||
ReadCostFlat: 0,
|
||||
ReadCostPerByte: 0,
|
||||
WriteCostFlat: 0,
|
||||
WriteCostPerByte: 0,
|
||||
IterNextCostFlat: 0,
|
||||
})
|
||||
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
92
app/ante/setup_context_decorator.go
Normal file
92
app/ante/setup_context_decorator.go
Normal file
@ -0,0 +1,92 @@
|
||||
package ante
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx"
|
||||
)
|
||||
|
||||
var _ GasTx = (*legacytx.StdTx)(nil) // assert StdTx implements GasTx
|
||||
|
||||
// GasTx defines a Tx with a GetGas() method which is needed to use SetUpContextDecorator
|
||||
type GasTx interface {
|
||||
sdk.Tx
|
||||
GetGas() uint64
|
||||
}
|
||||
|
||||
// SetUpContextDecorator sets the GasMeter in the Context and wraps the next AnteHandler with a defer clause
|
||||
// to recover from any downstream OutOfGas panics in the AnteHandler chain to return an error with information
|
||||
// on gas provided and gas used.
|
||||
// CONTRACT: Must be first decorator in the chain
|
||||
// CONTRACT: Tx must implement GasTx interface
|
||||
type SetUpContextDecorator struct {
|
||||
dk DaoKeeper
|
||||
}
|
||||
|
||||
func NewSetUpContextDecorator(dk DaoKeeper) SetUpContextDecorator {
|
||||
return SetUpContextDecorator{
|
||||
dk: dk,
|
||||
}
|
||||
}
|
||||
|
||||
func (sud SetUpContextDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
||||
// all transactions must implement GasTx
|
||||
gasTx, ok := tx.(GasTx)
|
||||
if !ok {
|
||||
// Set a gas meter with limit 0 as to prevent an infinite gas meter attack
|
||||
// during runTx.
|
||||
newCtx = SetGasMeter(simulate, ctx, 0)
|
||||
return newCtx, errorsmod.Wrap(sdkerrors.ErrTxDecode, "Tx must be GasTx")
|
||||
}
|
||||
|
||||
gasLimit := sud.dk.GetTxGasLimit(ctx)
|
||||
if gasLimit == 0 {
|
||||
gasLimit = gasTx.GetGas()
|
||||
}
|
||||
|
||||
newCtx = SetGasMeter(simulate, ctx, gasLimit)
|
||||
|
||||
if cp := ctx.ConsensusParams(); cp != nil && cp.Block != nil {
|
||||
// If there exists a maximum block gas limit, we must ensure that the tx
|
||||
// does not exceed it.
|
||||
if cp.Block.MaxGas > 0 && gasTx.GetGas() > uint64(cp.Block.MaxGas) {
|
||||
return newCtx, errorsmod.Wrapf(sdkerrors.ErrInvalidGasLimit, "tx gas limit %d exceeds block max gas %d", gasTx.GetGas(), cp.Block.MaxGas)
|
||||
}
|
||||
}
|
||||
|
||||
// Decorator will catch an OutOfGasPanic caused in the next antehandler
|
||||
// AnteHandlers must have their own defer/recover in order for the BaseApp
|
||||
// to know how much gas was used! This is because the GasMeter is created in
|
||||
// the AnteHandler, but if it panics the context won't be set properly in
|
||||
// runTx's recover call.
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
switch rType := r.(type) {
|
||||
case sdk.ErrorOutOfGas:
|
||||
log := fmt.Sprintf(
|
||||
"out of gas in location: %v; gasWanted: %d, gasUsed: %d",
|
||||
rType.Descriptor, gasTx.GetGas(), newCtx.GasMeter().GasConsumed())
|
||||
|
||||
err = errorsmod.Wrap(sdkerrors.ErrOutOfGas, log)
|
||||
default:
|
||||
panic(r)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return next(newCtx, tx, simulate)
|
||||
}
|
||||
|
||||
// SetGasMeter returns a new context with a gas meter set from a given context.
|
||||
func SetGasMeter(simulate bool, ctx sdk.Context, gasLimit uint64) sdk.Context {
|
||||
// In various cases such as simulation and during the genesis block, we do not
|
||||
// meter any gas utilization.
|
||||
if simulate || ctx.BlockHeight() == 0 {
|
||||
return ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
|
||||
}
|
||||
|
||||
return ctx.WithGasMeter(sdk.NewGasMeter(gasLimit))
|
||||
}
|
36
app/app.go
36
app/app.go
@ -109,6 +109,7 @@ import (
|
||||
ibctm "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint"
|
||||
"github.com/spf13/cast"
|
||||
|
||||
"github.com/planetmint/planetmint-go/monitor"
|
||||
machinemodule "github.com/planetmint/planetmint-go/x/machine"
|
||||
machinemodulekeeper "github.com/planetmint/planetmint-go/x/machine/keeper"
|
||||
machinemoduletypes "github.com/planetmint/planetmint-go/x/machine/types"
|
||||
@ -548,6 +549,8 @@ func New(
|
||||
keys[machinemoduletypes.AddressIndexKey],
|
||||
keys[machinemoduletypes.MemStoreKey],
|
||||
app.GetSubspace(machinemoduletypes.ModuleName),
|
||||
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
|
||||
homePath,
|
||||
)
|
||||
machineModule := machinemodule.NewAppModule(appCodec, app.MachineKeeper, app.AccountKeeper, app.BankKeeper)
|
||||
|
||||
@ -568,11 +571,14 @@ func New(
|
||||
keys[daomoduletypes.ChallengeKey],
|
||||
keys[daomoduletypes.MintRequestHashKey],
|
||||
keys[daomoduletypes.MintRequestAddressKey],
|
||||
keys[authtypes.StoreKey],
|
||||
app.GetSubspace(daomoduletypes.ModuleName),
|
||||
|
||||
app.BankKeeper,
|
||||
app.AccountKeeper,
|
||||
app.MachineKeeper,
|
||||
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
|
||||
homePath,
|
||||
)
|
||||
daoModule := daomodule.NewAppModule(appCodec, app.DaoKeeper, app.AccountKeeper, app.BankKeeper)
|
||||
|
||||
@ -777,6 +783,7 @@ func New(
|
||||
SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
|
||||
MachineKeeper: app.MachineKeeper,
|
||||
DaoKeeper: app.DaoKeeper,
|
||||
StakingKeeper: app.StakingKeeper,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
@ -788,6 +795,8 @@ func New(
|
||||
app.SetBeginBlocker(app.BeginBlocker)
|
||||
app.SetEndBlocker(app.EndBlocker)
|
||||
|
||||
app.setupUpgradeHandlers()
|
||||
|
||||
if loadLatest {
|
||||
if err := app.LoadLatestVersion(); err != nil {
|
||||
tmos.Exit(err.Error())
|
||||
@ -798,6 +807,8 @@ func New(
|
||||
app.ScopedTransferKeeper = scopedTransferKeeper
|
||||
// this line is used by starport scaffolding # stargate/app/beforeInitReturn
|
||||
|
||||
monitor.LazyMqttMonitorLoader(logger, homePath)
|
||||
|
||||
return app
|
||||
}
|
||||
|
||||
@ -944,6 +955,12 @@ func (app *App) RegisterTendermintService(clientCtx client.Context) {
|
||||
// RegisterNodeService implements the Application.RegisterNodeService method.
|
||||
func (app *App) RegisterNodeService(clientCtx client.Context) {
|
||||
nodeservice.RegisterNodeService(clientCtx, app.GRPCQueryRouter())
|
||||
// HACK: start mqtt monitor as late as possible (hint: look in vendor directory for startup order)
|
||||
mqttMonitorInstance := monitor.GetMqttMonitorInstance()
|
||||
err := mqttMonitorInstance.Start()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// initParamsKeeper init params keeper and its subspaces
|
||||
@ -979,3 +996,22 @@ func (app *App) SimulationManager() *module.SimulationManager {
|
||||
func (app *App) ModuleManager() *module.Manager {
|
||||
return app.mm
|
||||
}
|
||||
|
||||
func (app *App) setupUpgradeHandlers() {
|
||||
app.UpgradeKeeper.SetUpgradeHandler("v0.8.0", func(ctx sdk.Context, _ upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) {
|
||||
// Set versions to the latest ConsensusVersion in the VersionMap.
|
||||
// This will skip running InitGenesis on Dao
|
||||
fromVM[daomoduletypes.ModuleName] = daomodule.AppModule{}.ConsensusVersion()
|
||||
fromVM[machinemoduletypes.ModuleName] = machinemodule.AppModule{}.ConsensusVersion()
|
||||
return app.mm.RunMigrations(ctx, app.configurator, fromVM)
|
||||
})
|
||||
app.UpgradeKeeper.SetUpgradeHandler("v0.10.0", func(ctx sdk.Context, _ upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) {
|
||||
return app.mm.RunMigrations(ctx, app.configurator, fromVM)
|
||||
})
|
||||
app.UpgradeKeeper.SetUpgradeHandler("v0.10.5", func(ctx sdk.Context, _ upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) {
|
||||
return app.mm.RunMigrations(ctx, app.configurator, fromVM)
|
||||
})
|
||||
app.UpgradeKeeper.SetUpgradeHandler("v0.11.0", func(ctx sdk.Context, _ upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) {
|
||||
return app.mm.RunMigrations(ctx, app.configurator, fromVM)
|
||||
})
|
||||
}
|
||||
|
@ -6,8 +6,8 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
)
|
||||
|
||||
// The genesis state of the blockchain is represented here as a map of raw json
|
||||
// messages key'd by a identifier string.
|
||||
// GenesisState The genesis state of the blockchain is represented here as a
|
||||
// map of raw json messages key'd by a identifier string.
|
||||
// The identifier is used to determine which module genesis information belongs
|
||||
// to so it may be appropriately routed during init chain.
|
||||
// Within this application default genesis information is retrieved from
|
||||
|
48
clients/claim/client.go
Normal file
48
clients/claim/client.go
Normal file
@ -0,0 +1,48 @@
|
||||
package claim
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/planetmint/planetmint-go/config"
|
||||
"github.com/rddl-network/rddl-claim-service/client"
|
||||
"github.com/rddl-network/rddl-claim-service/types"
|
||||
)
|
||||
|
||||
var (
|
||||
RCClient client.IRCClient
|
||||
)
|
||||
|
||||
func lazyLoad() client.IRCClient {
|
||||
if RCClient != nil {
|
||||
return RCClient
|
||||
}
|
||||
cfg := config.GetConfig()
|
||||
RCClient = client.NewRCClient(cfg.ClaimHost, &http.Client{})
|
||||
return RCClient
|
||||
}
|
||||
|
||||
func PostClaim(ctx context.Context, beneficiary string, amount uint64, id uint64) (txID string, err error) {
|
||||
if beneficiary == "" {
|
||||
return txID, errors.New("beneficiary cannot be empty")
|
||||
}
|
||||
|
||||
if amount == 0 {
|
||||
return txID, errors.New("amount must be greater than 0")
|
||||
}
|
||||
|
||||
req := types.PostClaimRequest{
|
||||
Beneficiary: beneficiary,
|
||||
Amount: amount,
|
||||
ClaimID: int(id),
|
||||
}
|
||||
|
||||
client := lazyLoad()
|
||||
resp, err := client.PostClaim(ctx, req)
|
||||
if err != nil {
|
||||
return txID, fmt.Errorf("failed to post claim: %w", err)
|
||||
}
|
||||
return resp.TxID, nil
|
||||
}
|
55
clients/shamir/coordinator/client.go
Normal file
55
clients/shamir/coordinator/client.go
Normal file
@ -0,0 +1,55 @@
|
||||
package coordinator
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/planetmint/planetmint-go/config"
|
||||
"github.com/rddl-network/go-utils/tls"
|
||||
"github.com/rddl-network/shamir-coordinator-service/client"
|
||||
)
|
||||
|
||||
var (
|
||||
SCClient client.ISCClient
|
||||
)
|
||||
|
||||
func lazyLoad() client.ISCClient {
|
||||
if SCClient != nil {
|
||||
return SCClient
|
||||
}
|
||||
cfg := config.GetConfig()
|
||||
httpsClient, err := tls.Get2WayTLSClient(cfg.CertsPath)
|
||||
if err != nil {
|
||||
err := errors.New("fatal error setting up mutual tls client for shamir coordinator")
|
||||
panic(err)
|
||||
}
|
||||
SCClient = client.NewSCClient(cfg.IssuerHost, httpsClient)
|
||||
return SCClient
|
||||
}
|
||||
|
||||
func SendTokens(ctx context.Context, recipient string, amount string, asset string) (txID string, err error) {
|
||||
client := lazyLoad()
|
||||
resp, err := client.SendTokens(ctx, recipient, amount, asset)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return resp.TxID, nil
|
||||
}
|
||||
|
||||
func ReIssueAsset(ctx context.Context, asset string, amount string) (txID string, err error) {
|
||||
client := lazyLoad()
|
||||
resp, err := client.ReIssueAsset(ctx, asset, amount)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return resp.TxID, nil
|
||||
}
|
||||
|
||||
func IssueNFTAsset(ctx context.Context, name string, machineAddress string, domain string) (assetID string, contract string, hexTx string, err error) {
|
||||
client := lazyLoad()
|
||||
resp, err := client.IssueMachineNFT(ctx, name, machineAddress, domain)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return resp.Asset, resp.Contract, resp.HexTX, nil
|
||||
}
|
@ -2,25 +2,57 @@ package cmd
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
"github.com/planetmint/planetmint-go/app"
|
||||
)
|
||||
|
||||
func initSDKConfig() *sdk.Config {
|
||||
// Set prefixes
|
||||
accountPubKeyPrefix := app.AccountAddressPrefix + "pub"
|
||||
validatorAddressPrefix := app.AccountAddressPrefix + "valoper"
|
||||
validatorPubKeyPrefix := app.AccountAddressPrefix + "valoperpub"
|
||||
consNodeAddressPrefix := app.AccountAddressPrefix + "valcons"
|
||||
consNodePubKeyPrefix := app.AccountAddressPrefix + "valconspub"
|
||||
const (
|
||||
// Address prefix suffixes
|
||||
pubKeySuffix = "pub"
|
||||
valOperSuffix = "valoper"
|
||||
valOperPubSuffix = "valoperpub"
|
||||
valConsSuffix = "valcons"
|
||||
valConsPubSuffix = "valconspub"
|
||||
|
||||
// Set and seal config
|
||||
// PLMNT coin type as defined in SLIP44
|
||||
// https://github.com/satoshilabs/slips/blob/master/slip-0044.md
|
||||
plmntCoinType = 8680
|
||||
)
|
||||
|
||||
// initSDKConfig initializes and returns the SDK configuration with proper Bech32 prefixes
|
||||
// and coin type settings for the Planetmint network.
|
||||
func initSDKConfig() *sdk.Config {
|
||||
config := sdk.GetConfig()
|
||||
config.SetBech32PrefixForAccount(app.AccountAddressPrefix, accountPubKeyPrefix)
|
||||
config.SetBech32PrefixForValidator(validatorAddressPrefix, validatorPubKeyPrefix)
|
||||
config.SetBech32PrefixForConsensusNode(consNodeAddressPrefix, consNodePubKeyPrefix)
|
||||
// Set to PLMNT coin type as defined in SLIP44 (https://github.com/satoshilabs/slips/blob/master/slip-0044.md)
|
||||
config.SetCoinType(8680)
|
||||
|
||||
// Configure address prefixes
|
||||
configureBech32Prefixes(config)
|
||||
|
||||
// Set coin type for PLMNT
|
||||
config.SetCoinType(plmntCoinType)
|
||||
|
||||
// Seal the configuration to prevent further modifications
|
||||
config.Seal()
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
// configureBech32Prefixes sets up all the Bech32 prefixes for different address types
|
||||
// using the base account address prefix defined in the app package.
|
||||
func configureBech32Prefixes(config *sdk.Config) {
|
||||
// Account addresses
|
||||
config.SetBech32PrefixForAccount(
|
||||
app.AccountAddressPrefix,
|
||||
app.AccountAddressPrefix+pubKeySuffix,
|
||||
)
|
||||
|
||||
// Validator addresses
|
||||
config.SetBech32PrefixForValidator(
|
||||
app.AccountAddressPrefix+valOperSuffix,
|
||||
app.AccountAddressPrefix+valOperPubSuffix,
|
||||
)
|
||||
|
||||
// Consensus node addresses
|
||||
config.SetBech32PrefixForConsensusNode(
|
||||
app.AccountAddressPrefix+valConsSuffix,
|
||||
app.AccountAddressPrefix+valConsPubSuffix,
|
||||
)
|
||||
}
|
||||
|
@ -129,6 +129,7 @@ func initRootCmd(
|
||||
),
|
||||
genutilcli.ValidateGenesisCmd(app.ModuleBasics),
|
||||
AddGenesisAccountCmd(app.DefaultNodeHome),
|
||||
TrustWalletCmd(),
|
||||
tmcli.NewCompletionCmd(rootCmd, true),
|
||||
debug.Cmd(),
|
||||
config.Cmd(),
|
||||
@ -359,6 +360,7 @@ func initAppConfig(clientCtx client.Context) (string, interface{}) {
|
||||
type CustomAppConfig struct {
|
||||
serverconfig.Config
|
||||
PlmntConfig planetmintconfig.Config
|
||||
LibConfig lib.Config
|
||||
}
|
||||
|
||||
// Optionally allow the chain developer to overwrite the SDK's default
|
||||
@ -378,12 +380,14 @@ func initAppConfig(clientCtx client.Context) (string, interface{}) {
|
||||
// In simapp, we set the min gas prices to 0.
|
||||
srvCfg.MinGasPrices = "0stake"
|
||||
|
||||
plmntCfg := planetmintconfig.GetConfig()
|
||||
plmntCfg.SetRoot(clientCtx.HomeDir)
|
||||
plmntConfig := planetmintconfig.GetConfig()
|
||||
libConfig := lib.GetConfig()
|
||||
libConfig.SetChainID(clientCtx.ChainID)
|
||||
|
||||
customAppConfig := CustomAppConfig{
|
||||
Config: *srvCfg,
|
||||
PlmntConfig: *plmntCfg,
|
||||
PlmntConfig: *plmntConfig,
|
||||
LibConfig: *libConfig,
|
||||
}
|
||||
customAppTemplate := serverconfig.DefaultConfigTemplate + planetmintconfig.DefaultConfigTemplate
|
||||
|
||||
|
142
cmd/planetmint-god/cmd/trust_wallet.go
Normal file
142
cmd/planetmint-god/cmd/trust_wallet.go
Normal file
@ -0,0 +1,142 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/go-bip39"
|
||||
"github.com/planetmint/planetmint-go/lib/trustwallet"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
const (
|
||||
flagSerialPort = "serial-port"
|
||||
|
||||
SerialPort = "/dev/ttyACM0"
|
||||
)
|
||||
|
||||
func TrustWalletCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "trust-wallet [command]",
|
||||
Short: "Trust Wallet subcommands",
|
||||
DisableFlagParsing: true,
|
||||
SuggestionsMinimumDistance: 2,
|
||||
RunE: client.ValidateCmd,
|
||||
}
|
||||
|
||||
cmd.AddCommand(
|
||||
initializeCmd(),
|
||||
keysCmd(),
|
||||
)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func initializeCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "initialize \"[mnemonic]\"",
|
||||
Short: "Initialize a Trust Wallet",
|
||||
Long: `Initialize a Trust Wallet with a mnemonic phrase (optional). If no mnemonic is provided then one is created for you.
|
||||
Provided mnemonics must be 12 or 24 words long and adhere to bip39.`,
|
||||
RunE: initializeCmdFunc,
|
||||
Args: cobra.RangeArgs(0, 1),
|
||||
}
|
||||
|
||||
cmd.Flags().String(flagSerialPort, SerialPort, "The serial port your Trust Wallet is connected to")
|
||||
flags.AddQueryFlagsToCmd(cmd)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func initializeCmdFunc(cmd *cobra.Command, args []string) error {
|
||||
serialPort, err := cmd.Flags().GetString(flagSerialPort)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
connector, err := trustwallet.NewTrustWalletConnector(serialPort)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// create mnemonic if non is given
|
||||
if len(args) == 0 {
|
||||
cmd.Println("Initializing Trust Wallet. This may take a few seconds...")
|
||||
mnemonic, err := connector.CreateMnemonic()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd.Println("Created mnemonic:")
|
||||
cmd.Println(mnemonic + "\n")
|
||||
cmd.Println("IMPORTANT: Store your mnemonic securely in an offline location, such as a hardware wallet, encrypted USB, or paper stored in a safe, never online or on cloud storage!")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// recover from given mnemonic
|
||||
cmd.Println("Recovering Trust Wallet from mnemonic...")
|
||||
words := strings.Split(args[0], " ")
|
||||
if len(words) != 12 && len(words) != 24 {
|
||||
return errors.New("expected length of mnemonic is 12 or 24, got: " + strconv.Itoa(len(words)))
|
||||
}
|
||||
mnemonic := strings.Join(words, " ")
|
||||
if !bip39.IsMnemonicValid(mnemonic) {
|
||||
return errors.New("invalid mnemonic, please check provided words")
|
||||
}
|
||||
response, err := connector.RecoverFromMnemonic(mnemonic)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cmd.Println(response)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func keysCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "keys",
|
||||
Short: "Retrieve keys from Trust Wallet",
|
||||
Long: `Retrieve keys from Trust Wallet. Includes:
|
||||
planetmint address,
|
||||
extended planetmint public key,
|
||||
extended liquid public key,
|
||||
raw planetmint key (hex encoded)`,
|
||||
RunE: keysCmdFunc,
|
||||
Args: cobra.ExactArgs(0),
|
||||
}
|
||||
|
||||
cmd.Flags().String(flagSerialPort, SerialPort, "The serial port your Trust Wallet is connected to")
|
||||
flags.AddQueryFlagsToCmd(cmd)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func keysCmdFunc(cmd *cobra.Command, _ []string) error {
|
||||
serialPort, err := cmd.Flags().GetString(flagSerialPort)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
connector, err := trustwallet.NewTrustWalletConnector(serialPort)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd.Println("Retrieving keys from Trust Wallet. This may take a few seconds...")
|
||||
cmd.Println()
|
||||
|
||||
keys, err := connector.GetPlanetmintKeys()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd.Println("- address: " + keys.PlanetmintAddress)
|
||||
cmd.Printf(" pubkey: [{\"@type\":\"PlanetmintExtended\",\"key\":\"%s\"},{\"@type\":\"PlanetmintHex\",\"key\":\"%s\"},{\"@type\":\"LiquidExtended\",\"key\":\"%s\"}]\n", keys.ExtendedPlanetmintPubkey, keys.RawPlanetmintPubkey, keys.ExtendedLiquidPubkey)
|
||||
cmd.Println(" type: hardware")
|
||||
|
||||
return nil
|
||||
}
|
165
config/config.go
165
config/config.go
@ -2,7 +2,13 @@ package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/planetmint/planetmint-go/lib"
|
||||
"github.com/planetmint/planetmint-go/lib/trustwallet"
|
||||
"github.com/rddl-network/go-utils/logger"
|
||||
)
|
||||
|
||||
const DefaultConfigTemplate = `
|
||||
@ -11,45 +17,40 @@ const DefaultConfigTemplate = `
|
||||
###############################################################################
|
||||
|
||||
[planetmint]
|
||||
|
||||
asset-registry-endpoint = "{{ .PlmntConfig.AssetRegistryEndpoint }}"
|
||||
token-denom = "{{ .PlmntConfig.TokenDenom }}"
|
||||
stake-denom = "{{ .PlmntConfig.StakeDenom }}"
|
||||
fee-denom = "{{ .PlmntConfig.FeeDenom }}"
|
||||
pop-epochs = {{ .PlmntConfig.PoPEpochs }}
|
||||
rpc-host = "{{ .PlmntConfig.RPCHost }}"
|
||||
rpc-port = {{ .PlmntConfig.RPCPort }}
|
||||
rpc-user = "{{ .PlmntConfig.RPCUser }}"
|
||||
rpc-password = "{{ .PlmntConfig.RPCPassword }}"
|
||||
issuance-service-dir = "{{ .PlmntConfig.IssuanceServiceDir }}"
|
||||
reissuance-asset = "{{ .PlmntConfig.ReissuanceAsset }}"
|
||||
validator-address = "{{ .PlmntConfig.ValidatorAddress }}"
|
||||
distribution-address-inv = "{{ .PlmntConfig.DistributionAddrInv }}"
|
||||
distribution-address-dao = "{{ .PlmntConfig.DistributionAddrDAO }}"
|
||||
distribution-address-pop = "{{ .PlmntConfig.DistributionAddrPoP }}"
|
||||
distribution-epochs = {{ .PlmntConfig.DistributionEpochs }}
|
||||
|
||||
certs-path = "{{ .PlmntConfig.CertsPath }}"
|
||||
claim-host = "{{ .PlmntConfig.ClaimHost }}"
|
||||
issuer-host = "{{ .PlmntConfig.IssuerHost }}"
|
||||
mqtt-domain = "{{ .PlmntConfig.MqttDomain }}"
|
||||
mqtt-password = "{{ .PlmntConfig.MqttPassword }}"
|
||||
mqtt-port = {{ .PlmntConfig.MqttPort }}
|
||||
mqtt-tls = {{ .PlmntConfig.MqttTLS }}
|
||||
mqtt-user = "{{ .PlmntConfig.MqttUser }}"
|
||||
`
|
||||
|
||||
// ValAddr to be reomved see: https://github.com/planetmint/planetmint-go/issues/454
|
||||
const ValAddr = "VALIDATOR_ADDRESS"
|
||||
|
||||
const (
|
||||
defaultCertsPath = "./certs/"
|
||||
defaultClaimHost = "https://testnet-p2r.rddl.io"
|
||||
defaultIssuerHost = "https://testnet-issuer.rddl.io"
|
||||
defaultMqttDomain = "testnet-mqtt.rddl.io"
|
||||
defaultMqttPassword = "password"
|
||||
defaultMqttPort = 1886
|
||||
defaultMqttTLS = true
|
||||
defaultMqttUser = "user"
|
||||
)
|
||||
|
||||
// Config defines Planetmint's top level configuration
|
||||
type Config struct {
|
||||
AssetRegistryEndpoint string `json:"asset-registry-endpoint" mapstructure:"asset-registry-endpoint"`
|
||||
TokenDenom string `json:"token-denom" mapstructure:"token-denom"`
|
||||
StakeDenom string `json:"stake-denom" mapstructure:"stake-denom"`
|
||||
FeeDenom string `json:"fee-denom" mapstructure:"fee-denom"`
|
||||
ConfigRootDir string `json:"config-root-dir" mapstructure:"config-root-dir"`
|
||||
PoPEpochs int `json:"pop-epochs" mapstructure:"pop-epochs"` //nolint: tagliatelle // json(kebab): got 'pop-epochs' want 'po-p-epochs'
|
||||
RPCHost string `json:"rpc-host" mapstructure:"rpc-host"`
|
||||
RPCPort int `json:"rpc-port" mapstructure:"rpc-port"`
|
||||
RPCUser string `json:"rpc-user" mapstructure:"rpc-user"`
|
||||
RPCPassword string `json:"rpc-password" mapstructure:"rpc-password"`
|
||||
IssuanceServiceDir string `json:"issuance-service-dir" mapstructure:"issuance-service-dir"`
|
||||
ReissuanceAsset string `json:"reissuance-asset" mapstructure:"reissuance-asset"`
|
||||
ValidatorAddress string `json:"validator-address" mapstructure:"validator-address"`
|
||||
DistributionAddrInv string `json:"distribution-addr-inv" mapstructure:"distribution-addr-inv"`
|
||||
DistributionAddrDAO string `json:"distribution-addr-dao" mapstructure:"distribution-addr-dao"`
|
||||
DistributionAddrPoP string `json:"distribution-addr-pop" mapstructure:"distribution-addr-pop"` //nolint: tagliatelle // json(kebab): got 'distribution-addr-pop' want 'distribution-addr-po-p'
|
||||
DistributionEpochs int `json:"distribution-epochs" mapstructure:"distribution-epochs"`
|
||||
CertsPath string `json:"certs-path" mapstructure:"certs-path"`
|
||||
ClaimHost string `json:"claim-host" mapstructure:"claim-host"`
|
||||
IssuerHost string `json:"issuer-host" mapstructure:"issuer-host"`
|
||||
MqttDomain string `json:"mqtt-domain" mapstructure:"mqtt-domain"`
|
||||
MqttPassword string `json:"mqtt-password" mapstructure:"mqtt-password"`
|
||||
MqttPort int `json:"mqtt-port" mapstructure:"mqtt-port"`
|
||||
MqttTLS bool `json:"mqtt-tls" mapstructure:"mqtt-tls"`
|
||||
MqttUser string `json:"mqtt-user" mapstructure:"mqtt-user"`
|
||||
}
|
||||
|
||||
// cosmos-sdk wide global singleton
|
||||
@ -61,23 +62,14 @@ var (
|
||||
// DefaultConfig returns planetmint's default configuration.
|
||||
func DefaultConfig() *Config {
|
||||
return &Config{
|
||||
AssetRegistryEndpoint: "https://assets.rddl.io/register_asset",
|
||||
TokenDenom: "plmnt",
|
||||
StakeDenom: "plmntstake",
|
||||
FeeDenom: "plmnt",
|
||||
ConfigRootDir: "",
|
||||
PoPEpochs: 24, // 24 CometBFT epochs of 5s equate 120s
|
||||
RPCHost: "localhost",
|
||||
RPCPort: 18884,
|
||||
RPCUser: "user",
|
||||
RPCPassword: "password",
|
||||
IssuanceServiceDir: "/opt/issuer_service",
|
||||
ReissuanceAsset: "7add40beb27df701e02ee85089c5bc0021bc813823fedb5f1dcb5debda7f3da9",
|
||||
ValidatorAddress: "plmnt1w5dww335zhh98pzv783hqre355ck3u4w4hjxcx",
|
||||
DistributionAddrInv: "vjTyRN2G42Yq3T5TJBecHj1dF1xdhKF89hKV4HJN3uXxUbaVGVR76hAfVRQqQCovWaEpar7G5qBBprFG",
|
||||
DistributionAddrDAO: "vjU8eMzU3JbUWZEpVANt2ePJuPWSPixgjiSj2jDMvkVVQQi2DDnZuBRVX4Ygt5YGBf5zvTWCr1ntdqYH",
|
||||
DistributionAddrPoP: "vjTvXCFSReRsZ7grdsAreRR12KuKpDw8idueQJK9Yh1BYS7ggAqgvCxCgwh13KGK6M52y37HUmvr4GdD",
|
||||
DistributionEpochs: 17280, // CometBFT epochs of 5s equate 1 day (12*60*24)
|
||||
CertsPath: defaultCertsPath,
|
||||
ClaimHost: defaultClaimHost,
|
||||
IssuerHost: defaultIssuerHost,
|
||||
MqttDomain: defaultMqttDomain,
|
||||
MqttPassword: defaultMqttPassword,
|
||||
MqttPort: defaultMqttPort,
|
||||
MqttTLS: defaultMqttTLS,
|
||||
MqttUser: defaultMqttUser,
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,19 +81,72 @@ func GetConfig() *Config {
|
||||
return plmntConfig
|
||||
}
|
||||
|
||||
func (config *Config) SetRoot(root string) *Config {
|
||||
config.ConfigRootDir = root
|
||||
return config
|
||||
}
|
||||
|
||||
// SetWatchmenConfig sets Planetmint's configuration
|
||||
// SetPlanetmintConfig sets Planetmint's configuration
|
||||
func (config *Config) SetPlanetmintConfig(planetmintconfig interface{}) {
|
||||
jsonConfig, err := json.Marshal(planetmintconfig)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = json.Unmarshal(jsonConfig, &config)
|
||||
if err != nil {
|
||||
if err := json.Unmarshal(jsonConfig, config); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// GetNodeAddress retrieves the validator address through multiple methods
|
||||
func (config *Config) GetNodeAddress() (address string) {
|
||||
var err error
|
||||
// Check environment variable first <- this is used for test cases only
|
||||
if address = os.Getenv(ValAddr); address != "" {
|
||||
return
|
||||
}
|
||||
|
||||
libConfig := lib.GetConfig()
|
||||
|
||||
// Handle no Trust Wallet connected scenario
|
||||
if libConfig.GetSerialPort() == "" {
|
||||
address, err = getKeyringAddress(libConfig)
|
||||
} else { // Handle Trust Wallet connected scenario
|
||||
address, err = getTrustWalletAddress(libConfig)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
msg := "Cannot get node address. Please configure a Trust Wallet or define at least one key pair in the utilized keyring."
|
||||
newError := errors.New(msg + ": " + err.Error())
|
||||
panic(newError)
|
||||
}
|
||||
return address
|
||||
}
|
||||
|
||||
// getKeyringAddress retrieves the default validator address
|
||||
func getKeyringAddress(libConfig *lib.Config) (address string, err error) {
|
||||
defaultRecord, err := libConfig.GetDefaultValidatorRecord()
|
||||
if err != nil {
|
||||
logger.GetLogger(logger.ERROR).Error("msg", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
addr, err := defaultRecord.GetAddress()
|
||||
if err != nil {
|
||||
logger.GetLogger(logger.ERROR).Error("msg", err.Error())
|
||||
return
|
||||
}
|
||||
address = addr.String()
|
||||
return
|
||||
}
|
||||
|
||||
// getTrustWalletAddress retrieves validator address from Trust Wallet
|
||||
func getTrustWalletAddress(libConfig *lib.Config) (address string, err error) {
|
||||
connector, err := trustwallet.NewTrustWalletConnector(libConfig.GetSerialPort())
|
||||
if err != nil {
|
||||
logger.GetLogger(logger.ERROR).Error("msg", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
keys, err := connector.GetPlanetmintKeys()
|
||||
if err != nil {
|
||||
logger.GetLogger(logger.ERROR).Error("msg", err.Error())
|
||||
return
|
||||
}
|
||||
address = keys.PlanetmintAddress
|
||||
return
|
||||
}
|
||||
|
@ -5,7 +5,12 @@ import (
|
||||
)
|
||||
|
||||
// LiquidNetParams defines the network parameters for the Liquid network.
|
||||
var LiquidNetParams chaincfg.Params
|
||||
var LiquidNetParams = func() chaincfg.Params {
|
||||
params := chaincfg.MainNetParams
|
||||
params.Name = "liquidv1"
|
||||
params.HDCoinType = 1776
|
||||
return params
|
||||
}()
|
||||
|
||||
// PlmntNetParams defines the network parameters for the Planetmint network.
|
||||
var PlmntNetParams = chaincfg.Params{
|
||||
@ -21,17 +26,9 @@ var PlmntNetParams = chaincfg.Params{
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Not allowed to register LiquidNetParams, because it's just another
|
||||
// Bitcoin network with different coin type.
|
||||
// See https://github.com/satoshilabs/slips/blob/master/slip-0044.md
|
||||
LiquidNetParams = chaincfg.MainNetParams
|
||||
LiquidNetParams.Name = "liquidv1"
|
||||
LiquidNetParams.HDCoinType = 1776
|
||||
|
||||
// Need to register PlmntNetParams, otherwise we get an "unknown hd
|
||||
// private extended key bytes" error.
|
||||
err := chaincfg.Register(&PlmntNetParams)
|
||||
if err != nil {
|
||||
if err := chaincfg.Register(&PlmntNetParams); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
76
contrib/devtools/Makefile
Normal file
76
contrib/devtools/Makefile
Normal file
@ -0,0 +1,76 @@
|
||||
###
|
||||
# Find OS and Go environment
|
||||
# GO contains the Go binary
|
||||
# FS contains the OS file separator
|
||||
###
|
||||
ifeq ($(OS),Windows_NT)
|
||||
GO := $(shell where go.exe 2> NUL)
|
||||
FS := "\\"
|
||||
else
|
||||
GO := $(shell command -v go 2> /dev/null)
|
||||
FS := "/"
|
||||
endif
|
||||
|
||||
ifeq ($(GO),)
|
||||
$(error could not find go. Is it in PATH? $(GO))
|
||||
endif
|
||||
|
||||
###############################################################################
|
||||
### Functions ###
|
||||
###############################################################################
|
||||
|
||||
go_get = $(if $(findstring Windows_NT,$(OS)),\
|
||||
IF NOT EXIST $(GITHUBDIR)$(FS)$(1)$(FS) ( mkdir $(GITHUBDIR)$(FS)$(1) ) else (cd .) &\
|
||||
IF NOT EXIST $(GITHUBDIR)$(FS)$(1)$(FS)$(2)$(FS) ( cd $(GITHUBDIR)$(FS)$(1) && git clone https://github.com/$(1)/$(2) ) else (cd .) &\
|
||||
,\
|
||||
mkdir -p $(GITHUBDIR)$(FS)$(1) &&\
|
||||
(test ! -d $(GITHUBDIR)$(FS)$(1)$(FS)$(2) && cd $(GITHUBDIR)$(FS)$(1) && git clone https://github.com/$(1)/$(2)) || true &&\
|
||||
)\
|
||||
cd $(GITHUBDIR)$(FS)$(1)$(FS)$(2) && git fetch origin && git checkout -q $(3)
|
||||
|
||||
mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
|
||||
mkfile_dir := $(shell cd $(shell dirname $(mkfile_path)); pwd)
|
||||
|
||||
|
||||
###############################################################################
|
||||
### Tools ###
|
||||
###############################################################################
|
||||
|
||||
PREFIX ?= /usr/local
|
||||
BIN ?= $(PREFIX)/bin
|
||||
UNAME_S ?= $(shell uname -s)
|
||||
UNAME_M ?= $(shell uname -m)
|
||||
|
||||
GOPATH ?= $(shell $(GO) env GOPATH)
|
||||
GITHUBDIR := $(GOPATH)$(FS)src$(FS)github.com
|
||||
|
||||
BUF_VERSION ?= 0.11.0
|
||||
|
||||
TOOLS_DESTDIR ?= $(GOPATH)/bin
|
||||
STATIK = $(TOOLS_DESTDIR)/statik
|
||||
RUNSIM = $(TOOLS_DESTDIR)/runsim
|
||||
|
||||
tools: tools-stamp
|
||||
tools-stamp: statik runsim
|
||||
# Create dummy file to satisfy dependency and avoid
|
||||
# rebuilding when this Makefile target is hit twice
|
||||
# in a row.
|
||||
touch $@
|
||||
|
||||
# Install the runsim binary
|
||||
statik: $(STATIK)
|
||||
$(STATIK):
|
||||
@echo "Installing statik..."
|
||||
@go install github.com/rakyll/statik@v0.1.6
|
||||
|
||||
# Install the runsim binary
|
||||
runsim: $(RUNSIM)
|
||||
$(RUNSIM):
|
||||
@echo "Installing runsim..."
|
||||
@go install github.com/cosmos/tools/cmd/runsim@v1.0.0
|
||||
|
||||
tools-clean:
|
||||
rm -f $(STATIK) $(GOLANGCI_LINT) $(RUNSIM)
|
||||
rm -f tools-stamp
|
||||
|
||||
.PHONY: tools-clean statik runsim
|
1639
docs/static/openapi.yml
vendored
1639
docs/static/openapi.yml
vendored
File diff suppressed because it is too large
Load Diff
7
errormsg/error.go
Normal file
7
errormsg/error.go
Normal file
@ -0,0 +1,7 @@
|
||||
package errormsg
|
||||
|
||||
var (
|
||||
CouldNotGetValidatorIdentity = "could not get validator identity"
|
||||
ErrorInvalidCreator = "invalid creator address (%s)"
|
||||
InvalidRequest = "invalid request"
|
||||
)
|
156
go.mod
156
go.mod
@ -1,58 +1,67 @@
|
||||
module github.com/planetmint/planetmint-go
|
||||
|
||||
go 1.19
|
||||
go 1.22
|
||||
|
||||
require (
|
||||
cosmossdk.io/api v0.3.1
|
||||
cosmossdk.io/errors v1.0.0
|
||||
cosmossdk.io/math v1.1.2
|
||||
github.com/btcsuite/btcd v0.23.2
|
||||
github.com/btcsuite/btcd/btcutil v1.1.2
|
||||
github.com/cometbft/cometbft v0.37.2
|
||||
github.com/cometbft/cometbft-db v0.7.0
|
||||
github.com/cosmos/cosmos-proto v1.0.0-beta.2
|
||||
github.com/cosmos/cosmos-sdk v0.47.5
|
||||
cosmossdk.io/depinject v1.0.0-alpha.4
|
||||
cosmossdk.io/errors v1.0.1
|
||||
cosmossdk.io/math v1.4.0
|
||||
cosmossdk.io/simapp v0.0.0-20230323161446-0af178d721ff
|
||||
github.com/btcsuite/btcd v0.24.0
|
||||
github.com/btcsuite/btcd/btcutil v1.1.5
|
||||
github.com/cometbft/cometbft v0.37.5
|
||||
github.com/cometbft/cometbft-db v0.8.0
|
||||
github.com/cosmos/cosmos-proto v1.0.0-beta.5
|
||||
github.com/cosmos/cosmos-sdk v0.47.14
|
||||
github.com/cosmos/go-bip39 v1.0.0
|
||||
github.com/cosmos/gogoproto v1.4.10
|
||||
github.com/cosmos/ibc-go/v7 v7.1.0
|
||||
github.com/cosmos/gogoproto v1.7.0
|
||||
github.com/cosmos/ibc-go/v7 v7.4.0
|
||||
github.com/eclipse/paho.mqtt.golang v1.4.3
|
||||
github.com/golang/mock v1.6.0
|
||||
github.com/golang/protobuf v1.5.3
|
||||
github.com/golang/protobuf v1.5.4
|
||||
github.com/gorilla/mux v1.8.0
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.2
|
||||
github.com/planetmint/planetmint-go/lib v0.2.1
|
||||
github.com/spf13/cast v1.5.0
|
||||
github.com/spf13/cobra v1.6.1
|
||||
github.com/planetmint/planetmint-go/lib v0.6.0
|
||||
github.com/rddl-network/elements-rpc v1.2.1
|
||||
github.com/rddl-network/go-utils v0.2.3
|
||||
github.com/rddl-network/rddl-claim-service v0.3.2
|
||||
github.com/rddl-network/rddl-claim-service/client v0.0.6
|
||||
github.com/rddl-network/shamir-coordinator-service v0.7.7
|
||||
github.com/rddl-network/shamir-coordinator-service/client v0.1.0
|
||||
github.com/spf13/cast v1.6.0
|
||||
github.com/spf13/cobra v1.8.0
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/stretchr/testify v1.8.4
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230629202037-9506855d4529
|
||||
google.golang.org/grpc v1.56.3
|
||||
github.com/stretchr/testify v1.9.0
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80
|
||||
google.golang.org/grpc v1.62.1
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
gotest.tools v2.2.0+incompatible
|
||||
sigs.k8s.io/yaml v1.3.0
|
||||
sigs.k8s.io/yaml v1.4.0
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.110.4 // indirect
|
||||
cloud.google.com/go/compute v1.20.1 // indirect
|
||||
cloud.google.com/go v0.112.0 // indirect
|
||||
cloud.google.com/go/compute v1.23.3 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
||||
cloud.google.com/go/iam v1.1.0 // indirect
|
||||
cloud.google.com/go/storage v1.30.1 // indirect
|
||||
cloud.google.com/go/iam v1.1.5 // indirect
|
||||
cloud.google.com/go/storage v1.36.0 // indirect
|
||||
cosmossdk.io/core v0.5.1 // indirect
|
||||
cosmossdk.io/depinject v1.0.0-alpha.4 // indirect
|
||||
cosmossdk.io/log v1.2.1 // indirect
|
||||
cosmossdk.io/log v1.4.1 // indirect
|
||||
cosmossdk.io/tools/rosetta v0.2.1 // indirect
|
||||
filippo.io/edwards25519 v1.0.0 // indirect
|
||||
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect
|
||||
github.com/99designs/keyring v1.2.1 // indirect
|
||||
github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect
|
||||
github.com/ChainSafe/go-schnorrkel v1.0.0 // indirect
|
||||
github.com/armon/go-metrics v0.4.1 // indirect
|
||||
github.com/aws/aws-sdk-go v1.44.203 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
|
||||
github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect
|
||||
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect
|
||||
github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.1.3 // indirect
|
||||
github.com/cespare/xxhash v1.1.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
@ -65,40 +74,43 @@ require (
|
||||
github.com/confio/ics23/go v0.9.0 // indirect
|
||||
github.com/cosmos/btcutil v1.0.5 // indirect
|
||||
github.com/cosmos/gogogateway v1.2.0 // indirect
|
||||
github.com/cosmos/iavl v0.20.0 // indirect
|
||||
github.com/cosmos/iavl v0.20.1 // indirect
|
||||
github.com/cosmos/ics23/go v0.10.0 // indirect
|
||||
github.com/cosmos/ledger-cosmos-go v0.12.1 // indirect
|
||||
github.com/cosmos/ledger-cosmos-go v0.12.4 // indirect
|
||||
github.com/cosmos/rosetta-sdk-go v0.10.0 // indirect
|
||||
github.com/creachadair/taskgroup v0.4.2 // indirect
|
||||
github.com/creack/goselect v0.1.2 // indirect
|
||||
github.com/danieljoos/wincred v1.1.2 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect
|
||||
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect
|
||||
github.com/dgraph-io/badger/v2 v2.2007.4 // indirect
|
||||
github.com/dgraph-io/ristretto v0.1.1 // indirect
|
||||
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/dvsekhvalnov/jose2go v1.5.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.2 // indirect
|
||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||
github.com/dvsekhvalnov/jose2go v1.6.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/getsentry/sentry-go v0.23.0 // indirect
|
||||
github.com/ghodss/yaml v1.0.0 // indirect
|
||||
github.com/go-kit/kit v0.12.0 // indirect
|
||||
github.com/go-kit/log v0.2.1 // indirect
|
||||
github.com/go-logfmt/logfmt v0.6.0 // indirect
|
||||
github.com/go-logr/logr v1.3.0 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect
|
||||
github.com/gogo/googleapis v1.4.1 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/glog v1.1.0 // indirect
|
||||
github.com/golang/glog v1.2.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/btree v1.1.2 // indirect
|
||||
github.com/google/go-cmp v0.5.9 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/google/orderedcode v0.0.1 // indirect
|
||||
github.com/google/s2a-go v0.1.4 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.11.0 // indirect
|
||||
github.com/google/s2a-go v0.1.7 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.12.0 // indirect
|
||||
github.com/gorilla/handlers v1.5.1 // indirect
|
||||
github.com/gorilla/websocket v1.5.0 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
|
||||
@ -106,7 +118,7 @@ require (
|
||||
github.com/gtank/merlin v0.1.1 // indirect
|
||||
github.com/gtank/ristretto255 v0.1.2 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-getter v1.7.1 // indirect
|
||||
github.com/hashicorp/go-getter v1.7.5 // indirect
|
||||
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
|
||||
github.com/hashicorp/go-safetemp v1.0.0 // indirect
|
||||
github.com/hashicorp/go-version v1.6.0 // indirect
|
||||
@ -118,15 +130,16 @@ require (
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/jmhodges/levigo v1.0.0 // indirect
|
||||
github.com/klauspost/compress v1.16.3 // indirect
|
||||
github.com/klauspost/compress v1.17.0 // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/lib/pq v1.10.7 // indirect
|
||||
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
|
||||
github.com/linxGnu/grocksdb v1.7.16 // indirect
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
github.com/manifoldco/promptui v0.9.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||
github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect
|
||||
github.com/minio/highwayhash v1.0.2 // indirect
|
||||
@ -134,10 +147,10 @@ require (
|
||||
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/mtibben/percent v0.2.1 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.7 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
|
||||
github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_golang v1.14.0 // indirect
|
||||
github.com/prometheus/client_model v0.3.0 // indirect
|
||||
github.com/prometheus/common v0.42.0 // indirect
|
||||
@ -146,38 +159,47 @@ require (
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
|
||||
github.com/rogpeppe/go-internal v1.11.0 // indirect
|
||||
github.com/rs/cors v1.8.3 // indirect
|
||||
github.com/rs/zerolog v1.30.0 // indirect
|
||||
github.com/rs/zerolog v1.33.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
github.com/sasha-s/go-deadlock v0.3.1 // indirect
|
||||
github.com/spf13/afero v1.9.3 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/spf13/viper v1.15.0 // indirect
|
||||
github.com/subosito/gotenv v1.4.2 // indirect
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect
|
||||
github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
github.com/spf13/afero v1.11.0 // indirect
|
||||
github.com/spf13/viper v1.18.2 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/tendermint/go-amino v0.16.0 // indirect
|
||||
github.com/tidwall/btree v1.6.0 // indirect
|
||||
github.com/ulikunitz/xz v0.5.11 // indirect
|
||||
github.com/zondax/hid v0.9.1 // indirect
|
||||
github.com/zondax/ledger-go v0.14.1 // indirect
|
||||
github.com/zondax/hid v0.9.2 // indirect
|
||||
github.com/zondax/ledger-go v0.14.3 // indirect
|
||||
go.bug.st/serial v1.6.2 // indirect
|
||||
go.etcd.io/bbolt v1.3.7 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
golang.org/x/crypto v0.14.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20230711153332-06a737ee72cb // indirect
|
||||
golang.org/x/net v0.17.0 // indirect
|
||||
golang.org/x/oauth2 v0.8.0 // indirect
|
||||
golang.org/x/sys v0.13.0 // indirect
|
||||
golang.org/x/term v0.13.0 // indirect
|
||||
golang.org/x/text v0.13.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||
google.golang.org/api v0.126.0 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect
|
||||
google.golang.org/protobuf v1.31.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 // indirect
|
||||
go.opentelemetry.io/otel v1.21.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.21.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.21.0 // indirect
|
||||
go.uber.org/atomic v1.10.0 // indirect
|
||||
go.uber.org/multierr v1.9.0 // indirect
|
||||
golang.org/x/crypto v0.21.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
|
||||
golang.org/x/net v0.23.0 // indirect
|
||||
golang.org/x/oauth2 v0.16.0 // indirect
|
||||
golang.org/x/sync v0.6.0 // indirect
|
||||
golang.org/x/sys v0.22.0 // indirect
|
||||
golang.org/x/term v0.18.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
google.golang.org/api v0.155.0 // indirect
|
||||
google.golang.org/appengine v1.6.8 // indirect
|
||||
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect
|
||||
google.golang.org/protobuf v1.33.0 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
nhooyr.io/websocket v1.8.6 // indirect
|
||||
pgregory.net/rapid v0.5.5 // indirect
|
||||
pgregory.net/rapid v1.1.0 // indirect
|
||||
)
|
||||
|
||||
replace github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
|
||||
|
399
go.sum
399
go.sum
@ -3,7 +3,6 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
|
||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
||||
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||
cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
||||
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
|
||||
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
|
||||
@ -16,7 +15,6 @@ cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOY
|
||||
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
||||
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
|
||||
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
|
||||
cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
|
||||
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
|
||||
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
|
||||
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
|
||||
@ -32,8 +30,8 @@ cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w9
|
||||
cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc=
|
||||
cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU=
|
||||
cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA=
|
||||
cloud.google.com/go v0.110.4 h1:1JYyxKMN9hd5dR2MYTPWkGUgcoxVVhg0LKNKEo0qvmk=
|
||||
cloud.google.com/go v0.110.4/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI=
|
||||
cloud.google.com/go v0.112.0 h1:tpFCD7hpHFlQ8yPwT3x+QeXqc2T6+n6T+hmABHfDUSM=
|
||||
cloud.google.com/go v0.112.0/go.mod h1:3jEEVwZ/MHU4djK5t5RHuKOA/GbLddgTdVubX1qnPD4=
|
||||
cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw=
|
||||
cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY=
|
||||
cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI=
|
||||
@ -70,8 +68,8 @@ cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz
|
||||
cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU=
|
||||
cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U=
|
||||
cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU=
|
||||
cloud.google.com/go/compute v1.20.1 h1:6aKEtlUiwEpJzM001l0yFkpXmUVXaN8W+fbkb2AZNbg=
|
||||
cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM=
|
||||
cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk=
|
||||
cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI=
|
||||
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
|
||||
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
|
||||
cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I=
|
||||
@ -111,8 +109,8 @@ cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y97
|
||||
cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc=
|
||||
cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY=
|
||||
cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc=
|
||||
cloud.google.com/go/iam v1.1.0 h1:67gSqaPukx7O8WLLHMa0PNs3EBGd2eE4d+psbO/CO94=
|
||||
cloud.google.com/go/iam v1.1.0/go.mod h1:nxdHjaKfCr7fNYx/HJMM8LgiMugmveWlkatear5gVyk=
|
||||
cloud.google.com/go/iam v1.1.5 h1:1jTsCu4bcsNsE4iiqNT5SHwrDRCfRmIaaaVFhRveTJI=
|
||||
cloud.google.com/go/iam v1.1.5/go.mod h1:rB6P/Ic3mykPbFio+vo7403drjlgvoWfYpJhMXEbzv8=
|
||||
cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic=
|
||||
cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI=
|
||||
cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8=
|
||||
@ -170,12 +168,11 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo
|
||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
|
||||
cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y=
|
||||
cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc=
|
||||
cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s=
|
||||
cloud.google.com/go/storage v1.30.1 h1:uOdMxAs8HExqBlnLtnQyP0YkvbiDpdGShGKtx6U/oNM=
|
||||
cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E=
|
||||
cloud.google.com/go/storage v1.36.0 h1:P0mOkAcaJxhCTvAkMhxMfrTKiNcub4YmmPBtlhAyTr8=
|
||||
cloud.google.com/go/storage v1.36.0/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8=
|
||||
cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw=
|
||||
cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g=
|
||||
cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU=
|
||||
@ -193,12 +190,14 @@ cosmossdk.io/core v0.5.1 h1:vQVtFrIYOQJDV3f7rw4pjjVqc1id4+mE0L9hHP66pyI=
|
||||
cosmossdk.io/core v0.5.1/go.mod h1:KZtwHCLjcFuo0nmDc24Xy6CRNEL9Vl/MeimQ2aC7NLE=
|
||||
cosmossdk.io/depinject v1.0.0-alpha.4 h1:PLNp8ZYAMPTUKyG9IK2hsbciDWqna2z1Wsl98okJopc=
|
||||
cosmossdk.io/depinject v1.0.0-alpha.4/go.mod h1:HeDk7IkR5ckZ3lMGs/o91AVUc7E596vMaOmslGFM3yU=
|
||||
cosmossdk.io/errors v1.0.0 h1:nxF07lmlBbB8NKQhtJ+sJm6ef5uV1XkvPXG2bUntb04=
|
||||
cosmossdk.io/errors v1.0.0/go.mod h1:+hJZLuhdDE0pYN8HkOrVNwrIOYvUGnn6+4fjnJs/oV0=
|
||||
cosmossdk.io/log v1.2.1 h1:Xc1GgTCicniwmMiKwDxUjO4eLhPxoVdI9vtMW8Ti/uk=
|
||||
cosmossdk.io/log v1.2.1/go.mod h1:GNSCc/6+DhFIj1aLn/j7Id7PaO8DzNylUZoOYBL9+I4=
|
||||
cosmossdk.io/math v1.1.2 h1:ORZetZCTyWkI5GlZ6CZS28fMHi83ZYf+A2vVnHNzZBM=
|
||||
cosmossdk.io/math v1.1.2/go.mod h1:l2Gnda87F0su8a/7FEKJfFdJrM0JZRXQaohlgJeyQh0=
|
||||
cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0=
|
||||
cosmossdk.io/errors v1.0.1/go.mod h1:MeelVSZThMi4bEakzhhhE/CKqVv3nOJDA25bIqRDu/U=
|
||||
cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM=
|
||||
cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU=
|
||||
cosmossdk.io/math v1.4.0 h1:XbgExXFnXmF/CccPPEto40gOO7FpWu9yWNAZPN3nkNQ=
|
||||
cosmossdk.io/math v1.4.0/go.mod h1:O5PkD4apz2jZs4zqFdTr16e1dcaQCc5z6lkEnrrppuk=
|
||||
cosmossdk.io/simapp v0.0.0-20230323161446-0af178d721ff h1:P1ialzTepD1oxdNPYc5N8Eggq3RdejZq3cJs8YYMs9Y=
|
||||
cosmossdk.io/simapp v0.0.0-20230323161446-0af178d721ff/go.mod h1:AKzx6Mb544LjJ9RHmGFHjY9rEOLiUAi8I0F727TR0dY=
|
||||
cosmossdk.io/tools/rosetta v0.2.1 h1:ddOMatOH+pbxWbrGJKRAawdBkPYLfKXutK9IETnjYxw=
|
||||
cosmossdk.io/tools/rosetta v0.2.1/go.mod h1:Pqdc1FdvkNV3LcNIkYWt2RQY6IP1ge6YWZk8MhhO9Hw=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
@ -209,14 +208,17 @@ github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN
|
||||
github.com/99designs/keyring v1.2.1 h1:tYLp1ULvO7i3fI5vE21ReQuj99QFSs7lGm0xWyJo87o=
|
||||
github.com/99designs/keyring v1.2.1/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg=
|
||||
github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4=
|
||||
github.com/ChainSafe/go-schnorrkel v1.0.0 h1:3aDA67lAykLaG1y3AOjs88dMxC88PgUuHRrLeDnvGIM=
|
||||
github.com/ChainSafe/go-schnorrkel v1.0.0/go.mod h1:dpzHYVxLZcp8pjlV+O+UR8K0Hp/z7vcchBSbMBEhCw4=
|
||||
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||
github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=
|
||||
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
|
||||
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
|
||||
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw=
|
||||
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
|
||||
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||
@ -224,6 +226,7 @@ github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMx
|
||||
github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE=
|
||||
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
|
||||
github.com/adlio/schema v1.3.3 h1:oBJn8I02PyTB466pZO1UZEn1TV5XLlifBSyMrmHl/1I=
|
||||
github.com/adlio/schema v1.3.3/go.mod h1:1EsRssiv9/Ce2CMzq5DoL7RiMshhuigQxrR4DMV9fHg=
|
||||
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
|
||||
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
@ -258,20 +261,21 @@ github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 h1:41iFGWnSlI2
|
||||
github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
|
||||
github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M=
|
||||
github.com/btcsuite/btcd v0.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY=
|
||||
github.com/btcsuite/btcd v0.23.2 h1:/YOgUp25sdCnP5ho6Hl3s0E438zlX+Kak7E6TgBgoT0=
|
||||
github.com/btcsuite/btcd v0.23.2/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY=
|
||||
github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A=
|
||||
github.com/btcsuite/btcd v0.24.0 h1:gL3uHE/IaFj6fcZSu03SvqPMSx7s/dPzfpG/atRwWdo=
|
||||
github.com/btcsuite/btcd v0.24.0/go.mod h1:K4IDc1593s8jKXIF7yS7yCTSxrknB9z0STzc2j6XgE4=
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA=
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE=
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U=
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04=
|
||||
github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A=
|
||||
github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE=
|
||||
github.com/btcsuite/btcd/btcutil v1.1.2 h1:XLMbX8JQEiwMcYft2EGi8zPUkoa0abKIU6/BJSRsjzQ=
|
||||
github.com/btcsuite/btcd/btcutil v1.1.2/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0=
|
||||
github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8=
|
||||
github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00=
|
||||
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc=
|
||||
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U=
|
||||
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc=
|
||||
github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ=
|
||||
github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc=
|
||||
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
|
||||
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
|
||||
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg=
|
||||
@ -282,6 +286,9 @@ github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg
|
||||
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
|
||||
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
|
||||
github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA=
|
||||
github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8=
|
||||
github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s=
|
||||
github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
|
||||
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||
@ -295,6 +302,8 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL
|
||||
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/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM=
|
||||
github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ=
|
||||
@ -317,6 +326,8 @@ github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWH
|
||||
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ=
|
||||
github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM=
|
||||
github.com/cockroachdb/apd/v2 v2.0.2 h1:weh8u7Cneje73dDh+2tEVLUvyBc89iwepWCD8b8034E=
|
||||
github.com/cockroachdb/apd/v2 v2.0.2/go.mod h1:DDxRlzC2lo3/vSlmSoS7JkqbbrARPuFOGr0B9pvN3Gw=
|
||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||
@ -329,13 +340,14 @@ github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZ
|
||||
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
|
||||
github.com/coinbase/rosetta-sdk-go/types v1.0.0 h1:jpVIwLcPoOeCR6o1tU+Xv7r5bMONNbHU7MuEHboiFuA=
|
||||
github.com/coinbase/rosetta-sdk-go/types v1.0.0/go.mod h1:eq7W2TMRH22GTW0N0beDnN931DW0/WOI1R2sdHNHG4c=
|
||||
github.com/cometbft/cometbft v0.37.2 h1:XB0yyHGT0lwmJlFmM4+rsRnczPlHoAKFX6K8Zgc2/Jc=
|
||||
github.com/cometbft/cometbft v0.37.2/go.mod h1:Y2MMMN//O5K4YKd8ze4r9jmk4Y7h0ajqILXbH5JQFVs=
|
||||
github.com/cometbft/cometbft-db v0.7.0 h1:uBjbrBx4QzU0zOEnU8KxoDl18dMNgDh+zZRUE0ucsbo=
|
||||
github.com/cometbft/cometbft-db v0.7.0/go.mod h1:yiKJIm2WKrt6x8Cyxtq9YTEcIMPcEe4XPxhgX59Fzf0=
|
||||
github.com/cometbft/cometbft v0.37.5 h1:/U/TlgMh4NdnXNo+YU9T2NMCWyhXNDF34Mx582jlvq0=
|
||||
github.com/cometbft/cometbft v0.37.5/go.mod h1:QC+mU0lBhKn8r9qvmnq53Dmf3DWBt4VtkcKw2C81wxY=
|
||||
github.com/cometbft/cometbft-db v0.8.0 h1:vUMDaH3ApkX8m0KZvOFFy9b5DZHBAjsnEuo9AKVZpjo=
|
||||
github.com/cometbft/cometbft-db v0.8.0/go.mod h1:6ASCP4pfhmrCBpfk01/9E1SI29nD3HfVHrY4PG8x5c0=
|
||||
github.com/confio/ics23/go v0.9.0 h1:cWs+wdbS2KRPZezoaaj+qBleXgUk5WOQFMP3CQFGTr4=
|
||||
github.com/confio/ics23/go v0.9.0/go.mod h1:4LPZ2NYqnYIVRklaozjNR1FScgDJ2s5Xrp+e/mYVRak=
|
||||
github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg=
|
||||
github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
@ -344,41 +356,44 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV
|
||||
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk=
|
||||
github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis=
|
||||
github.com/cosmos/cosmos-proto v1.0.0-beta.2 h1:X3OKvWgK9Gsejo0F1qs5l8Qn6xJV/AzgIWR2wZ8Nua8=
|
||||
github.com/cosmos/cosmos-proto v1.0.0-beta.2/go.mod h1:+XRCLJ14pr5HFEHIUcn51IKXD1Fy3rkEQqt4WqmN4V0=
|
||||
github.com/cosmos/cosmos-sdk v0.47.5 h1:n1+WjP/VM/gAEOx3TqU2/Ny734rj/MX1kpUnn7zVJP8=
|
||||
github.com/cosmos/cosmos-sdk v0.47.5/go.mod h1:EHwCeN9IXonsjKcjpS12MqeStdZvIdxt3VYXhus3G3c=
|
||||
github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA=
|
||||
github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec=
|
||||
github.com/cosmos/cosmos-sdk v0.47.14 h1:vD9JyIdlbVaXMOE/BLamViQvylfUq0E0FpqdPVv/fWw=
|
||||
github.com/cosmos/cosmos-sdk v0.47.14/go.mod h1:GrDj/zd9Tiuy8ZpG9PbUbhghCVU7lwyH0GS7CpxHpyM=
|
||||
github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y=
|
||||
github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY=
|
||||
github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw=
|
||||
github.com/cosmos/gogogateway v1.2.0 h1:Ae/OivNhp8DqBi/sh2A8a1D0y638GpL3tkmLQAiKxTE=
|
||||
github.com/cosmos/gogogateway v1.2.0/go.mod h1:iQpLkGWxYcnCdz5iAdLcRBSw3h7NXeOkZ4GUkT+tbFI=
|
||||
github.com/cosmos/gogoproto v1.4.2/go.mod h1:cLxOsn1ljAHSV527CHOtaIP91kK6cCrZETRBrkzItWU=
|
||||
github.com/cosmos/gogoproto v1.4.10 h1:QH/yT8X+c0F4ZDacDv3z+xE3WU1P1Z3wQoLMBRJoKuI=
|
||||
github.com/cosmos/gogoproto v1.4.10/go.mod h1:3aAZzeRWpAwr+SS/LLkICX2/kDFyaYVzckBDzygIxek=
|
||||
github.com/cosmos/iavl v0.20.0 h1:fTVznVlepH0KK8NyKq8w+U7c2L6jofa27aFX6YGlm38=
|
||||
github.com/cosmos/iavl v0.20.0/go.mod h1:WO7FyvaZJoH65+HFOsDir7xU9FWk2w9cHXNW1XHcl7A=
|
||||
github.com/cosmos/ibc-go/v7 v7.1.0 h1:SCLgs7tqVnzdIDO5MRLgovAnc696vTTKl+8qsTu8IMM=
|
||||
github.com/cosmos/ibc-go/v7 v7.1.0/go.mod h1:7MptlWeIyqmDiuJeRAFqBvXKY8Hybd+rF8vMSmGd2zg=
|
||||
github.com/cosmos/gogoproto v1.7.0 h1:79USr0oyXAbxg3rspGh/m4SWNyoz/GLaAh0QlCe2fro=
|
||||
github.com/cosmos/gogoproto v1.7.0/go.mod h1:yWChEv5IUEYURQasfyBW5ffkMHR/90hiHgbNgrtp4j0=
|
||||
github.com/cosmos/iavl v0.20.1 h1:rM1kqeG3/HBT85vsZdoSNsehciqUQPWrR4BYmqE2+zg=
|
||||
github.com/cosmos/iavl v0.20.1/go.mod h1:WO7FyvaZJoH65+HFOsDir7xU9FWk2w9cHXNW1XHcl7A=
|
||||
github.com/cosmos/ibc-go/v7 v7.4.0 h1:8FqYMptvksgMvlbN4UW9jFxTXzsPyfAzEZurujXac8M=
|
||||
github.com/cosmos/ibc-go/v7 v7.4.0/go.mod h1:L/KaEhzV5TGUCTfGysVgMBQtl5Dm7hHitfpk+GIeoAo=
|
||||
github.com/cosmos/ics23/go v0.10.0 h1:iXqLLgp2Lp+EdpIuwXTYIQU+AiHj9mOC2X9ab++bZDM=
|
||||
github.com/cosmos/ics23/go v0.10.0/go.mod h1:ZfJSmng/TBNTBkFemHHHj5YY7VAU/MBU980F4VU1NG0=
|
||||
github.com/cosmos/ledger-cosmos-go v0.12.1 h1:sMBxza5p/rNK/06nBSNmsI/WDqI0pVJFVNihy1Y984w=
|
||||
github.com/cosmos/ledger-cosmos-go v0.12.1/go.mod h1:dhO6kj+Y+AHIOgAe4L9HL/6NDdyyth4q238I9yFpD2g=
|
||||
github.com/cosmos/ledger-cosmos-go v0.12.4 h1:drvWt+GJP7Aiw550yeb3ON/zsrgW0jgh5saFCr7pDnw=
|
||||
github.com/cosmos/ledger-cosmos-go v0.12.4/go.mod h1:fjfVWRf++Xkygt9wzCsjEBdjcf7wiiY35fv3ctT+k4M=
|
||||
github.com/cosmos/rosetta-sdk-go v0.10.0 h1:E5RhTruuoA7KTIXUcMicL76cffyeoyvNybzUGSKFTcM=
|
||||
github.com/cosmos/rosetta-sdk-go v0.10.0/go.mod h1:SImAZkb96YbwvoRkzSMQB6noNJXFgWl/ENIznEoYQI4=
|
||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creachadair/taskgroup v0.4.2 h1:jsBLdAJE42asreGss2xZGZ8fJra7WtwnHWeJFxv2Li8=
|
||||
github.com/creachadair/taskgroup v0.4.2/go.mod h1:qiXUOSrbwAY3u0JPGTzObbE3yf9hcXHDKBZ2ZjpCbgM=
|
||||
github.com/creack/goselect v0.1.2 h1:2DNy14+JPjRBgPzAd1thbQp4BSIihxcBf0IXhQXDRa0=
|
||||
github.com/creack/goselect v0.1.2/go.mod h1:a/NhLweNvqIYMuxcMOuWY516Cimucms3DglDzQP3hKY=
|
||||
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/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0=
|
||||
github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0=
|
||||
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0=
|
||||
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs=
|
||||
@ -397,16 +412,20 @@ github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUn
|
||||
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y=
|
||||
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
|
||||
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/dvsekhvalnov/jose2go v1.5.0 h1:3j8ya4Z4kMCwT5nXIKFSV84YS+HdqSSO0VsTQxaLAeM=
|
||||
github.com/dvsekhvalnov/jose2go v1.5.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU=
|
||||
github.com/dvsekhvalnov/jose2go v1.6.0 h1:Y9gnSnP4qEI0+/uQkHvFXeD2PLPJeXEL+ySMEA2EjTY=
|
||||
github.com/dvsekhvalnov/jose2go v1.6.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU=
|
||||
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||
github.com/eclipse/paho.mqtt.golang v1.4.3 h1:2kwcUGn8seMUfWndX0hGbvH8r7crgcJguQNCyp70xik=
|
||||
github.com/eclipse/paho.mqtt.golang v1.4.3/go.mod h1:CSYvoAlsMkhYOXh/oKyxa8EcBci6dVkLCbo5tTC1RIE=
|
||||
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
@ -419,21 +438,24 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.m
|
||||
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
|
||||
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c h1:8ISkoahWXwZR41ois5lSJBSVw4D0OV19Ht/JSTzvSv0=
|
||||
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A=
|
||||
github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/felixge/httpsnoop v1.0.2 h1:+nS9g82KMXccJ/wp0zyRW9ZBHFETmMGtkk+2CTTrW4o=
|
||||
github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
|
||||
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
||||
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
|
||||
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
|
||||
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
|
||||
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
|
||||
github.com/getsentry/sentry-go v0.23.0 h1:dn+QRCeJv4pPt9OjVXiMcGIBIefaTJPw/h0bZWO05nE=
|
||||
github.com/getsentry/sentry-go v0.23.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
|
||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||
@ -441,8 +463,10 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
|
||||
github.com/gin-gonic/gin v1.8.1 h1:4+fr/el88TOO3ewCmQr8cx/CtZ/umlIRIs5M4NTNjf8=
|
||||
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
|
||||
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
|
||||
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
|
||||
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
@ -458,13 +482,21 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
|
||||
github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=
|
||||
github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
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-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
||||
github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
||||
github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
|
||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
|
||||
github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ=
|
||||
github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js=
|
||||
github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
|
||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0=
|
||||
@ -473,7 +505,8 @@ github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8=
|
||||
github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
|
||||
github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo=
|
||||
github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
|
||||
github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk=
|
||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0=
|
||||
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
@ -488,8 +521,8 @@ github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE=
|
||||
github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ=
|
||||
github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68=
|
||||
github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
|
||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
@ -524,8 +557,8 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||
@ -548,17 +581,20 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
||||
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
|
||||
github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw=
|
||||
github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
|
||||
github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us=
|
||||
github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
@ -570,24 +606,24 @@ github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hf
|
||||
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/s2a-go v0.1.4 h1:1kZ/sQM3srePvKs3tXAvQzo66XfcReoqFpIpIccE7Oc=
|
||||
github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A=
|
||||
github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o=
|
||||
github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
|
||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
|
||||
@ -597,10 +633,9 @@ github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99
|
||||
github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c=
|
||||
github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo=
|
||||
github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY=
|
||||
github.com/googleapis/gax-go/v2 v2.11.0 h1:9V9PWXEsWnPpQhu/PeQIkS4eGzMlTLGgt80cUUI8Ki4=
|
||||
github.com/googleapis/gax-go/v2 v2.11.0/go.mod h1:DxmR61SGKkGLa2xigwuZIQpkCI2S5iydzRfb3peWZJI=
|
||||
github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas=
|
||||
github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU=
|
||||
github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4=
|
||||
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
|
||||
@ -637,8 +672,8 @@ github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
|
||||
github.com/hashicorp/go-getter v1.7.1 h1:SWiSWN/42qdpR0MdhaOc/bLR48PLuP1ZQtYLRlM69uY=
|
||||
github.com/hashicorp/go-getter v1.7.1/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744=
|
||||
github.com/hashicorp/go-getter v1.7.5 h1:dT58k9hQ/vbxNMwoI5+xFYAJuv6152UNvdHokfI5wE4=
|
||||
github.com/hashicorp/go-getter v1.7.5/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744=
|
||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc=
|
||||
github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
@ -680,13 +715,13 @@ github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:
|
||||
github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2tzCixLaUPQ=
|
||||
github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPtwNr0l57L4f878wP8=
|
||||
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-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
|
||||
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c=
|
||||
github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
|
||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||
@ -703,6 +738,7 @@ github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
@ -717,11 +753,12 @@ github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYs
|
||||
github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
||||
github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
|
||||
github.com/klauspost/compress v1.16.3 h1:XuJt9zzcnaz6a16/OU53ZjWp/v7/42WcR5t2a0PcNQY=
|
||||
github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM=
|
||||
github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
|
||||
github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
@ -731,13 +768,16 @@ 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/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
|
||||
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
|
||||
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
|
||||
github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw=
|
||||
github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8=
|
||||
github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg=
|
||||
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
|
||||
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
|
||||
github.com/linxGnu/grocksdb v1.7.16 h1:Q2co1xrpdkr5Hx3Fp+f+f7fRGhQFQhvi/+226dtLmA8=
|
||||
github.com/linxGnu/grocksdb v1.7.16/go.mod h1:JkS7pl5qWpGpuVb3bPqTz8nC12X3YtPZT+Xq7+QfQo4=
|
||||
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
|
||||
@ -745,16 +785,15 @@ github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3v
|
||||
github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA=
|
||||
github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.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.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
@ -785,6 +824,7 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs=
|
||||
github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
@ -801,6 +841,7 @@ github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OS
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
|
||||
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
|
||||
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
||||
@ -809,15 +850,20 @@ github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
||||
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
|
||||
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
||||
github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.20.0 h1:8W0cWlwFkflGPLltQvLRB7ZVD5HuP6ng320w2IS245Q=
|
||||
github.com/onsi/gomega v1.20.0/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo=
|
||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034=
|
||||
github.com/opencontainers/image-spec v1.1.0-rc2/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ=
|
||||
github.com/opencontainers/runc v1.1.3 h1:vIXrkId+0/J2Ymu2m7VjGvbSlAId9XNRPhn2p4b+d8w=
|
||||
github.com/opencontainers/runc v1.1.3/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg=
|
||||
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
|
||||
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
|
||||
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
@ -827,14 +873,15 @@ github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJ
|
||||
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
||||
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
||||
github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA=
|
||||
github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs=
|
||||
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
|
||||
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pelletier/go-toml/v2 v2.0.7 h1:muncTPStnKRos5dpVKULv2FVd4bMOhNePj9CjgDb8Us=
|
||||
github.com/pelletier/go-toml/v2 v2.0.7/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
|
||||
github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
|
||||
github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
|
||||
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
|
||||
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o=
|
||||
github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 h1:hDSdbBuw3Lefr6R18ax0tZ2BJeNB3NehB3trOwYBsdU=
|
||||
@ -842,15 +889,16 @@ github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08/go.mod h1:pxMtw7c
|
||||
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
|
||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
|
||||
github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
|
||||
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
|
||||
@ -889,6 +937,18 @@ github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Ung
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/rddl-network/elements-rpc v1.2.1 h1:clE3daxNPJJ1EDiAkTSlXUM2+gakmLHxWOazZ4t2W48=
|
||||
github.com/rddl-network/elements-rpc v1.2.1/go.mod h1:9a71Z7xja4rFMXa+ssUMLAF9VIZVPz2jZRB1hTS9Ey4=
|
||||
github.com/rddl-network/go-utils v0.2.3 h1:STiiyZVkFjovjMAyKK1IsqvVED14mRHoXFIDVbwxlFQ=
|
||||
github.com/rddl-network/go-utils v0.2.3/go.mod h1:jLOkVBK/xjfVyY0d4gs1pkafTXF3mYA7ZIE68QXau5o=
|
||||
github.com/rddl-network/rddl-claim-service v0.3.2 h1:Cp8FV40y9mwTbjVNlFrZ02QT+HZWD1pSsWaE5MLYAmc=
|
||||
github.com/rddl-network/rddl-claim-service v0.3.2/go.mod h1:RLg6AcNL790WuAl3AYoxFGkuuwKP3t3IiBfhOYOcwdo=
|
||||
github.com/rddl-network/rddl-claim-service/client v0.0.6 h1:GLqj8RMozFPVUvPQGRLBH2yGV+VHRuUCXTWaf+4wxFo=
|
||||
github.com/rddl-network/rddl-claim-service/client v0.0.6/go.mod h1:CFAfupB5XogWqVsb6ndsLU97feGs4oUqlGI4WRff3zU=
|
||||
github.com/rddl-network/shamir-coordinator-service v0.7.7 h1:hszDZZnqBdeiOEBWlnSK2lKIJEbWclX6cchYDazpvIU=
|
||||
github.com/rddl-network/shamir-coordinator-service v0.7.7/go.mod h1:g3JnQlzKQWtnp4ZA7VtD/4N0GKpFWrW0ANHqged7M/g=
|
||||
github.com/rddl-network/shamir-coordinator-service/client v0.1.0 h1:o8oZzvGSAyTto5hSkNRr2KvilhwWiqGbL70HRg4aKhA=
|
||||
github.com/rddl-network/shamir-coordinator-service/client v0.1.0/go.mod h1:dhxYyhmU71iv32WqS6S+6Pm/Lsb5/d0KVn2MVTq5Jfk=
|
||||
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=
|
||||
@ -899,12 +959,16 @@ github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||
github.com/rs/cors v1.8.3 h1:O+qNyWn7Z+F9M0ILBHgMVPuB1xTOucVd5gtaYyXBpRo=
|
||||
github.com/rs/cors v1.8.3/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
|
||||
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
github.com/rs/zerolog v1.30.0 h1:SymVODrcRsaRaSInD9yQtKbtWqwsfoPcRff/oRXLj4c=
|
||||
github.com/rs/zerolog v1.30.0/go.mod h1:/tk+P47gFdPXq4QYjvCmT5/Gsug2nagsFWBWhAiSi1w=
|
||||
github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
|
||||
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
|
||||
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
|
||||
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
|
||||
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
|
||||
github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0=
|
||||
github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM=
|
||||
@ -915,41 +979,43 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
|
||||
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
|
||||
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
||||
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk=
|
||||
github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
|
||||
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
|
||||
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
|
||||
github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
|
||||
github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
|
||||
github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
|
||||
github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
|
||||
github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
|
||||
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
|
||||
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
|
||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
||||
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||
github.com/spf13/viper v1.15.0 h1:js3yy885G8xwJa6iOISGFwd+qlUo5AvyXb7CiihdtiU=
|
||||
github.com/spf13/viper v1.15.0/go.mod h1:fFcTBJxvhhzSJiZy8n+PeW6t8l+KeT/uTARa0jHOQLA=
|
||||
github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ=
|
||||
github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk=
|
||||
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
|
||||
github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
|
||||
github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.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/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
@ -959,25 +1025,27 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
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.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=
|
||||
github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
|
||||
github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c h1:g+WoO5jjkqGAzHWCjJB1zZfXPIAaDpzXIEJ0eS6B5Ok=
|
||||
github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8=
|
||||
github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E=
|
||||
github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME=
|
||||
github.com/tidwall/btree v1.6.0 h1:LDZfKfQIBHGHWSwckhXI0RPSXzlo+KYdjK7FWSqOzzg=
|
||||
github.com/tidwall/btree v1.6.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
|
||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||
github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
|
||||
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
|
||||
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||
github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8=
|
||||
github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||
@ -991,10 +1059,12 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/zondax/hid v0.9.1 h1:gQe66rtmyZ8VeGFcOpbuH3r7erYtNEAezCAYu8LdkJo=
|
||||
github.com/zondax/hid v0.9.1/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM=
|
||||
github.com/zondax/ledger-go v0.14.1 h1:Pip65OOl4iJ84WTpA4BKChvOufMhhbxED3BaihoZN4c=
|
||||
github.com/zondax/ledger-go v0.14.1/go.mod h1:fZ3Dqg6qcdXWSOJFKMG8GCTnD7slO/RL2feOQv8K320=
|
||||
github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U=
|
||||
github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM=
|
||||
github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw=
|
||||
github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI=
|
||||
go.bug.st/serial v1.6.2 h1:kn9LRX3sdm+WxWKufMlIRndwGfPWsH1/9lCWXQCasq8=
|
||||
go.bug.st/serial v1.6.2/go.mod h1:UABfsluHAiaNI+La2iESysd9Vetq7VRdpxvjx7CmmOE=
|
||||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ=
|
||||
go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
|
||||
@ -1010,15 +1080,33 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
||||
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 h1:SpGay3w+nEwMpfVnbqOLH5gY52/foP8RE8UzTZ1pdSE=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1/go.mod h1:4UoMYEZOC0yN/sPGH76KPkkU7zgiEWYWL9vwmbnTJPE=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 h1:aFJWCqJMNjENlcleuuOkGAPH82y0yULBScfXcIEdS24=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1/go.mod h1:sEGXWArGqc3tVa+ekntsN65DmVbVeW+7lTKTjZF3/Fo=
|
||||
go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc=
|
||||
go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo=
|
||||
go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4=
|
||||
go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM=
|
||||
go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8=
|
||||
go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E=
|
||||
go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc=
|
||||
go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ=
|
||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||
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.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
|
||||
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
|
||||
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
|
||||
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
|
||||
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
|
||||
golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
|
||||
golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
@ -1031,12 +1119,9 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
||||
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
|
||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
@ -1048,8 +1133,8 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw=
|
||||
golang.org/x/exp v0.0.0-20230711153332-06a737ee72cb h1:xIApU0ow1zwMa2uL1VDNeQlNVFTWMQxZUZCMDy0Q4Us=
|
||||
golang.org/x/exp v0.0.0-20230711153332-06a737ee72cb/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
@ -1076,7 +1161,8 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=
|
||||
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
|
||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@ -1119,14 +1205,12 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
|
||||
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
@ -1139,8 +1223,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
|
||||
golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
|
||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
|
||||
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@ -1166,8 +1250,8 @@ golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri
|
||||
golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
|
||||
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
|
||||
golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A=
|
||||
golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8=
|
||||
golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE=
|
||||
golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ=
|
||||
golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o=
|
||||
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=
|
||||
@ -1182,7 +1266,8 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
|
||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@ -1239,13 +1324,11 @@ golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@ -1257,7 +1340,6 @@ golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
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-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@ -1277,17 +1359,17 @@ golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
|
||||
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
|
||||
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
||||
golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
|
||||
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@ -1299,12 +1381,14 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@ -1359,7 +1443,6 @@ golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4f
|
||||
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
@ -1367,7 +1450,8 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
|
||||
golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
|
||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@ -1426,8 +1510,8 @@ google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ
|
||||
google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s=
|
||||
google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s=
|
||||
google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70=
|
||||
google.golang.org/api v0.126.0 h1:q4GJq+cAdMAC7XP7njvQ4tvohGLiSlytuL4BQxbIZ+o=
|
||||
google.golang.org/api v0.126.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw=
|
||||
google.golang.org/api v0.155.0 h1:vBmGhCYs0djJttDNynWo44zosHlPvHmA0XiN2zP2DtA=
|
||||
google.golang.org/api v0.155.0/go.mod h1:GI5qK5f40kCpHfPn6+YzGAByIKWv8ujFnmoWm7Igduk=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
@ -1435,8 +1519,9 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
|
||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
|
||||
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
@ -1475,10 +1560,8 @@ google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6D
|
||||
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
@ -1545,12 +1628,12 @@ google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqw
|
||||
google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM=
|
||||
google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM=
|
||||
google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s=
|
||||
google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130 h1:Au6te5hbKUV8pIYWHqOUZ1pva5qK/rwbIhoXEUB9Lu8=
|
||||
google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:O9kGHb51iE/nOGvQaDUuadVYqovW56s5emA88lQnj6Y=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230629202037-9506855d4529 h1:s5YSX+ZH5b5vS9rnpGymvIyMpLRJizowqDlOuyjXnTk=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230629202037-9506855d4529/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM=
|
||||
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ=
|
||||
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 h1:Lj5rbfG876hIAYFjqiJnPHfhXbv+nzTWfm04Fg/XSVU=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
|
||||
@ -1592,8 +1675,8 @@ google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACu
|
||||
google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
|
||||
google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
|
||||
google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
|
||||
google.golang.org/grpc v1.56.3 h1:8I4C0Yq1EjstUzUJzpcRVbuYA2mODtEmpWiQoN/b2nc=
|
||||
google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
|
||||
google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk=
|
||||
google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE=
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
@ -1610,14 +1693,15 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
||||
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
@ -1645,7 +1729,8 @@ 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.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY=
|
||||
gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
|
||||
gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
@ -1656,12 +1741,12 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9
|
||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
nhooyr.io/websocket v1.8.6 h1:s+C3xAMLwGmlI31Nyn/eAehUlZPwfYZu2JXM621Q5/k=
|
||||
nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
|
||||
pgregory.net/rapid v0.5.5 h1:jkgx1TjbQPD/feRoK+S/mXw9e1uj6WilpHrXJowi6oA=
|
||||
pgregory.net/rapid v0.5.5/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04=
|
||||
pgregory.net/rapid v1.1.0 h1:CMa0sjHSru3puNx+J0MIAuiiEV4N0qj8/cMWGBBCsjw=
|
||||
pgregory.net/rapid v1.1.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
|
||||
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
|
||||
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
|
||||
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
|
||||
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
|
||||
|
@ -9,6 +9,10 @@ After that we construct three messages to send `10plmnt` each to three addresses
|
||||
We then build and sign the transaction and eventually send this transaction via RPC.
|
||||
For debugging purposes we print the transaction that we send as JSON.
|
||||
|
||||
## Support for Trust Wallet over serial connection
|
||||
|
||||
The config has a setting for a `serialPort`. If it is set then `BroadcastTxWithFileLock()` will sign transactions with the TrustWallet. Be aware that the public key must be available on the keyring in order to construct transactions signing data.
|
||||
|
||||
```
|
||||
package main
|
||||
|
||||
@ -45,7 +49,7 @@ func main() {
|
||||
}
|
||||
fmt.Println(txJSON)
|
||||
|
||||
_, err = lib.BroadcastTx(addr0, msg1, msg2, msg3)
|
||||
_, err = lib.BroadcastTxWithFileLock(addr0, msg1, msg2, msg3)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
197
lib/config.go
197
lib/config.go
@ -1,73 +1,190 @@
|
||||
package lib
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/planetmint/planetmint-go/lib/params"
|
||||
)
|
||||
|
||||
// Config defines library top level configuration.
|
||||
type Config struct {
|
||||
ChainID string `json:"chain-id" mapstructure:"chain-id"`
|
||||
EncodingConfig params.EncodingConfig `json:"encoding-config" mapstructure:"encoding-config"`
|
||||
RootDir string `json:"root-dir" mapstructure:"root-dir"`
|
||||
RPCEndpoint string `json:"rpc-endpoint" mapstructure:"rpc-endpoint"`
|
||||
}
|
||||
|
||||
// lib wide global singleton
|
||||
var (
|
||||
libConfig *Config
|
||||
sdkConfig *sdk.Config
|
||||
initConfig sync.Once
|
||||
// ErrInvalidConfig is returned when configuration validation fails
|
||||
ErrInvalidConfig = errors.New("invalid configuration")
|
||||
|
||||
// Global singleton instances
|
||||
instance *Config
|
||||
mu sync.RWMutex
|
||||
once sync.Once
|
||||
sdkConfig *sdk.Config
|
||||
)
|
||||
|
||||
// DefaultConfig returns library default configuration.
|
||||
func DefaultConfig() *Config {
|
||||
// Config defines the top-level configuration for the Planetmint library.
|
||||
// All fields are exported to allow external access while maintaining
|
||||
// thread-safe modifications through methods.
|
||||
type Config struct {
|
||||
ChainID string
|
||||
ClientCtx client.Context
|
||||
EncodingConfig params.EncodingConfig
|
||||
FeeDenom string
|
||||
RPCEndpoint string
|
||||
RootDir string
|
||||
SerialPort string
|
||||
TxGas uint64
|
||||
}
|
||||
|
||||
// NewConfig creates a new Config instance with default values.
|
||||
func NewConfig() *Config {
|
||||
return &Config{
|
||||
ChainID: "planetmint-testnet-1",
|
||||
ClientCtx: client.Context{},
|
||||
EncodingConfig: params.EncodingConfig{},
|
||||
RootDir: "~/.planetmint-go/",
|
||||
FeeDenom: "plmnt",
|
||||
RPCEndpoint: "http://127.0.0.1:26657",
|
||||
RootDir: "~/.planetmint-go/",
|
||||
TxGas: 200000,
|
||||
}
|
||||
}
|
||||
|
||||
// GetConfig returns the config instance for the SDK.
|
||||
// GetConfig returns the singleton Config instance, initializing it if necessary.
|
||||
func GetConfig() *Config {
|
||||
initConfig.Do(func() {
|
||||
libConfig = DefaultConfig()
|
||||
once.Do(func() {
|
||||
instance = NewConfig()
|
||||
sdkConfig = sdk.GetConfig()
|
||||
libConfig.SetBech32PrefixForAccount("plmnt")
|
||||
|
||||
// Initialize default configuration
|
||||
instance.SetBech32PrefixForAccount("plmnt")
|
||||
encodingConfig := MakeEncodingConfig()
|
||||
instance.SetEncodingConfig(encodingConfig)
|
||||
})
|
||||
return libConfig
|
||||
return instance
|
||||
}
|
||||
|
||||
// SetBech32PrefixForAccount sets the bech32 account prefix.
|
||||
func (config *Config) SetBech32PrefixForAccount(bech32Prefix string) *Config {
|
||||
sdkConfig.SetBech32PrefixForAccount(bech32Prefix, "pub")
|
||||
return config
|
||||
// Validate checks if the configuration is valid.
|
||||
func (c *Config) Validate() error {
|
||||
mu.RLock()
|
||||
defer mu.RUnlock()
|
||||
|
||||
if c.ChainID == "" {
|
||||
return errors.New("chain ID cannot be empty")
|
||||
}
|
||||
if c.RPCEndpoint == "" {
|
||||
return errors.New("RPC endpoint cannot be empty")
|
||||
}
|
||||
if c.TxGas == 0 {
|
||||
return errors.New("transaction gas cannot be zero")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetEncodingConfig sets the encoding config and must not be nil.
|
||||
func (config *Config) SetEncodingConfig(encodingConfig params.EncodingConfig) *Config {
|
||||
config.EncodingConfig = encodingConfig
|
||||
return config
|
||||
// Builder methods
|
||||
|
||||
func (c *Config) SetBech32PrefixForAccount(prefix string) *Config {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
sdkConfig.SetBech32PrefixForAccount(prefix, "pub")
|
||||
return c
|
||||
}
|
||||
|
||||
// SetChainID sets the chain ID parameter.
|
||||
func (config *Config) SetChainID(chainID string) *Config {
|
||||
config.ChainID = chainID
|
||||
return config
|
||||
func (c *Config) SetEncodingConfig(config params.EncodingConfig) *Config {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
c.EncodingConfig = config
|
||||
return c
|
||||
}
|
||||
|
||||
// SetRoot sets the root directory where to find the keyring.
|
||||
func (config *Config) SetRoot(root string) *Config {
|
||||
config.RootDir = root
|
||||
return config
|
||||
func (c *Config) SetChainID(chainID string) *Config {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
c.ChainID = chainID
|
||||
return c
|
||||
}
|
||||
|
||||
// SetRPCEndpoint sets the RPC endpoint to send requests to.
|
||||
func (config *Config) SetRPCEndpoint(rpcEndpoint string) *Config {
|
||||
config.RPCEndpoint = rpcEndpoint
|
||||
return config
|
||||
func (c *Config) SetClientCtx(ctx client.Context) *Config {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
c.ClientCtx = ctx
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Config) SetFeeDenom(denom string) *Config {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
c.FeeDenom = denom
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Config) SetRoot(root string) *Config {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
c.RootDir = root
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Config) SetRPCEndpoint(endpoint string) *Config {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
c.RPCEndpoint = endpoint
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Config) SetTxGas(gas uint64) *Config {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
c.TxGas = gas
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Config) SetSerialPort(port string) *Config {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
c.SerialPort = port
|
||||
return c
|
||||
}
|
||||
|
||||
// Getter methods
|
||||
|
||||
func (c *Config) GetSerialPort() string {
|
||||
mu.RLock()
|
||||
defer mu.RUnlock()
|
||||
return c.SerialPort
|
||||
}
|
||||
|
||||
// Keyring operations
|
||||
|
||||
// GetLibKeyring returns a new keyring instance configured with the current settings.
|
||||
func (c *Config) GetLibKeyring() (keyring.Keyring, error) {
|
||||
mu.RLock()
|
||||
defer mu.RUnlock()
|
||||
|
||||
return keyring.New(
|
||||
"lib",
|
||||
keyring.BackendTest,
|
||||
c.RootDir,
|
||||
os.Stdin,
|
||||
c.EncodingConfig.Marshaler,
|
||||
[]keyring.Option{}...,
|
||||
)
|
||||
}
|
||||
|
||||
// GetDefaultValidatorRecord returns the first validator record from the keyring.
|
||||
func (c *Config) GetDefaultValidatorRecord() (*keyring.Record, error) {
|
||||
keyring, err := c.GetLibKeyring()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
records, err := keyring.List()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(records) == 0 {
|
||||
return nil, errors.New("no keyring records found")
|
||||
}
|
||||
|
||||
return records[0], nil
|
||||
}
|
||||
|
32
lib/encoding.go
Normal file
32
lib/encoding.go
Normal file
@ -0,0 +1,32 @@
|
||||
package lib
|
||||
|
||||
import (
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/cosmos/cosmos-sdk/std"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/tx"
|
||||
"github.com/planetmint/planetmint-go/lib/params"
|
||||
)
|
||||
|
||||
// makeEncodingConfig creates an EncodingConfig for an amino based test configuration.
|
||||
func makeEncodingConfig() params.EncodingConfig {
|
||||
amino := codec.NewLegacyAmino()
|
||||
interfaceRegistry := types.NewInterfaceRegistry()
|
||||
marshaler := codec.NewProtoCodec(interfaceRegistry)
|
||||
txCfg := tx.NewTxConfig(marshaler, tx.DefaultSignModes)
|
||||
|
||||
return params.EncodingConfig{
|
||||
InterfaceRegistry: interfaceRegistry,
|
||||
Marshaler: marshaler,
|
||||
TxConfig: txCfg,
|
||||
Amino: amino,
|
||||
}
|
||||
}
|
||||
|
||||
// MakeEncodingConfig creates an EncodingConfig for testing
|
||||
func MakeEncodingConfig() params.EncodingConfig {
|
||||
encodingConfig := makeEncodingConfig()
|
||||
std.RegisterLegacyAminoCodec(encodingConfig.Amino)
|
||||
std.RegisterInterfaces(encodingConfig.InterfaceRegistry)
|
||||
return encodingConfig
|
||||
}
|
167
lib/go.mod
167
lib/go.mod
@ -1,125 +1,202 @@
|
||||
module github.com/planetmint/planetmint-go/lib
|
||||
|
||||
go 1.20
|
||||
go 1.22
|
||||
|
||||
require (
|
||||
github.com/cometbft/cometbft v0.37.2
|
||||
github.com/cosmos/cosmos-sdk v0.47.5
|
||||
github.com/cometbft/cometbft v0.37.5
|
||||
github.com/cosmos/cosmos-sdk v0.47.14
|
||||
github.com/planetmint/planetmint-go v0.12.8
|
||||
github.com/stretchr/testify v1.9.0
|
||||
go.bug.st/serial v1.6.2
|
||||
sigs.k8s.io/yaml v1.4.0
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.112.0 // indirect
|
||||
cloud.google.com/go/compute v1.23.3 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
||||
cloud.google.com/go/iam v1.1.5 // indirect
|
||||
cloud.google.com/go/storage v1.36.0 // indirect
|
||||
cosmossdk.io/api v0.3.1 // indirect
|
||||
cosmossdk.io/core v0.5.1 // indirect
|
||||
cosmossdk.io/depinject v1.0.0-alpha.4 // indirect
|
||||
cosmossdk.io/errors v1.0.0 // indirect
|
||||
cosmossdk.io/math v1.1.2 // indirect
|
||||
cosmossdk.io/errors v1.0.1 // indirect
|
||||
cosmossdk.io/log v1.4.1 // indirect
|
||||
cosmossdk.io/math v1.4.0 // indirect
|
||||
cosmossdk.io/simapp v0.0.0-20230323161446-0af178d721ff // indirect
|
||||
cosmossdk.io/tools/rosetta v0.2.1 // indirect
|
||||
filippo.io/edwards25519 v1.0.0 // indirect
|
||||
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect
|
||||
github.com/99designs/keyring v1.2.1 // indirect
|
||||
github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect
|
||||
github.com/ChainSafe/go-schnorrkel v1.0.0 // indirect
|
||||
github.com/armon/go-metrics v0.4.1 // indirect
|
||||
github.com/aws/aws-sdk-go v1.44.203 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
|
||||
github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect
|
||||
github.com/btcsuite/btcd v0.24.0 // indirect
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect
|
||||
github.com/btcsuite/btcd/btcutil v1.1.5 // indirect
|
||||
github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.1.3 // indirect
|
||||
github.com/cespare/xxhash v1.1.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/chzyer/readline v1.5.1 // indirect
|
||||
github.com/cockroachdb/apd/v2 v2.0.2 // indirect
|
||||
github.com/cockroachdb/errors v1.10.0 // indirect
|
||||
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
|
||||
github.com/cockroachdb/redact v1.1.5 // indirect
|
||||
github.com/cometbft/cometbft-db v0.7.0 // indirect
|
||||
github.com/coinbase/rosetta-sdk-go/types v1.0.0 // indirect
|
||||
github.com/cometbft/cometbft-db v0.8.0 // indirect
|
||||
github.com/confio/ics23/go v0.9.0 // indirect
|
||||
github.com/cosmos/btcutil v1.0.5 // indirect
|
||||
github.com/cosmos/cosmos-proto v1.0.0-beta.2 // indirect
|
||||
github.com/cosmos/cosmos-proto v1.0.0-beta.5 // indirect
|
||||
github.com/cosmos/go-bip39 v1.0.0 // indirect
|
||||
github.com/cosmos/gogoproto v1.4.10 // indirect
|
||||
github.com/cosmos/iavl v0.20.0 // indirect
|
||||
github.com/cosmos/ledger-cosmos-go v0.12.1 // indirect
|
||||
github.com/cosmos/gogogateway v1.2.0 // indirect
|
||||
github.com/cosmos/gogoproto v1.7.0 // indirect
|
||||
github.com/cosmos/iavl v0.20.1 // indirect
|
||||
github.com/cosmos/ibc-go/v7 v7.4.0 // indirect
|
||||
github.com/cosmos/ics23/go v0.10.0 // indirect
|
||||
github.com/cosmos/ledger-cosmos-go v0.12.4 // indirect
|
||||
github.com/cosmos/rosetta-sdk-go v0.10.0 // indirect
|
||||
github.com/creachadair/taskgroup v0.4.2 // indirect
|
||||
github.com/creack/goselect v0.1.2 // indirect
|
||||
github.com/danieljoos/wincred v1.1.2 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect
|
||||
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect
|
||||
github.com/dgraph-io/badger/v2 v2.2007.4 // indirect
|
||||
github.com/dgraph-io/ristretto v0.1.1 // indirect
|
||||
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/dvsekhvalnov/jose2go v1.5.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||
github.com/dvsekhvalnov/jose2go v1.6.0 // indirect
|
||||
github.com/eclipse/paho.mqtt.golang v1.4.3 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/getsentry/sentry-go v0.23.0 // indirect
|
||||
github.com/go-kit/kit v0.12.0 // indirect
|
||||
github.com/go-kit/log v0.2.1 // indirect
|
||||
github.com/go-logfmt/logfmt v0.6.0 // indirect
|
||||
github.com/go-logr/logr v1.3.0 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect
|
||||
github.com/gogo/googleapis v1.4.1 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/glog v1.1.0 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/golang/glog v1.2.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/mock v1.6.0 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/btree v1.1.2 // indirect
|
||||
github.com/google/go-cmp v0.5.9 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/google/orderedcode v0.0.1 // indirect
|
||||
github.com/google/s2a-go v0.1.7 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.12.0 // indirect
|
||||
github.com/gorilla/handlers v1.5.1 // indirect
|
||||
github.com/gorilla/mux v1.8.0 // indirect
|
||||
github.com/gorilla/websocket v1.5.0 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
|
||||
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect
|
||||
github.com/gtank/merlin v0.1.1 // indirect
|
||||
github.com/gtank/ristretto255 v0.1.2 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-getter v1.7.5 // indirect
|
||||
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
|
||||
github.com/hashicorp/go-uuid v1.0.1 // indirect
|
||||
github.com/hashicorp/go-safetemp v1.0.0 // indirect
|
||||
github.com/hashicorp/go-version v1.6.0 // indirect
|
||||
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/hdevalence/ed25519consensus v0.1.0 // indirect
|
||||
github.com/huandu/skiplist v1.2.0 // indirect
|
||||
github.com/improbable-eng/grpc-web v0.15.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/jmhodges/levigo v1.0.0 // indirect
|
||||
github.com/klauspost/compress v1.16.3 // indirect
|
||||
github.com/klauspost/compress v1.17.0 // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/lib/pq v1.10.7 // indirect
|
||||
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
|
||||
github.com/linxGnu/grocksdb v1.7.16 // indirect
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||
github.com/manifoldco/promptui v0.9.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||
github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect
|
||||
github.com/minio/highwayhash v1.0.2 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/mtibben/percent v0.2.1 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.7 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
|
||||
github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_golang v1.14.0 // indirect
|
||||
github.com/prometheus/client_model v0.3.0 // indirect
|
||||
github.com/prometheus/common v0.42.0 // indirect
|
||||
github.com/prometheus/procfs v0.9.0 // indirect
|
||||
github.com/rakyll/statik v0.1.7 // indirect
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
|
||||
github.com/rddl-network/elements-rpc v1.2.1 // indirect
|
||||
github.com/rddl-network/go-utils v0.2.3 // indirect
|
||||
github.com/rddl-network/rddl-claim-service v0.3.2 // indirect
|
||||
github.com/rddl-network/rddl-claim-service/client v0.0.6 // indirect
|
||||
github.com/rddl-network/shamir-coordinator-service v0.7.7 // indirect
|
||||
github.com/rddl-network/shamir-coordinator-service/client v0.1.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.11.0 // indirect
|
||||
github.com/rs/cors v1.8.3 // indirect
|
||||
github.com/rs/zerolog v1.33.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
github.com/sasha-s/go-deadlock v0.3.1 // indirect
|
||||
github.com/spf13/afero v1.9.3 // indirect
|
||||
github.com/spf13/cast v1.5.0 // indirect
|
||||
github.com/spf13/cobra v1.6.1 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
github.com/spf13/afero v1.11.0 // indirect
|
||||
github.com/spf13/cast v1.6.0 // indirect
|
||||
github.com/spf13/cobra v1.8.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/spf13/viper v1.15.0 // indirect
|
||||
github.com/stretchr/testify v1.8.4 // indirect
|
||||
github.com/subosito/gotenv v1.4.2 // indirect
|
||||
github.com/spf13/viper v1.18.2 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect
|
||||
github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect
|
||||
github.com/tendermint/go-amino v0.16.0 // indirect
|
||||
github.com/tidwall/btree v1.6.0 // indirect
|
||||
github.com/zondax/hid v0.9.1 // indirect
|
||||
github.com/zondax/ledger-go v0.14.1 // indirect
|
||||
github.com/ulikunitz/xz v0.5.11 // indirect
|
||||
github.com/zondax/hid v0.9.2 // indirect
|
||||
github.com/zondax/ledger-go v0.14.3 // indirect
|
||||
go.etcd.io/bbolt v1.3.7 // indirect
|
||||
golang.org/x/crypto v0.14.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20230711153332-06a737ee72cb // indirect
|
||||
golang.org/x/net v0.17.0 // indirect
|
||||
golang.org/x/sys v0.13.0 // indirect
|
||||
golang.org/x/term v0.13.0 // indirect
|
||||
golang.org/x/text v0.13.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230629202037-9506855d4529 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect
|
||||
google.golang.org/grpc v1.56.3 // indirect
|
||||
google.golang.org/protobuf v1.31.0 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 // indirect
|
||||
go.opentelemetry.io/otel v1.21.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.21.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.21.0 // indirect
|
||||
go.uber.org/atomic v1.10.0 // indirect
|
||||
go.uber.org/multierr v1.9.0 // indirect
|
||||
golang.org/x/crypto v0.21.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
|
||||
golang.org/x/net v0.23.0 // indirect
|
||||
golang.org/x/oauth2 v0.16.0 // indirect
|
||||
golang.org/x/sync v0.6.0 // indirect
|
||||
golang.org/x/sys v0.22.0 // indirect
|
||||
golang.org/x/term v0.18.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
google.golang.org/api v0.155.0 // indirect
|
||||
google.golang.org/appengine v1.6.8 // indirect
|
||||
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect
|
||||
google.golang.org/grpc v1.62.1 // indirect
|
||||
google.golang.org/protobuf v1.33.0 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
pgregory.net/rapid v0.5.5 // indirect
|
||||
sigs.k8s.io/yaml v1.3.0 // indirect
|
||||
nhooyr.io/websocket v1.8.6 // indirect
|
||||
pgregory.net/rapid v1.1.0 // indirect
|
||||
)
|
||||
|
||||
replace github.com/planetmint/planetmint-go => ../
|
||||
|
1094
lib/go.sum
1094
lib/go.sum
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
package dao
|
||||
package machine
|
||||
|
||||
import (
|
||||
"testing"
|
||||
@ -8,8 +8,9 @@ import (
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
func TestE2ETestSuite(t *testing.T) {
|
||||
func TestE2ELibTestSuite(t *testing.T) {
|
||||
t.Parallel()
|
||||
cfg := network.DefaultConfig()
|
||||
cfg := network.LoaderDefaultConfig()
|
||||
cfg.NumValidators = 2
|
||||
suite.Run(t, NewE2ETestSuite(cfg))
|
||||
}
|
146
lib/tests/e2e/suite.go
Normal file
146
lib/tests/e2e/suite.go
Normal file
@ -0,0 +1,146 @@
|
||||
package machine
|
||||
|
||||
import (
|
||||
"github.com/cosmos/cosmos-sdk/crypto/hd"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
"github.com/planetmint/planetmint-go/lib"
|
||||
"github.com/planetmint/planetmint-go/lib/trustwallet"
|
||||
clitestutil "github.com/planetmint/planetmint-go/testutil/cli"
|
||||
"github.com/planetmint/planetmint-go/testutil/network"
|
||||
"github.com/planetmint/planetmint-go/testutil/sample"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
const (
|
||||
SerialPort = "/dev/ttyACM0"
|
||||
)
|
||||
|
||||
// E2ETestSuite struct definition of machine suite
|
||||
type E2ETestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
cfg network.Config
|
||||
network *network.Network
|
||||
}
|
||||
|
||||
// NewE2ETestSuite returns configured machine E2ETestSuite
|
||||
func NewE2ETestSuite(cfg network.Config) *E2ETestSuite {
|
||||
return &E2ETestSuite{cfg: cfg}
|
||||
}
|
||||
|
||||
// SetupSuite initializes machine E2ETestSuite
|
||||
func (s *E2ETestSuite) SetupSuite() {
|
||||
s.T().Log("setting up e2e lib test suite")
|
||||
|
||||
s.network = network.Load(s.T(), s.cfg)
|
||||
}
|
||||
|
||||
// TearDownSuite clean up after testing
|
||||
func (s *E2ETestSuite) TearDownSuite() {
|
||||
s.T().Log("tearing down e2e lib test suite")
|
||||
}
|
||||
|
||||
func (s *E2ETestSuite) TestBankSendBroadcastTxWithFileLock() {
|
||||
val := s.network.Validators[0]
|
||||
|
||||
kb := val.ClientCtx.Keyring
|
||||
account, err := kb.NewAccount(sample.Name, sample.Mnemonic, keyring.DefaultBIP39Passphrase, sample.DefaultDerivationPath, hd.Secp256k1)
|
||||
s.Require().NoError(err)
|
||||
|
||||
addr, err := account.GetAddress()
|
||||
s.Require().NoError(err)
|
||||
|
||||
libConfig := lib.GetConfig()
|
||||
libConfig.SetFeeDenom("stake")
|
||||
|
||||
// incorrect denom
|
||||
coin := sdk.NewCoins(sdk.NewInt64Coin("foobar", 1000))
|
||||
msg := banktypes.NewMsgSend(val.Address, addr, coin)
|
||||
|
||||
out, err := lib.BroadcastTxWithFileLock(val.Address, msg)
|
||||
s.Require().NoError(err)
|
||||
|
||||
txResponse, err := lib.GetTxResponseFromOut(out)
|
||||
s.Require().NoError(err)
|
||||
assert.Equal(s.T(), "received wrong fee denom; got: stake required: plmnt: invalid coins", txResponse.RawLog)
|
||||
|
||||
libConfig.SetFeeDenom(sample.FeeDenom)
|
||||
|
||||
// incorrect coin
|
||||
out, err = lib.BroadcastTxWithFileLock(val.Address, msg)
|
||||
s.Require().NoError(err)
|
||||
|
||||
txResponse, err = lib.GetTxResponseFromOut(out)
|
||||
s.Require().NoError(err)
|
||||
assert.Equal(s.T(), "[]", txResponse.RawLog)
|
||||
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
_, err = clitestutil.GetRawLogFromTxOut(val, out)
|
||||
assert.Equal(s.T(), "failed to execute message; message index: 0: spendable balance is smaller than 1000foobar: insufficient funds", err.Error())
|
||||
|
||||
// valid transaction
|
||||
coin = sdk.NewCoins(sdk.NewInt64Coin("stake", 1000))
|
||||
msg = banktypes.NewMsgSend(val.Address, addr, coin)
|
||||
|
||||
out, err = lib.BroadcastTxWithFileLock(val.Address, msg)
|
||||
s.Require().NoError(err)
|
||||
|
||||
txResponse, err = lib.GetTxResponseFromOut(out)
|
||||
s.Require().NoError(err)
|
||||
assert.Equal(s.T(), "[]", txResponse.RawLog)
|
||||
}
|
||||
|
||||
func (s *E2ETestSuite) TestLoadKeys() {
|
||||
s.T().SkipNow()
|
||||
_, err := setKeys()
|
||||
if err == nil {
|
||||
_, err = loadKeys()
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
}
|
||||
|
||||
func (s *E2ETestSuite) TestOccSigning() {
|
||||
s.T().SkipNow()
|
||||
val := s.network.Validators[0]
|
||||
|
||||
keys, err := loadKeys()
|
||||
s.Require().NoError(err)
|
||||
|
||||
addr := sdk.MustAccAddressFromBech32(keys.PlanetmintAddress)
|
||||
|
||||
coin := sdk.NewCoins(sdk.NewInt64Coin("stake", 10))
|
||||
msg := banktypes.NewMsgSend(addr, val.Address, coin)
|
||||
|
||||
libConfig := lib.GetConfig()
|
||||
libConfig.SetSerialPort(SerialPort)
|
||||
|
||||
out, err := lib.BroadcastTxWithFileLock(addr, msg)
|
||||
s.Require().NoError(err)
|
||||
|
||||
txResponse, err := lib.GetTxResponseFromOut(out)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal("[]", txResponse.RawLog)
|
||||
s.Require().Equal(uint32(0), txResponse.Code)
|
||||
}
|
||||
|
||||
// set sample mnemonic on trust wallet
|
||||
func setKeys() (string, error) {
|
||||
connector, err := trustwallet.NewTrustWalletConnector(SerialPort)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return connector.RecoverFromMnemonic(sample.Mnemonic)
|
||||
}
|
||||
|
||||
func loadKeys() (*trustwallet.PlanetMintKeys, error) {
|
||||
connector, err := trustwallet.NewTrustWalletConnector(SerialPort)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return connector.GetPlanetmintKeys()
|
||||
}
|
139
lib/trustwallet/occ.go
Normal file
139
lib/trustwallet/occ.go
Normal file
@ -0,0 +1,139 @@
|
||||
package trustwallet
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"go.bug.st/serial"
|
||||
)
|
||||
|
||||
const (
|
||||
SlipEnd = 0xC0
|
||||
SlipEsc = 0xDB
|
||||
SlipEscEnd = 0xDC
|
||||
SlipEscEsc = 0xDD
|
||||
nsPerUs = 1000
|
||||
nsPerMs = 8000 * nsPerUs
|
||||
)
|
||||
|
||||
// occDo performs the operations to send and receive data over serial port.
|
||||
func occDo(data []byte, bufferDelayMs int, portName string, outBuffer []byte) (int, error) {
|
||||
// Initialize unencoded and encoded payloads
|
||||
payloadUnencoded := make([]byte, 0, len(data))
|
||||
payloadSlipEncoded := make([]byte, 0, len(data)*2)
|
||||
|
||||
// Copy data to payloadUnencoded
|
||||
payloadUnencoded = append(payloadUnencoded, data...)
|
||||
|
||||
// Open serial port
|
||||
mode := &serial.Mode{BaudRate: 115200}
|
||||
s, err := serial.Open(portName, mode)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("unable to open serial port: %w", err)
|
||||
}
|
||||
defer s.Close()
|
||||
|
||||
// Encode payload using SLIP
|
||||
encodeSLIP(payloadUnencoded, &payloadSlipEncoded)
|
||||
|
||||
// Send encoded payload over serial
|
||||
if _, err := s.Write(payloadSlipEncoded); err != nil {
|
||||
return 0, fmt.Errorf("unable to write to serial port: %w", err)
|
||||
}
|
||||
|
||||
time.Sleep(time.Duration(bufferDelayMs) * time.Millisecond)
|
||||
|
||||
// Read response from serial
|
||||
readBuffer := make([]byte, 1)
|
||||
encodedResponse := make([]byte, 0)
|
||||
|
||||
slipMsgFramer := 0
|
||||
|
||||
for {
|
||||
n, err := s.Read(readBuffer)
|
||||
if err != nil && !errors.Is(err, io.EOF) {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
continue
|
||||
}
|
||||
if n == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
encodedResponse = append(encodedResponse, readBuffer[0])
|
||||
|
||||
if readBuffer[0] == SlipEnd {
|
||||
if slipMsgFramer == 1 {
|
||||
break
|
||||
}
|
||||
slipMsgFramer++
|
||||
}
|
||||
time.Sleep(1 * time.Millisecond)
|
||||
}
|
||||
|
||||
// Decode SLIP response
|
||||
decodedResponse, err := decodeSLIP(encodedResponse)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("unable to decode SLIP: %w", err)
|
||||
}
|
||||
|
||||
// Copy decoded response to outBuffer
|
||||
copyLength := min(len(decodedResponse), len(outBuffer))
|
||||
copy(outBuffer, decodedResponse[:copyLength])
|
||||
|
||||
return copyLength, nil
|
||||
}
|
||||
|
||||
// encodeSLIP encodes data using SLIP protocol.
|
||||
func encodeSLIP(data []byte, encoded *[]byte) {
|
||||
*encoded = append(*encoded, SlipEnd)
|
||||
for _, b := range data {
|
||||
switch b {
|
||||
case SlipEnd:
|
||||
*encoded = append(*encoded, SlipEsc, SlipEscEnd)
|
||||
case SlipEsc:
|
||||
*encoded = append(*encoded, SlipEsc, SlipEscEsc)
|
||||
default:
|
||||
*encoded = append(*encoded, b)
|
||||
}
|
||||
}
|
||||
*encoded = append(*encoded, SlipEnd)
|
||||
}
|
||||
|
||||
// decodeSLIP decodes SLIP-encoded data.
|
||||
func decodeSLIP(encoded []byte) ([]byte, error) {
|
||||
// Check for empty input
|
||||
if len(encoded) == 0 {
|
||||
return nil, errors.New("encoded data is empty")
|
||||
}
|
||||
|
||||
// Remove first and last SLIP_END bytes
|
||||
if encoded[0] == SlipEnd {
|
||||
encoded = encoded[1:]
|
||||
}
|
||||
if encoded[len(encoded)-1] == SlipEnd {
|
||||
encoded = encoded[:len(encoded)-1]
|
||||
}
|
||||
|
||||
decoded := make([]byte, 0, len(encoded))
|
||||
esc := false
|
||||
|
||||
for _, b := range encoded {
|
||||
switch {
|
||||
case b == SlipEsc && !esc:
|
||||
esc = true
|
||||
case b == SlipEscEnd && esc:
|
||||
decoded = append(decoded, SlipEnd)
|
||||
esc = false
|
||||
case b == SlipEscEsc && esc:
|
||||
decoded = append(decoded, SlipEsc)
|
||||
esc = false
|
||||
default:
|
||||
decoded = append(decoded, b)
|
||||
esc = false
|
||||
}
|
||||
}
|
||||
|
||||
return decoded, nil
|
||||
}
|
88
lib/trustwallet/osc_message_sender.go
Normal file
88
lib/trustwallet/osc_message_sender.go
Normal file
@ -0,0 +1,88 @@
|
||||
package trustwallet
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
PrefixIhw = "/IHW"
|
||||
BufferSize = 1024
|
||||
BufferDelayMs = 200
|
||||
)
|
||||
|
||||
type OSCResponse struct {
|
||||
Command string
|
||||
Data []string
|
||||
}
|
||||
|
||||
type OSCMessageSender struct {
|
||||
portName []byte
|
||||
bufferSize int
|
||||
bufferDelayMs int
|
||||
}
|
||||
|
||||
func NewOSCMessageSender(portName string) (*OSCMessageSender, error) {
|
||||
return &OSCMessageSender{
|
||||
portName: []byte(portName),
|
||||
bufferSize: BufferSize,
|
||||
bufferDelayMs: BufferDelayMs,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *OSCMessageSender) SendMessage(message []byte) (OSCResponse, error) {
|
||||
outputBuffer := make([]byte, s.bufferSize)
|
||||
|
||||
// Call occDo function
|
||||
outputLength, err := occDo(
|
||||
message,
|
||||
s.bufferDelayMs,
|
||||
string(s.portName),
|
||||
outputBuffer,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return OSCResponse{}, fmt.Errorf("failed to send message: %w", err)
|
||||
}
|
||||
|
||||
if outputLength == 0 {
|
||||
return OSCResponse{}, errors.New("no response received")
|
||||
}
|
||||
|
||||
// Extract the information from the output buffer
|
||||
return extractInformation(outputBuffer[:outputLength])
|
||||
}
|
||||
|
||||
func extractInformation(responseBytes []byte) (OSCResponse, error) {
|
||||
decodedString := string(bytes.Trim(responseBytes, "\x00"))
|
||||
parts := strings.Split(decodedString, "\x00")
|
||||
|
||||
var response OSCResponse
|
||||
if len(parts) > 0 {
|
||||
commandPart := parts[0]
|
||||
dataParts := parts[1:]
|
||||
|
||||
if strings.Contains(commandPart, ",") {
|
||||
splitCmd := strings.SplitN(commandPart, ",", 2)
|
||||
response.Command = strings.TrimSpace(splitCmd[0])
|
||||
dataParts = append([]string{splitCmd[1]}, dataParts...)
|
||||
} else {
|
||||
response.Command = strings.TrimSpace(commandPart)
|
||||
}
|
||||
|
||||
response.Data = make([]string, 0, len(dataParts))
|
||||
for _, part := range dataParts {
|
||||
if trimmed := strings.TrimSpace(part); trimmed != "" {
|
||||
response.Data = append(response.Data, trimmed)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(response.Data) == 0 {
|
||||
response.Data = []string{"No valid data found."}
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
290
lib/trustwallet/trustwallet.go
Normal file
290
lib/trustwallet/trustwallet.go
Normal file
@ -0,0 +1,290 @@
|
||||
package trustwallet
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"strconv"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const (
|
||||
NoDataReturned = "no data returned"
|
||||
NoPublicKeyReturned = "no public key returned"
|
||||
NoSignatureReturned = "no signature returned"
|
||||
)
|
||||
|
||||
var (
|
||||
keys *PlanetMintKeys
|
||||
)
|
||||
|
||||
type Connector struct {
|
||||
oscSender *OSCMessageSender
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
func NewTrustWalletConnector(portName string) (*Connector, error) {
|
||||
sender, err := NewOSCMessageSender(portName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Connector{
|
||||
oscSender: sender,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (t *Connector) sendOSCMessage(address string, args ...interface{}) (OSCResponse, error) {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
|
||||
message, err := encodeOSCMessage(address, args...)
|
||||
if err != nil {
|
||||
return OSCResponse{}, err
|
||||
}
|
||||
|
||||
return t.oscSender.SendMessage(message)
|
||||
}
|
||||
|
||||
func (t *Connector) ValiseGet() (string, error) {
|
||||
response, err := t.sendOSCMessage(PrefixIhw + "/getSeed")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(response.Data) > 1 {
|
||||
return response.Data[1], nil
|
||||
}
|
||||
return "", errors.New(NoDataReturned)
|
||||
}
|
||||
|
||||
func (t *Connector) CreateMnemonic() (string, error) {
|
||||
response, err := t.sendOSCMessage(PrefixIhw+"/mnemonicToSeed", int32(1))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(response.Data) > 1 {
|
||||
return response.Data[1], nil
|
||||
}
|
||||
return "", errors.New(NoDataReturned)
|
||||
}
|
||||
|
||||
func (t *Connector) InjectPlanetminkeyToSE050(slot int) (bool, error) {
|
||||
response, err := t.sendOSCMessage(PrefixIhw+"/se050InjectSECPKeys", int32(slot))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if len(response.Data) > 1 {
|
||||
return response.Data[1] == "0", nil
|
||||
}
|
||||
return false, errors.New(NoDataReturned)
|
||||
}
|
||||
|
||||
func (t *Connector) RecoverFromMnemonic(mnemonic string) (string, error) {
|
||||
response, err := t.sendOSCMessage(PrefixIhw+"/mnemonicToSeed", int32(1), mnemonic)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(response.Data) > 1 {
|
||||
return response.Data[1], nil
|
||||
}
|
||||
return "", errors.New(NoDataReturned)
|
||||
}
|
||||
|
||||
func (t *Connector) GetPlanetmintKeys() (*PlanetMintKeys, error) {
|
||||
if keys == nil {
|
||||
response, err := t.sendOSCMessage(PrefixIhw + "/getPlntmntKeys")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(response.Data) < 4 {
|
||||
return nil, errors.New("trust wallet not initialized. Please initialize the wallet")
|
||||
}
|
||||
|
||||
keys = &PlanetMintKeys{
|
||||
PlanetmintAddress: response.Data[1],
|
||||
ExtendedLiquidPubkey: response.Data[2],
|
||||
ExtendedPlanetmintPubkey: response.Data[3],
|
||||
RawPlanetmintPubkey: response.Data[4],
|
||||
}
|
||||
}
|
||||
return keys, nil
|
||||
}
|
||||
|
||||
func (t *Connector) GetSeedSE050() (string, error) {
|
||||
response, err := t.sendOSCMessage(PrefixIhw + "/se050GetSeed")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(response.Data) > 1 {
|
||||
return response.Data[1], nil
|
||||
}
|
||||
return "", errors.New(NoDataReturned)
|
||||
}
|
||||
|
||||
func (t *Connector) SignHashWithPlanetmint(dataToSign string) (string, error) {
|
||||
response, err := t.sendOSCMessage(PrefixIhw+"/ecdsaSignPlmnt", dataToSign)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(response.Data) > 1 {
|
||||
return response.Data[1], nil
|
||||
}
|
||||
return "", errors.New(NoSignatureReturned)
|
||||
}
|
||||
|
||||
func (t *Connector) SignHashWithRDDL(dataToSign string) (string, error) {
|
||||
response, err := t.sendOSCMessage(PrefixIhw+"/ecdsaSignRddl", dataToSign)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(response.Data) > 1 {
|
||||
return response.Data[1], nil
|
||||
}
|
||||
return "", errors.New(NoSignatureReturned)
|
||||
}
|
||||
|
||||
func (t *Connector) CreateOptegaKeypair(ctx int) (string, error) {
|
||||
response, err := t.sendOSCMessage(PrefixIhw+"/optigaTrustXCreateSecret", int32(ctx), "")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(response.Data) > 1 {
|
||||
return response.Data[1], nil
|
||||
}
|
||||
return "", errors.New(NoPublicKeyReturned)
|
||||
}
|
||||
|
||||
func (t *Connector) SignWithOptega(ctx int, dataToSign, pubkey string) (string, error) {
|
||||
response, err := t.sendOSCMessage(PrefixIhw+"/optigaTrustXSignMessage", int32(ctx), dataToSign, pubkey, "")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(response.Data) > 1 {
|
||||
return response.Data[1], nil
|
||||
}
|
||||
return "", errors.New(NoSignatureReturned)
|
||||
}
|
||||
|
||||
func (t *Connector) UnwrapPublicKey(publicKey string) (bool, string) {
|
||||
length := len(publicKey)
|
||||
if length == 136 || length == 130 {
|
||||
return true, publicKey[len(publicKey)-128:]
|
||||
} else if length == 128 {
|
||||
return true, publicKey
|
||||
}
|
||||
return false, publicKey
|
||||
}
|
||||
|
||||
func (t *Connector) CalculateHash(dataToSign string) (string, error) {
|
||||
response, err := t.sendOSCMessage(PrefixIhw+"/se050CalculateHash", dataToSign)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(response.Data) > 1 {
|
||||
return response.Data[1], nil
|
||||
}
|
||||
return "", errors.New("no hash returned")
|
||||
}
|
||||
|
||||
func (t *Connector) CreateSE050KeypairNIST(ctx int) (string, error) {
|
||||
response, err := t.sendOSCMessage(PrefixIhw+"/se050CreateKeyPair", int32(ctx), int32(1))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(response.Data) > 1 {
|
||||
return response.Data[1], nil
|
||||
}
|
||||
return "", errors.New(NoPublicKeyReturned)
|
||||
}
|
||||
|
||||
func (t *Connector) GetPublicKeyFromSE050(ctx int) (string, error) {
|
||||
response, err := t.sendOSCMessage(PrefixIhw+"/se050GetPublicKey", int32(ctx))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(response.Data) > 1 {
|
||||
valid, pubKey := t.UnwrapPublicKey(response.Data[1])
|
||||
if !valid {
|
||||
return "", errors.New("inject PlanetMintKey failed: No key found")
|
||||
}
|
||||
return pubKey, nil
|
||||
}
|
||||
return "", errors.New(NoPublicKeyReturned)
|
||||
}
|
||||
|
||||
func (t *Connector) SignWithSE050(dataToSign string, ctx int) (string, error) {
|
||||
response, err := t.sendOSCMessage(PrefixIhw+"/se050SignData", dataToSign, int32(ctx))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(response.Data) > 1 {
|
||||
return response.Data[1], nil
|
||||
}
|
||||
return "", errors.New(NoSignatureReturned)
|
||||
}
|
||||
|
||||
func (t *Connector) VerifySE050Signature(dataToSign, signature string, ctx int) (bool, error) {
|
||||
response, err := t.sendOSCMessage(PrefixIhw+"/se050VerifySignature", dataToSign, signature, int32(ctx))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if len(response.Data) > 1 {
|
||||
return strconv.ParseBool(response.Data[1])
|
||||
}
|
||||
return false, errors.New("no verification result returned")
|
||||
}
|
||||
|
||||
func encodeOSCMessage(address string, args ...interface{}) (returnBytes []byte, err error) {
|
||||
var buffer bytes.Buffer
|
||||
|
||||
// Write address
|
||||
buffer.WriteString(address)
|
||||
buffer.WriteByte(0)
|
||||
alignBuffer(&buffer)
|
||||
|
||||
// Write type tags
|
||||
buffer.WriteByte(',')
|
||||
for _, arg := range args {
|
||||
switch arg.(type) {
|
||||
case int32:
|
||||
err = buffer.WriteByte('i')
|
||||
case float32:
|
||||
err = buffer.WriteByte('f')
|
||||
case string:
|
||||
err = buffer.WriteByte('s')
|
||||
}
|
||||
if err != nil {
|
||||
return buffer.Bytes(), err
|
||||
}
|
||||
}
|
||||
|
||||
buffer.WriteByte(0)
|
||||
alignBuffer(&buffer)
|
||||
|
||||
// Write arguments
|
||||
for _, arg := range args {
|
||||
switch v := arg.(type) {
|
||||
case int32:
|
||||
err = binary.Write(&buffer, binary.BigEndian, v)
|
||||
case float32:
|
||||
err = binary.Write(&buffer, binary.BigEndian, v)
|
||||
case string:
|
||||
_, err = buffer.WriteString(v)
|
||||
if err != nil {
|
||||
return buffer.Bytes(), err
|
||||
}
|
||||
err = buffer.WriteByte(0)
|
||||
alignBuffer(&buffer)
|
||||
}
|
||||
if err != nil {
|
||||
return buffer.Bytes(), err
|
||||
}
|
||||
}
|
||||
|
||||
return buffer.Bytes(), nil
|
||||
}
|
||||
|
||||
func alignBuffer(buffer *bytes.Buffer) {
|
||||
for buffer.Len()%4 != 0 {
|
||||
buffer.WriteByte(0)
|
||||
}
|
||||
}
|
8
lib/trustwallet/types.go
Normal file
8
lib/trustwallet/types.go
Normal file
@ -0,0 +1,8 @@
|
||||
package trustwallet
|
||||
|
||||
type PlanetMintKeys struct {
|
||||
PlanetmintAddress string
|
||||
ExtendedLiquidPubkey string
|
||||
ExtendedPlanetmintPubkey string
|
||||
RawPlanetmintPubkey string
|
||||
}
|
319
lib/tx.go
319
lib/tx.go
@ -1,28 +1,34 @@
|
||||
package lib
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/cometbft/cometbft/crypto"
|
||||
comethttp "github.com/cometbft/cometbft/rpc/client/http"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
"github.com/planetmint/planetmint-go/lib/trustwallet"
|
||||
)
|
||||
|
||||
var ErrTypeAssertionFailed = errors.New("type assertion failed")
|
||||
var (
|
||||
ErrTypeAssertionFailed = errors.New("type assertion failed")
|
||||
LibSyncAccess sync.Mutex
|
||||
)
|
||||
|
||||
func init() {
|
||||
GetConfig()
|
||||
@ -38,31 +44,51 @@ func getAccountNumberAndSequence(clientCtx client.Context) (accountNumber, seque
|
||||
return
|
||||
}
|
||||
|
||||
func getClientContextAndTxFactory(address sdk.AccAddress) (clientCtx client.Context, txf tx.Factory, err error) {
|
||||
clientCtx, err = getClientContext(address)
|
||||
func getClientContextAndTxFactory(fromAddress sdk.AccAddress, withoutFee bool) (clientCtx client.Context, txf tx.Factory, err error) {
|
||||
clientCtx = GetConfig().ClientCtx
|
||||
// at least we need an account retriever
|
||||
// it would be better to check for an empty client context, but that does not work at the moment
|
||||
if clientCtx.AccountRetriever == nil {
|
||||
clientCtx, err = getClientContext(fromAddress)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
record, err := clientCtx.Keyring.KeyByAddress(fromAddress)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// name and address of private key with which to sign
|
||||
clientCtx = clientCtx.
|
||||
WithFromAddress(fromAddress).
|
||||
WithFromName(record.Name)
|
||||
|
||||
accountNumber, sequence, err := getAccountNumberAndSequence(clientCtx)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
txf = getTxFactoryWithAccountNumberAndSequence(clientCtx, accountNumber, sequence)
|
||||
gasPrice := "0.000005"
|
||||
if withoutFee {
|
||||
gasPrice = "0.0"
|
||||
}
|
||||
txf = getTxFactoryWithAccountNumberAndSequence(clientCtx, accountNumber, sequence, gasPrice)
|
||||
return
|
||||
}
|
||||
|
||||
func getTxFactoryWithAccountNumberAndSequence(clientCtx client.Context, accountNumber, sequence uint64) (txf tx.Factory) {
|
||||
func getTxFactoryWithAccountNumberAndSequence(clientCtx client.Context, accountNumber, sequence uint64, gasPrice string) (txf tx.Factory) {
|
||||
return tx.Factory{}.
|
||||
WithAccountNumber(accountNumber).
|
||||
WithAccountRetriever(clientCtx.AccountRetriever).
|
||||
WithChainID(clientCtx.ChainID).
|
||||
WithGas(200000).
|
||||
WithGasPrices("0.000005plmnt").
|
||||
WithFeeGranter(clientCtx.FeeGranter).
|
||||
WithGas(GetConfig().TxGas).
|
||||
WithGasPrices(gasPrice + GetConfig().FeeDenom).
|
||||
WithKeybase(clientCtx.Keyring).
|
||||
WithSequence(sequence).
|
||||
WithTxConfig(clientCtx.TxConfig)
|
||||
}
|
||||
|
||||
func getClientContext(address sdk.AccAddress) (clientCtx client.Context, err error) {
|
||||
func getClientContext(fromAddress sdk.AccAddress) (clientCtx client.Context, err error) {
|
||||
encodingConfig := GetConfig().EncodingConfig
|
||||
|
||||
rootDir := GetConfig().RootDir
|
||||
@ -70,12 +96,12 @@ func getClientContext(address sdk.AccAddress) (clientCtx client.Context, err err
|
||||
codec := encodingConfig.Marshaler
|
||||
keyringOptions := []keyring.Option{}
|
||||
|
||||
keyring, err := keyring.New("lib", keyring.BackendTest, rootDir, input, codec, keyringOptions...)
|
||||
keyring, err := GetConfig().GetLibKeyring()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
record, err := keyring.KeyByAddress(address)
|
||||
record, err := keyring.KeyByAddress(fromAddress)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@ -94,8 +120,8 @@ func getClientContext(address sdk.AccAddress) (clientCtx client.Context, err err
|
||||
ChainID: GetConfig().ChainID,
|
||||
Client: wsClient,
|
||||
Codec: codec,
|
||||
From: address.String(),
|
||||
FromAddress: address,
|
||||
From: fromAddress.String(),
|
||||
FromAddress: fromAddress,
|
||||
FromName: record.Name,
|
||||
HomeDir: rootDir,
|
||||
Input: input,
|
||||
@ -113,10 +139,21 @@ func getClientContext(address sdk.AccAddress) (clientCtx client.Context, err err
|
||||
return
|
||||
}
|
||||
|
||||
func isMachineAttestationMsg(msgs ...sdk.Msg) (isMachineAttestation bool) {
|
||||
if len(msgs) != 1 {
|
||||
return
|
||||
}
|
||||
if sdk.MsgTypeURL(msgs[0]) == "/planetmintgo.machine.MsgAttestMachine" {
|
||||
isMachineAttestation = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// BuildUnsignedTx builds a transaction to be signed given a set of messages.
|
||||
// Once created, the fee, memo, and messages are set.
|
||||
func BuildUnsignedTx(address sdk.AccAddress, msgs ...sdk.Msg) (txJSON string, err error) {
|
||||
clientCtx, txf, err := getClientContextAndTxFactory(address)
|
||||
func BuildUnsignedTx(fromAddress sdk.AccAddress, msgs ...sdk.Msg) (txJSON string, err error) {
|
||||
withoutFee := isMachineAttestationMsg(msgs...)
|
||||
clientCtx, txf, err := getClientContextAndTxFactory(fromAddress, withoutFee)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@ -133,101 +170,20 @@ func BuildUnsignedTx(address sdk.AccAddress, msgs ...sdk.Msg) (txJSON string, er
|
||||
return
|
||||
}
|
||||
|
||||
// BroadcastTx broadcasts a transaction via RPC.
|
||||
func BroadcastTx(address sdk.AccAddress, msgs ...sdk.Msg) (broadcastTxResponseJSON string, err error) {
|
||||
clientCtx, txf, err := getClientContextAndTxFactory(address)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
broadcastTxResponseJSON, err = broadcastTx(clientCtx, txf, msgs...)
|
||||
return
|
||||
}
|
||||
|
||||
func broadcastTx(clientCtx client.Context, txf tx.Factory, msgs ...sdk.Msg) (broadcastTxResponseJSON string, err error) {
|
||||
func broadcastTx(clientCtx client.Context, txf tx.Factory, msgs ...sdk.Msg) (out *bytes.Buffer, err error) {
|
||||
err = tx.GenerateOrBroadcastTxWithFactory(clientCtx, txf, msgs...)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
output, ok := clientCtx.Output.(*bytes.Buffer)
|
||||
if !ok {
|
||||
err = ErrTypeAssertionFailed
|
||||
return
|
||||
}
|
||||
|
||||
result := make(map[string]interface{})
|
||||
err = json.Unmarshal(output.Bytes(), &result)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
code, ok := result["code"].(float64)
|
||||
if !ok {
|
||||
err = ErrTypeAssertionFailed
|
||||
return
|
||||
}
|
||||
if code != 0 {
|
||||
err = errors.New(output.String())
|
||||
return
|
||||
}
|
||||
|
||||
broadcastTxResponseJSON = output.String()
|
||||
return
|
||||
}
|
||||
func getSequenceFromFile(seqFile *os.File, filename string) (sequence uint64, err error) {
|
||||
var sequenceString string
|
||||
lineCount := int64(0)
|
||||
scanner := bufio.NewScanner(seqFile)
|
||||
for scanner.Scan() {
|
||||
sequenceString = scanner.Text()
|
||||
lineCount++
|
||||
}
|
||||
err = scanner.Err()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if lineCount == 0 {
|
||||
err = errors.New("Sequence file empty " + filename + ": no lines")
|
||||
return
|
||||
} else if lineCount != 1 {
|
||||
err = errors.New("Malformed " + filename + ": wrong number of lines")
|
||||
return
|
||||
}
|
||||
sequence, err = strconv.ParseUint(sequenceString, 10, 64)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getSequenceFromChain(clientCtx client.Context) (sequence uint64, err error) {
|
||||
// Get sequence number from chain.
|
||||
account, err := clientCtx.AccountRetriever.GetAccount(clientCtx, clientCtx.FromAddress)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
sequence = account.GetSequence()
|
||||
return
|
||||
return writeClientCtxOutputToBuffer(clientCtx)
|
||||
}
|
||||
|
||||
// BroadcastTxWithFileLock broadcasts a transaction via gRPC and synchronises requests via a file lock.
|
||||
func BroadcastTxWithFileLock(address sdk.AccAddress, msgs ...sdk.Msg) (broadcastTxResponseJSON string, err error) {
|
||||
func BroadcastTxWithFileLock(fromAddress sdk.AccAddress, msgs ...sdk.Msg) (out *bytes.Buffer, err error) {
|
||||
LibSyncAccess.Lock()
|
||||
defer LibSyncAccess.Unlock()
|
||||
// open and lock file, if it exists
|
||||
usr, err := user.Current()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
homeDir := usr.HomeDir
|
||||
|
||||
addrHex := hex.EncodeToString(address)
|
||||
filename := filepath.Join(GetConfig().RootDir, addrHex+".sequence")
|
||||
|
||||
// Expand tilde to user's home directory.
|
||||
if filename == "~" {
|
||||
filename = homeDir
|
||||
} else if strings.HasPrefix(filename, "~/") {
|
||||
filename = filepath.Join(homeDir, filename[2:])
|
||||
}
|
||||
|
||||
file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, 0644)
|
||||
file, err := openSequenceFile(fromAddress)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@ -245,12 +201,13 @@ func BroadcastTxWithFileLock(address sdk.AccAddress, msgs ...sdk.Msg) (broadcast
|
||||
}()
|
||||
|
||||
// get basic chain information
|
||||
clientCtx, txf, err := getClientContextAndTxFactory(address)
|
||||
withoutFee := isMachineAttestationMsg(msgs...)
|
||||
clientCtx, txf, err := getClientContextAndTxFactory(fromAddress, withoutFee)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
sequenceFromFile, errFile := getSequenceFromFile(file, filename)
|
||||
sequenceFromFile, errFile := getSequenceFromFile(file)
|
||||
sequenceFromChain, errChain := getSequenceFromChain(clientCtx)
|
||||
|
||||
var sequence uint64
|
||||
@ -265,11 +222,25 @@ func BroadcastTxWithFileLock(address sdk.AccAddress, msgs ...sdk.Msg) (broadcast
|
||||
|
||||
// Set new sequence number
|
||||
txf = txf.WithSequence(sequence)
|
||||
broadcastTxResponseJSON, err = broadcastTx(clientCtx, txf, msgs...)
|
||||
if GetConfig().SerialPort != "" {
|
||||
out, err = broadcastTxWithTrustWalletSignature(clientCtx, txf, msgs...)
|
||||
} else {
|
||||
out, err = broadcastTx(clientCtx, txf, msgs...)
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
txResponse, err := GetTxResponseFromOut(out)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Only increase counter if broadcast was successful
|
||||
if txResponse.Code != 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// Increase counter for next round.
|
||||
sequence++
|
||||
|
||||
@ -282,3 +253,135 @@ func BroadcastTxWithFileLock(address sdk.AccAddress, msgs ...sdk.Msg) (broadcast
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func broadcastTxWithTrustWalletSignature(clientCtx client.Context, txf tx.Factory, msgs ...sdk.Msg) (out *bytes.Buffer, err error) {
|
||||
txBuilder, err := txf.BuildUnsignedTx(msgs...)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = signWithTrustWallet(txf, clientCtx, txBuilder); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
txBytes, err := clientCtx.TxConfig.TxEncoder()(txBuilder.GetTx())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
res, err := clientCtx.BroadcastTx(txBytes)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = clientCtx.PrintProto(res); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return writeClientCtxOutputToBuffer(clientCtx)
|
||||
}
|
||||
|
||||
func writeClientCtxOutputToBuffer(clientCtx client.Context) (out *bytes.Buffer, err error) {
|
||||
output, ok := clientCtx.Output.(*bytes.Buffer)
|
||||
if !ok {
|
||||
err = ErrTypeAssertionFailed
|
||||
return
|
||||
}
|
||||
defer output.Reset()
|
||||
|
||||
result := make(map[string]interface{})
|
||||
err = json.Unmarshal(output.Bytes(), &result)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Make a copy because we `defer output.Reset()`
|
||||
out = &bytes.Buffer{}
|
||||
// This is still copying references: *out = *output
|
||||
// Make a real copy: https://stackoverflow.com/a/69758157
|
||||
out.Write(output.Bytes())
|
||||
return
|
||||
}
|
||||
|
||||
func signWithTrustWallet(txf tx.Factory, clientCtx client.Context, txBuilder client.TxBuilder) error {
|
||||
connector, err := trustwallet.NewTrustWalletConnector(GetConfig().SerialPort)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
keys, err := connector.GetPlanetmintKeys()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pubkeyBytes, err := hex.DecodeString(keys.RawPlanetmintPubkey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pk := secp256k1.PubKey{Key: pubkeyBytes}
|
||||
|
||||
signMode := txf.SignMode()
|
||||
if signMode == signing.SignMode_SIGN_MODE_UNSPECIFIED {
|
||||
// use the SignModeHandler's default mode if unspecified
|
||||
signMode = clientCtx.TxConfig.SignModeHandler().DefaultMode()
|
||||
}
|
||||
|
||||
signerData := authsigning.SignerData{
|
||||
ChainID: txf.ChainID(),
|
||||
AccountNumber: txf.AccountNumber(),
|
||||
Sequence: txf.Sequence(),
|
||||
PubKey: &pk,
|
||||
Address: sdk.AccAddress(pk.Address()).String(),
|
||||
}
|
||||
|
||||
sigData := signing.SingleSignatureData{
|
||||
SignMode: signMode,
|
||||
Signature: nil,
|
||||
}
|
||||
|
||||
sig := signing.SignatureV2{
|
||||
PubKey: &pk,
|
||||
Data: &sigData,
|
||||
Sequence: txf.Sequence(),
|
||||
}
|
||||
|
||||
if err := txBuilder.SetSignatures(sig); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bytesToSign, err := clientCtx.TxConfig.SignModeHandler().GetSignBytes(signMode, signerData, txBuilder.GetTx())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
hashBytesToSign := crypto.Sha256(bytesToSign)
|
||||
hexHash := hex.EncodeToString(hashBytesToSign)
|
||||
|
||||
hexSig, err := connector.SignHashWithPlanetmint(hexHash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
signature, err := hex.DecodeString(hexSig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sigData = signing.SingleSignatureData{
|
||||
SignMode: signMode,
|
||||
Signature: signature,
|
||||
}
|
||||
sig = signing.SignatureV2{
|
||||
PubKey: &pk,
|
||||
Data: &sigData,
|
||||
Sequence: txf.Sequence(),
|
||||
}
|
||||
|
||||
if err = txBuilder.SetSignatures(sig); err != nil {
|
||||
return fmt.Errorf("unable to set signatures on payload: %w", err)
|
||||
}
|
||||
|
||||
// Run optional preprocessing if specified. By default, this is unset
|
||||
// and will return nil.
|
||||
return txf.PreprocessTx(clientCtx.FromName, txBuilder)
|
||||
}
|
||||
|
107
lib/utils.go
Normal file
107
lib/utils.go
Normal file
@ -0,0 +1,107 @@
|
||||
package lib
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"os"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
func getSequenceFromFile(seqFile *os.File) (sequence uint64, err error) {
|
||||
var sequenceString string
|
||||
lineCount := int64(0)
|
||||
scanner := bufio.NewScanner(seqFile)
|
||||
for scanner.Scan() {
|
||||
sequenceString = scanner.Text()
|
||||
lineCount++
|
||||
}
|
||||
err = scanner.Err()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if lineCount == 0 {
|
||||
err = errors.New("Sequence file empty " + seqFile.Name() + ": no lines")
|
||||
return
|
||||
} else if lineCount != 1 {
|
||||
err = errors.New("Malformed " + seqFile.Name() + ": wrong number of lines")
|
||||
return
|
||||
}
|
||||
sequence, err = strconv.ParseUint(sequenceString, 10, 64)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getSequenceFromChain(clientCtx client.Context) (sequence uint64, err error) {
|
||||
// get sequence number from chain
|
||||
account, err := clientCtx.AccountRetriever.GetAccount(clientCtx, clientCtx.FromAddress)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
sequence = account.GetSequence()
|
||||
return
|
||||
}
|
||||
|
||||
func createSequenceDirectory() (path string, err error) {
|
||||
usr, err := user.Current()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
homeDir := usr.HomeDir
|
||||
path = filepath.Join(GetConfig().RootDir, "sequence")
|
||||
// expand tilde to user's home directory
|
||||
if strings.HasPrefix(path, "~/") {
|
||||
path = filepath.Join(homeDir, path[2:])
|
||||
}
|
||||
_, err = os.Stat(path)
|
||||
// directory already exists
|
||||
if !os.IsNotExist(err) {
|
||||
return
|
||||
}
|
||||
err = os.Mkdir(path, os.ModePerm)
|
||||
return
|
||||
}
|
||||
|
||||
func openSequenceFile(fromAddress sdk.AccAddress) (file *os.File, err error) {
|
||||
path, err := createSequenceDirectory()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
addrHex := hex.EncodeToString(fromAddress)
|
||||
filename := filepath.Join(path, addrHex)
|
||||
|
||||
file, err = os.OpenFile(filename, os.O_RDWR|os.O_CREATE, 0644)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetTxResponseFromOut converts strings to numbers and unmarshalles out into TxResponse struct
|
||||
func GetTxResponseFromOut(out *bytes.Buffer) (txResponse sdk.TxResponse, err error) {
|
||||
m := regexp.MustCompile(`"([0-9]+?)"`)
|
||||
str := m.ReplaceAllString(out.String(), "${1}")
|
||||
|
||||
// We might have YAML here, so we need to convert to JSON first, because TxResponse struct lacks `yaml:"height,omitempty"`, etc.
|
||||
// Since JSON is a subset of YAML, passing JSON through YAMLToJSON is a no-op and the result is the byte array of the JSON again.
|
||||
j, err := yaml.YAMLToJSON([]byte(str))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = json.Unmarshal(j, &txResponse)
|
||||
return
|
||||
}
|
109
monitor/backend.go
Normal file
109
monitor/backend.go
Normal file
@ -0,0 +1,109 @@
|
||||
package monitor
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/syndtr/goleveldb/leveldb/iterator"
|
||||
)
|
||||
|
||||
type LastSeenEvent struct {
|
||||
Address string `binding:"required" json:"address"`
|
||||
Timestamp int64 `binding:"required" json:"timestamp"`
|
||||
}
|
||||
|
||||
func (mms *MqttMonitor) AddParticipant(address string, lastSeenTS int64) (err error) {
|
||||
// store receive address - planetmint address pair
|
||||
var lastSeen LastSeenEvent
|
||||
lastSeen.Address = address
|
||||
lastSeen.Timestamp = lastSeenTS
|
||||
|
||||
lastSeenBytes, err := json.Marshal(lastSeen)
|
||||
if err != nil {
|
||||
Log("error serializing ConversionRequest: " + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// returns an error if the entry does not exist (we have to increase the counter in this case)
|
||||
_, err = mms.db.Get([]byte(address), nil)
|
||||
if err != nil {
|
||||
mms.setNumDBElements(mms.getNumDBElements() + 1)
|
||||
}
|
||||
mms.dbMutex.Lock()
|
||||
defer mms.dbMutex.Unlock()
|
||||
err = mms.db.Put([]byte(address), lastSeenBytes, nil)
|
||||
if err != nil {
|
||||
Log("error storing addresses in DB: " + err.Error())
|
||||
} else {
|
||||
Log("stored address in DB: " + address)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (mms *MqttMonitor) deleteEntry(key []byte) (err error) {
|
||||
mms.setNumDBElements(mms.getNumDBElements() - 1)
|
||||
mms.dbMutex.Lock()
|
||||
defer mms.dbMutex.Unlock()
|
||||
return mms.db.Delete(key, nil)
|
||||
}
|
||||
|
||||
func (mms *MqttMonitor) getAmountOfElements() (amount int64, err error) {
|
||||
iter := mms.db.NewIterator(nil, nil)
|
||||
defer iter.Release()
|
||||
|
||||
for iter.Next() {
|
||||
amount++
|
||||
}
|
||||
|
||||
// Check for any errors encountered during iteration
|
||||
if err := iter.Error(); err != nil {
|
||||
Log("" + err.Error())
|
||||
} else {
|
||||
Log("elements: " + strconv.FormatInt(amount, 10))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
func (mms *MqttMonitor) getDataFromIter(iter iterator.Iterator) (lastSeen LastSeenEvent, err error) {
|
||||
key := iter.Key()
|
||||
value := iter.Value()
|
||||
err = json.Unmarshal(value, &lastSeen)
|
||||
if err != nil {
|
||||
Log("failed to unmarshal entry: " + string(key) + " - " + err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (mms *MqttMonitor) CleanupDB() {
|
||||
// Create an iterator for the database
|
||||
Log("starting clean-up process")
|
||||
iter := mms.db.NewIterator(nil, nil)
|
||||
defer iter.Release() // Make sure to release the iterator at the end
|
||||
|
||||
// Iterate over all elements in the database
|
||||
for iter.Next() && !mms.IsTerminated() {
|
||||
// Use iter.Key() and iter.Value() to access the key and value
|
||||
lastSeen, err := mms.getDataFromIter(iter)
|
||||
if err != nil {
|
||||
Log("failed to unmarshal entry: " + string(iter.Key()) + " - " + err.Error())
|
||||
continue
|
||||
}
|
||||
timeThreshold := time.Now().Add(-1 * mms.CleanupPeriodicityInMinutes * time.Minute).Unix()
|
||||
if lastSeen.Timestamp <= timeThreshold {
|
||||
// If the entry is older than 12 hours, delete it
|
||||
err := mms.deleteEntry(iter.Key())
|
||||
if err != nil {
|
||||
Log("failed to delete entry: " + err.Error())
|
||||
} else {
|
||||
Log("delete entry: " + string(iter.Key()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check for any errors encountered during iteration
|
||||
if err := iter.Error(); err != nil {
|
||||
Log("error during cleanup : " + err.Error())
|
||||
}
|
||||
}
|
83
monitor/interface.go
Normal file
83
monitor/interface.go
Normal file
@ -0,0 +1,83 @@
|
||||
package monitor
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/cometbft/cometbft/libs/log"
|
||||
"github.com/planetmint/planetmint-go/config"
|
||||
"github.com/syndtr/goleveldb/leveldb"
|
||||
)
|
||||
|
||||
type MQTTMonitorClientI interface {
|
||||
AddParticipant(address string, lastSeenTS int64) (err error)
|
||||
SelectPoPParticipantsOutOfActiveActors() (challenger string, challengee string, err error)
|
||||
GetActiveActorCount() (count uint64)
|
||||
Start() (err error)
|
||||
}
|
||||
|
||||
var monitorMutex sync.RWMutex
|
||||
var mqttLogger log.Logger
|
||||
var mqttMonitorInstance MQTTMonitorClientI
|
||||
|
||||
func SetMqttMonitorInstance(monitorInstance MQTTMonitorClientI) {
|
||||
monitorMutex.Lock()
|
||||
defer monitorMutex.Unlock()
|
||||
mqttMonitorInstance = monitorInstance
|
||||
}
|
||||
|
||||
func GetMqttMonitorInstance() (monitorInstance MQTTMonitorClientI) {
|
||||
monitorMutex.Lock()
|
||||
defer monitorMutex.Unlock()
|
||||
return mqttMonitorInstance
|
||||
}
|
||||
|
||||
func LazyMqttMonitorLoader(logger log.Logger, homeDir string) {
|
||||
monitorMutex.RLock()
|
||||
tmpInstance := mqttMonitorInstance
|
||||
monitorMutex.RUnlock()
|
||||
if tmpInstance != nil {
|
||||
return
|
||||
}
|
||||
if logger != nil {
|
||||
mqttLogger = logger
|
||||
}
|
||||
if homeDir == "" {
|
||||
homeDir = "./"
|
||||
}
|
||||
aciveActorsDB, err := leveldb.OpenFile(homeDir+"activeActors.db", nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
SetMqttMonitorInstance(NewMqttMonitorService(aciveActorsDB, *config.GetConfig()))
|
||||
}
|
||||
|
||||
func SelectPoPParticipantsOutOfActiveActors() (challenger string, challengee string, err error) {
|
||||
monitorMutex.RLock()
|
||||
defer monitorMutex.RUnlock()
|
||||
return mqttMonitorInstance.SelectPoPParticipantsOutOfActiveActors()
|
||||
}
|
||||
|
||||
func Start() (err error) {
|
||||
err = mqttMonitorInstance.Start()
|
||||
return
|
||||
}
|
||||
|
||||
func AddParticipant(address string, lastSeenTS int64) (err error) {
|
||||
monitorMutex.RLock()
|
||||
defer monitorMutex.RUnlock()
|
||||
return mqttMonitorInstance.AddParticipant(address, lastSeenTS)
|
||||
}
|
||||
|
||||
func GetActiveActorCount() (count uint64) {
|
||||
monitorMutex.RLock()
|
||||
defer monitorMutex.RUnlock()
|
||||
return mqttMonitorInstance.GetActiveActorCount()
|
||||
}
|
||||
|
||||
func Log(msg string) {
|
||||
if mqttLogger == nil {
|
||||
return
|
||||
}
|
||||
mqttLogger.Info("[app] [monitor] " + msg)
|
||||
}
|
37
monitor/mocks/mqtt_monitor.go
Normal file
37
monitor/mocks/mqtt_monitor.go
Normal file
@ -0,0 +1,37 @@
|
||||
package mocks
|
||||
|
||||
import "log"
|
||||
|
||||
// MockMQTTMonitorClientI is a mock of MQTTMonitorClientI interface.
|
||||
type MockMQTTMonitorClientI struct {
|
||||
myStringList []string
|
||||
}
|
||||
|
||||
// AddParticipant mocks base method.
|
||||
func (m *MockMQTTMonitorClientI) AddParticipant(address string, _ int64) error {
|
||||
log.Println("[app] [Monitor] [Mock] added participant: " + address)
|
||||
m.myStringList = append(m.myStringList, address)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SelectPoPParticipantsOutOfActiveActors mocks base method.
|
||||
func (m *MockMQTTMonitorClientI) SelectPoPParticipantsOutOfActiveActors() (string, string, error) {
|
||||
var challenger, challengee string
|
||||
amount := len(m.myStringList)
|
||||
if amount >= 2 {
|
||||
challenger = m.myStringList[amount-2]
|
||||
challengee = m.myStringList[amount-1]
|
||||
}
|
||||
log.Println("[app] [Monitor] [Mock] participants: " + challenger + ", " + challengee)
|
||||
return challenger, challengee, nil
|
||||
}
|
||||
|
||||
func (m *MockMQTTMonitorClientI) GetActiveActorCount() (count uint64) {
|
||||
return uint64(len(m.myStringList))
|
||||
}
|
||||
|
||||
// Start mocks base method.
|
||||
func (m *MockMQTTMonitorClientI) Start() error {
|
||||
return nil
|
||||
}
|
410
monitor/mqtt_monitor.go
Normal file
410
monitor/mqtt_monitor.go
Normal file
@ -0,0 +1,410 @@
|
||||
package monitor
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
mqtt "github.com/eclipse/paho.mqtt.golang"
|
||||
"github.com/planetmint/planetmint-go/config"
|
||||
"github.com/planetmint/planetmint-go/util"
|
||||
"github.com/syndtr/goleveldb/leveldb"
|
||||
)
|
||||
|
||||
var MonitorMQTTClient util.MQTTClientI
|
||||
|
||||
type MqttMonitor struct {
|
||||
db *leveldb.DB
|
||||
dbMutex sync.Mutex // Mutex to synchronize write operations
|
||||
CleanupPeriodicityInMinutes time.Duration
|
||||
config config.Config
|
||||
numberOfElementsMutex sync.RWMutex
|
||||
numberOfElements int64
|
||||
isTerminated bool
|
||||
terminationMutex sync.RWMutex
|
||||
maxRetries time.Duration
|
||||
lostConnection bool
|
||||
lostConnectionMutex sync.Mutex
|
||||
clientMutex sync.Mutex
|
||||
localMqttClient util.MQTTClientI
|
||||
}
|
||||
|
||||
func (mms *MqttMonitor) Terminate() {
|
||||
mms.terminationMutex.Lock()
|
||||
defer mms.terminationMutex.Unlock()
|
||||
mms.isTerminated = true
|
||||
}
|
||||
|
||||
func (mms *MqttMonitor) IsTerminated() (isTerminated bool) {
|
||||
mms.terminationMutex.RLock()
|
||||
defer mms.terminationMutex.RUnlock()
|
||||
return mms.isTerminated
|
||||
}
|
||||
|
||||
func (mms *MqttMonitor) getNumDBElements() int64 {
|
||||
mms.numberOfElementsMutex.RLock()
|
||||
defer mms.numberOfElementsMutex.RUnlock()
|
||||
return mms.numberOfElements
|
||||
}
|
||||
|
||||
func (mms *MqttMonitor) setNumDBElements(numElements int64) {
|
||||
mms.numberOfElementsMutex.Lock()
|
||||
defer mms.numberOfElementsMutex.Unlock()
|
||||
mms.numberOfElements = numElements
|
||||
}
|
||||
|
||||
func getClientID() string {
|
||||
conf := config.GetConfig()
|
||||
return "monitor-" + conf.GetNodeAddress()
|
||||
}
|
||||
|
||||
func (mms *MqttMonitor) lazyLoadMonitorMQTTClient() util.MQTTClientI {
|
||||
if MonitorMQTTClient != nil {
|
||||
return MonitorMQTTClient
|
||||
}
|
||||
|
||||
conf := config.GetConfig()
|
||||
hostPort := net.JoinHostPort(conf.MqttDomain, strconv.FormatInt(int64(conf.MqttPort), 10))
|
||||
uri := "tcp://" + hostPort
|
||||
if conf.MqttTLS {
|
||||
uri = "ssl://" + hostPort
|
||||
}
|
||||
|
||||
opts := mqtt.NewClientOptions().AddBroker(uri).SetKeepAlive(time.Second * 60).SetCleanSession(true)
|
||||
opts.SetClientID(getClientID())
|
||||
opts.SetUsername(conf.MqttUser)
|
||||
opts.SetPassword(conf.MqttPassword)
|
||||
opts.SetConnectionLostHandler(mms.onConnectionLost)
|
||||
if conf.MqttTLS {
|
||||
tlsConfig := &tls.Config{}
|
||||
opts.SetTLSConfig(tlsConfig)
|
||||
}
|
||||
|
||||
Log("create new client")
|
||||
client := mqtt.NewClient(opts)
|
||||
return client
|
||||
}
|
||||
|
||||
func NewMqttMonitorService(db *leveldb.DB, config config.Config) *MqttMonitor {
|
||||
service := &MqttMonitor{db: db, config: config, numberOfElements: 0, CleanupPeriodicityInMinutes: 10}
|
||||
return service
|
||||
}
|
||||
|
||||
func (mms *MqttMonitor) runPeriodicTasks() {
|
||||
tickerRestablishConnection := time.NewTicker(2 * time.Minute)
|
||||
tickerCleanup := time.NewTicker(5 * time.Minute)
|
||||
defer tickerRestablishConnection.Stop()
|
||||
defer tickerCleanup.Stop()
|
||||
|
||||
for !mms.IsTerminated() {
|
||||
select {
|
||||
case <-tickerRestablishConnection.C:
|
||||
go mms.MonitorActiveParticipants()
|
||||
case <-tickerCleanup.C:
|
||||
go mms.CleanupDB()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (mms *MqttMonitor) Start() (err error) {
|
||||
amount, err := mms.getAmountOfElements()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
mms.setNumDBElements(amount)
|
||||
go mms.runPeriodicTasks()
|
||||
go mms.MonitorActiveParticipants()
|
||||
go mms.CleanupDB()
|
||||
return
|
||||
}
|
||||
func (mms *MqttMonitor) getRandomNumbers() (challenger int, challengee int) {
|
||||
for challenger == challengee {
|
||||
// Generate random numbers
|
||||
numElements := int(mms.getNumDBElements())
|
||||
challenger = rand.Intn(numElements)
|
||||
challengee = rand.Intn(numElements)
|
||||
}
|
||||
return
|
||||
}
|
||||
func (mms *MqttMonitor) SelectPoPParticipantsOutOfActiveActors() (challenger string, challengee string, err error) {
|
||||
numElements := int(mms.getNumDBElements())
|
||||
if numElements < 2 {
|
||||
return
|
||||
}
|
||||
randomChallenger, randomChallengee := mms.getRandomNumbers()
|
||||
Log("number of elements: " + strconv.Itoa(numElements))
|
||||
Log("selected IDs: " + strconv.Itoa(randomChallenger) + " " + strconv.Itoa(randomChallengee))
|
||||
iter := mms.db.NewIterator(nil, nil)
|
||||
defer iter.Release()
|
||||
count := 0
|
||||
found := 0
|
||||
var lastSeen LastSeenEvent
|
||||
for iter.Next() {
|
||||
if count == randomChallenger {
|
||||
lastSeen, err = mms.getDataFromIter(iter)
|
||||
if err != nil {
|
||||
Log("could not get Data from ID" + strconv.Itoa(randomChallenger))
|
||||
return
|
||||
}
|
||||
challenger = lastSeen.Address
|
||||
found++
|
||||
} else if count == randomChallengee {
|
||||
lastSeen, err = mms.getDataFromIter(iter)
|
||||
if err != nil {
|
||||
Log("could not get Data from ID" + strconv.Itoa(randomChallengee))
|
||||
return
|
||||
}
|
||||
challengee = lastSeen.Address
|
||||
found++
|
||||
}
|
||||
|
||||
count++
|
||||
if found == 2 {
|
||||
break
|
||||
}
|
||||
}
|
||||
Log("challenger, challengee: " + challenger + " " + challengee)
|
||||
return
|
||||
}
|
||||
|
||||
func (mms *MqttMonitor) GetActiveActorCount() (count uint64) {
|
||||
count = uint64(mms.getNumDBElements())
|
||||
return
|
||||
}
|
||||
|
||||
func (mms *MqttMonitor) MqttMsgHandler(_ mqtt.Client, msg mqtt.Message) {
|
||||
if mms.IsTerminated() {
|
||||
return
|
||||
}
|
||||
topicParts := strings.Split(msg.Topic(), "/")
|
||||
if len(topicParts) != 3 {
|
||||
return
|
||||
}
|
||||
if topicParts[0] != "tele" {
|
||||
return
|
||||
}
|
||||
if topicParts[2] != "STATE" {
|
||||
return
|
||||
}
|
||||
address := topicParts[1]
|
||||
valid, err := util.IsValidAddress(address)
|
||||
if err != nil || !valid {
|
||||
return
|
||||
}
|
||||
|
||||
active, err := IsLegitMachineAddress(address)
|
||||
if err != nil || !active {
|
||||
return
|
||||
}
|
||||
|
||||
unixTime := time.Now().Unix()
|
||||
err = mms.AddParticipant(address, unixTime)
|
||||
|
||||
if err != nil {
|
||||
Log("error adding active actor to DB: " + address + " " + err.Error())
|
||||
} else {
|
||||
Log("added active actor to DB: " + address)
|
||||
}
|
||||
}
|
||||
|
||||
func IsLegitMachineAddress(address string) (active bool, err error) {
|
||||
url := "http://localhost:1317/planetmint/machine/address/" + address
|
||||
|
||||
// Create a new HTTP client
|
||||
client := &http.Client{}
|
||||
|
||||
// Create a new request
|
||||
ctx := context.Background()
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||
if err != nil {
|
||||
Log("cannot send machine query request " + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Set the header
|
||||
req.Header.Set("Accept", "application/json")
|
||||
|
||||
// Send the request
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
Log("cannot connect to server: " + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Close the response body
|
||||
defer resp.Body.Close()
|
||||
|
||||
// Read the response body
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
Log("cannot read response: " + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Check the status code
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
Log("unexpected status code: " + string(body))
|
||||
return
|
||||
}
|
||||
|
||||
// Unmarshal the response body into a map
|
||||
var data map[string]interface{}
|
||||
err = json.Unmarshal(body, &data)
|
||||
if err != nil {
|
||||
Log("cannot unmarshal response " + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Check if the "info" key exists
|
||||
machineValue, ok := data["machine"]
|
||||
if !ok {
|
||||
Log("response does not contain the required machine")
|
||||
return
|
||||
}
|
||||
machineMap, ok := machineValue.(map[string]interface{})
|
||||
if !ok {
|
||||
Log("cannot convert machine map")
|
||||
return
|
||||
}
|
||||
addressMap, ok := machineMap["address"]
|
||||
if !ok {
|
||||
Log("response does not contain the required name")
|
||||
return
|
||||
}
|
||||
value, ok := addressMap.(string)
|
||||
if !ok || value != address {
|
||||
Log("return machine is not the required one")
|
||||
return
|
||||
}
|
||||
|
||||
err = nil
|
||||
active = true
|
||||
return
|
||||
}
|
||||
|
||||
func (mms *MqttMonitor) onConnectionLost(_ mqtt.Client, err error) {
|
||||
Log("connection lost: " + err.Error())
|
||||
// Handle connection loss here (e.g., reconnect attempts, logging)
|
||||
if !mms.IsTerminated() {
|
||||
mms.setConnectionStatus(true)
|
||||
}
|
||||
}
|
||||
|
||||
func (mms *MqttMonitor) MonitorActiveParticipants() {
|
||||
mqttClient, err := mms.initializeClient()
|
||||
if err != nil {
|
||||
Log(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Maximum reconnection attempts (adjust as needed)
|
||||
mms.SetMaxRetries()
|
||||
|
||||
for !mms.IsTerminated() && mms.maxRetries > 0 {
|
||||
if !mms.connectClient(mqttClient) {
|
||||
continue
|
||||
}
|
||||
|
||||
if !mms.subscribeToTopic(mqttClient) {
|
||||
continue
|
||||
}
|
||||
|
||||
mms.monitorConnection(mqttClient)
|
||||
}
|
||||
|
||||
mms.handleConnectionTermination()
|
||||
}
|
||||
|
||||
func (mms *MqttMonitor) initializeClient() (mqttClient util.MQTTClientI, err error) {
|
||||
mms.clientMutex.Lock()
|
||||
defer mms.clientMutex.Unlock()
|
||||
|
||||
if mms.localMqttClient != nil {
|
||||
return nil, errors.New("client is still working")
|
||||
}
|
||||
|
||||
mms.localMqttClient = mms.lazyLoadMonitorMQTTClient()
|
||||
return mms.localMqttClient, nil
|
||||
}
|
||||
|
||||
func (mms *MqttMonitor) connectClient(mqttClient util.MQTTClientI) bool {
|
||||
if token := mqttClient.Connect(); token.Wait() && token.Error() != nil {
|
||||
Log("error connecting to mqtt: " + token.Error().Error())
|
||||
mms.maxRetries--
|
||||
time.Sleep(time.Second * 5)
|
||||
return false
|
||||
}
|
||||
|
||||
mms.setConnectionStatus(false)
|
||||
Log("established connection")
|
||||
return true
|
||||
}
|
||||
|
||||
func (mms *MqttMonitor) subscribeToTopic(mqttClient util.MQTTClientI) bool {
|
||||
messageHandler := mqtt.MessageHandler(mms.MqttMsgHandler)
|
||||
subscriptionTopic := "tele/#"
|
||||
|
||||
if token := mqttClient.Subscribe(subscriptionTopic, 0, messageHandler); token.Wait() && token.Error() != nil {
|
||||
Log("error registering the mqtt subscription: " + token.Error().Error())
|
||||
return false
|
||||
}
|
||||
|
||||
Log("subscribed to tele/# channels")
|
||||
return true
|
||||
}
|
||||
|
||||
func (mms *MqttMonitor) monitorConnection(mqttClient util.MQTTClientI) {
|
||||
for !mms.IsTerminated() {
|
||||
if mms.isConnectionLost(mqttClient) {
|
||||
Log("retry establishing a connection")
|
||||
break
|
||||
}
|
||||
|
||||
SendUpdateMessage(mqttClient)
|
||||
mms.SetMaxRetries()
|
||||
time.Sleep(60 * time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
func (mms *MqttMonitor) isConnectionLost(mqttClient util.MQTTClientI) bool {
|
||||
mms.lostConnectionMutex.Lock()
|
||||
defer mms.lostConnectionMutex.Unlock()
|
||||
|
||||
return !mqttClient.IsConnected() || !mqttClient.IsConnectionOpen() || mms.lostConnection
|
||||
}
|
||||
|
||||
func (mms *MqttMonitor) setConnectionStatus(lost bool) {
|
||||
mms.lostConnectionMutex.Lock()
|
||||
defer mms.lostConnectionMutex.Unlock()
|
||||
mms.lostConnection = lost
|
||||
}
|
||||
|
||||
func (mms *MqttMonitor) handleConnectionTermination() {
|
||||
if mms.maxRetries == 0 {
|
||||
Log("reached maximum reconnection attempts. Exiting. New client will be activated soon.")
|
||||
}
|
||||
|
||||
mms.clientMutex.Lock()
|
||||
defer mms.clientMutex.Unlock()
|
||||
mms.localMqttClient = nil
|
||||
}
|
||||
|
||||
func SendUpdateMessage(mqttClient util.MQTTClientI) {
|
||||
// Publish message
|
||||
now := time.Now().Format("2006-01-02 15:04:05") // Adjust format as needed
|
||||
token := mqttClient.Publish("tele/"+getClientID(), 1, false, now)
|
||||
token.Wait()
|
||||
}
|
||||
|
||||
func (mms *MqttMonitor) SetMaxRetries() {
|
||||
mms.maxRetries = 5
|
||||
}
|
132
monitor/mqtt_monitor_test.go
Normal file
132
monitor/mqtt_monitor_test.go
Normal file
@ -0,0 +1,132 @@
|
||||
package monitor_test
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/planetmint/planetmint-go/config"
|
||||
"github.com/planetmint/planetmint-go/monitor"
|
||||
"github.com/planetmint/planetmint-go/util/mocks"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/syndtr/goleveldb/leveldb"
|
||||
"github.com/syndtr/goleveldb/leveldb/storage"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// Use MQTT mock client
|
||||
monitor.MonitorMQTTClient = &mocks.MockMQTTClient{}
|
||||
os.Setenv(config.ValAddr, "plmnt10mq5nj8jhh27z7ejnz2ql3nh0qhzjnfvy50877")
|
||||
}
|
||||
|
||||
const (
|
||||
challengerInput = "plmnt1fx3x6u8k5q8kjl7pamsuwjtut8nkks8dk92dek"
|
||||
challengeeInput = "plmnt1fsaljz3xqf6vchkjxfzfrd30cdp3j4vqh298pr"
|
||||
)
|
||||
|
||||
func TestGMonitorActiveParticipants(t *testing.T) {
|
||||
cfg := config.GetConfig()
|
||||
db, err := leveldb.Open(storage.NewMemStorage(), nil)
|
||||
assert.NoError(t, err)
|
||||
defer db.Close()
|
||||
|
||||
mqttMonitor := monitor.NewMqttMonitorService(db, *cfg)
|
||||
err = mqttMonitor.Start()
|
||||
assert.NoError(t, err)
|
||||
|
||||
currentTime := time.Now()
|
||||
unixTime := currentTime.Unix()
|
||||
err = mqttMonitor.AddParticipant(challengerInput, unixTime)
|
||||
assert.NoError(t, err)
|
||||
err = mqttMonitor.AddParticipant(challengeeInput, unixTime)
|
||||
assert.NoError(t, err)
|
||||
mqttMonitor.CleanupDB()
|
||||
|
||||
challenger, challengee, err := mqttMonitor.SelectPoPParticipantsOutOfActiveActors()
|
||||
assert.NoError(t, err)
|
||||
assert.Contains(t, challenger, "plmnt")
|
||||
assert.Contains(t, challengee, "plmnt")
|
||||
mqttMonitor.Terminate()
|
||||
}
|
||||
|
||||
func TestCleanupRemoval(t *testing.T) {
|
||||
cfg := config.GetConfig()
|
||||
db, err := leveldb.Open(storage.NewMemStorage(), nil)
|
||||
assert.NoError(t, err)
|
||||
defer db.Close()
|
||||
|
||||
mqttMonitor := monitor.NewMqttMonitorService(db, *cfg)
|
||||
err = mqttMonitor.Start()
|
||||
assert.NoError(t, err)
|
||||
|
||||
currentTime := time.Now()
|
||||
CleanupPeriodicityAgo := currentTime.Add(-1 * mqttMonitor.CleanupPeriodicityInMinutes * time.Minute)
|
||||
unixTimeNow := currentTime.Unix()
|
||||
err = mqttMonitor.AddParticipant(challengerInput, unixTimeNow)
|
||||
assert.NoError(t, err)
|
||||
err = mqttMonitor.AddParticipant(challengeeInput, CleanupPeriodicityAgo.Unix()-1)
|
||||
assert.NoError(t, err)
|
||||
mqttMonitor.CleanupDB()
|
||||
|
||||
challenger, challengee, err := mqttMonitor.SelectPoPParticipantsOutOfActiveActors()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "", challenger)
|
||||
assert.Contains(t, "", challengee)
|
||||
mqttMonitor.Terminate()
|
||||
}
|
||||
|
||||
func TestCleanupPrecisionTest(t *testing.T) {
|
||||
cfg := config.GetConfig()
|
||||
db, err := leveldb.Open(storage.NewMemStorage(), nil)
|
||||
assert.NoError(t, err)
|
||||
defer db.Close()
|
||||
|
||||
mqttMonitor := monitor.NewMqttMonitorService(db, *cfg)
|
||||
err = mqttMonitor.Start()
|
||||
assert.NoError(t, err)
|
||||
|
||||
currentTime := time.Now()
|
||||
CleanupThresholdAgo := currentTime.Add(-1 * mqttMonitor.CleanupPeriodicityInMinutes * time.Minute)
|
||||
aboveThreshold := CleanupThresholdAgo.Unix() + 10
|
||||
unixTimeNow := currentTime.Unix()
|
||||
err = mqttMonitor.AddParticipant(challengerInput, unixTimeNow)
|
||||
assert.NoError(t, err)
|
||||
err = mqttMonitor.AddParticipant(challengeeInput, aboveThreshold)
|
||||
assert.NoError(t, err)
|
||||
mqttMonitor.CleanupDB()
|
||||
|
||||
challenger, challengee, err := mqttMonitor.SelectPoPParticipantsOutOfActiveActors()
|
||||
assert.NoError(t, err)
|
||||
assert.Contains(t, challenger, "plmnt")
|
||||
assert.Contains(t, challengee, "plmnt")
|
||||
mqttMonitor.Terminate()
|
||||
}
|
||||
|
||||
func TestIsLegitMachineAddress(t *testing.T) {
|
||||
t.SkipNow()
|
||||
active, err := monitor.IsLegitMachineAddress("plmnt1z6xmwqfnn9mvean9gsd57segawgjykpxw8hq5t")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, active, true)
|
||||
}
|
||||
|
||||
func TestGetActiveActorCount(t *testing.T) {
|
||||
cfg := config.GetConfig()
|
||||
db, err := leveldb.Open(storage.NewMemStorage(), nil)
|
||||
assert.NoError(t, err)
|
||||
defer db.Close()
|
||||
|
||||
mqttMonitor := monitor.NewMqttMonitorService(db, *cfg)
|
||||
err = mqttMonitor.Start()
|
||||
assert.NoError(t, err)
|
||||
|
||||
currentTime := time.Now()
|
||||
unixTime := currentTime.Unix()
|
||||
err = mqttMonitor.AddParticipant(challengerInput, unixTime)
|
||||
assert.NoError(t, err)
|
||||
err = mqttMonitor.AddParticipant(challengeeInput, unixTime)
|
||||
assert.NoError(t, err)
|
||||
mqttMonitor.CleanupDB()
|
||||
|
||||
count := mqttMonitor.GetActiveActorCount()
|
||||
assert.Equal(t, uint64(2), count)
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
syntax = "proto3";
|
||||
package planetmintgo.asset;
|
||||
|
||||
option go_package = "github.com/planetmint/planetmint-go/x/asset/types";
|
||||
|
||||
message Asset {
|
||||
string cid = 1;
|
||||
}
|
@ -20,13 +20,13 @@ service Query {
|
||||
|
||||
// Queries a list of GetCIDsByAddress items.
|
||||
rpc GetCIDsByAddress (QueryGetCIDsByAddressRequest) returns (QueryGetCIDsByAddressResponse) {
|
||||
option (google.api.http).get = "/planetmint/asset/get_cids_by_address/{address}/{lookupPeriodInMin}";
|
||||
option (google.api.http).get = "/planetmint/asset/address/{address}/{numElements}";
|
||||
|
||||
}
|
||||
|
||||
// Queries a list of GetNotarizedAsset items.
|
||||
rpc GetNotarizedAsset (QueryGetNotarizedAssetRequest) returns (QueryGetNotarizedAssetResponse) {
|
||||
option (google.api.http).get = "/planetmint/asset/get_notarized_asset/{cid}";
|
||||
option (google.api.http).get = "/planetmint/asset/cid/{cid}";
|
||||
|
||||
}
|
||||
}
|
||||
@ -42,7 +42,7 @@ message QueryParamsResponse {
|
||||
|
||||
message QueryGetCIDsByAddressRequest {
|
||||
string address = 1;
|
||||
uint64 lookupPeriodInMin = 2;
|
||||
uint64 numElements = 2;
|
||||
cosmos.base.query.v1beta1.PageRequest pagination = 3;
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@ message Challenge {
|
||||
string initiator = 1;
|
||||
string challenger = 2;
|
||||
string challengee = 3;
|
||||
uint64 height = 4;
|
||||
int64 height = 4;
|
||||
bool success = 5;
|
||||
string description = 6;
|
||||
bool finished = 6;
|
||||
}
|
||||
|
@ -4,8 +4,6 @@ package planetmintgo.dao;
|
||||
option go_package = "github.com/planetmint/planetmint-go/x/dao/types";
|
||||
|
||||
message DistributionOrder {
|
||||
|
||||
|
||||
string daoAddr = 1;
|
||||
string daoAmount = 2;
|
||||
string daoTxID = 3;
|
||||
@ -18,4 +16,10 @@ message DistributionOrder {
|
||||
int64 firstPop = 10;
|
||||
int64 lastPop = 11;
|
||||
string proposer = 12;
|
||||
string earlyInvAddr = 13;
|
||||
string earlyInvAmount = 14;
|
||||
string earlyInvTxID = 15;
|
||||
string strategicAddr = 16;
|
||||
string strategicAmount = 17;
|
||||
string strategicTxID = 18;
|
||||
}
|
||||
|
@ -1,12 +1,15 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package planetmintgo.dao;
|
||||
|
||||
import "gogoproto/gogo.proto";
|
||||
import "planetmintgo/dao/params.proto";
|
||||
import "planetmintgo/dao/redeem_claim.proto";
|
||||
|
||||
option go_package = "github.com/planetmint/planetmint-go/x/dao/types";
|
||||
|
||||
// GenesisState defines the dao module's genesis state.
|
||||
message GenesisState {
|
||||
Params params = 1 [(gogoproto.nullable) = false];
|
||||
Params params = 1 [(gogoproto.nullable) = false];
|
||||
}
|
||||
|
||||
|
@ -10,4 +10,20 @@ message Params {
|
||||
option (gogoproto.goproto_stringer) = false;
|
||||
|
||||
string mint_address = 1;
|
||||
string token_denom = 2;
|
||||
string staged_denom = 3;
|
||||
string claim_denom = 4;
|
||||
string reissuance_asset = 5;
|
||||
int64 reissuance_epochs = 6;
|
||||
int64 pop_epochs = 7;
|
||||
int64 distribution_offset = 8;
|
||||
string distribution_address_early_inv = 9;
|
||||
string distribution_address_investor = 10;
|
||||
string distribution_address_strategic = 11;
|
||||
string distribution_address_dao = 12;
|
||||
string distribution_address_pop = 13;
|
||||
int64 mqtt_response_timeout = 14;
|
||||
string claim_address = 15;
|
||||
uint64 tx_gas_limit = 16;
|
||||
uint64 validator_pop_reward = 17;
|
||||
}
|
||||
|
@ -9,6 +9,10 @@ import "planetmintgo/dao/params.proto";
|
||||
import "planetmintgo/dao/mint_request.proto";
|
||||
import "planetmintgo/dao/mint_requests.proto";
|
||||
import "planetmintgo/dao/reissuance.proto";
|
||||
import "planetmintgo/dao/challenge.proto";
|
||||
import "amino/amino.proto";
|
||||
import "planetmintgo/dao/distribution_order.proto";
|
||||
import "planetmintgo/dao/redeem_claim.proto";
|
||||
|
||||
option go_package = "github.com/planetmint/planetmint-go/x/dao/types";
|
||||
|
||||
@ -23,25 +27,65 @@ service Query {
|
||||
|
||||
// Queries a list of GetMintRequestsByHash items.
|
||||
rpc GetMintRequestsByHash (QueryGetMintRequestsByHashRequest) returns (QueryGetMintRequestsByHashResponse) {
|
||||
option (google.api.http).get = "/planetmint/dao/get_mint_requests_by_hash/{hash}";
|
||||
option (google.api.http).get = "/planetmint/dao/mint_requests/hash/{hash}";
|
||||
|
||||
}
|
||||
|
||||
// Queries a list of MintRequestsByAddress items.
|
||||
rpc MintRequestsByAddress (QueryMintRequestsByAddressRequest) returns (QueryMintRequestsByAddressResponse) {
|
||||
option (google.api.http).get = "/planetmint/dao/mint_requests_by_address/{address}";
|
||||
option (google.api.http).get = "/planetmint/dao/mint_requests/address/{address}";
|
||||
|
||||
}
|
||||
|
||||
// Queries a list of GetReissuance items.
|
||||
rpc GetReissuance (QueryGetReissuanceRequest) returns (QueryGetReissuanceResponse) {
|
||||
option (google.api.http).get = "/planetmint/dao/get_reissuance/{blockHeight}";
|
||||
option (google.api.http).get = "/planetmint/dao/reissuance/{blockHeight}";
|
||||
|
||||
}
|
||||
|
||||
// Queries a list of GetReissuances items.
|
||||
rpc GetReissuances (QueryGetReissuancesRequest) returns (QueryGetReissuancesResponse) {
|
||||
option (google.api.http).get = "/planetmint/dao/get_reissuances";
|
||||
// Queries a list of Reissuances items.
|
||||
rpc Reissuances (QueryReissuancesRequest) returns (QueryReissuancesResponse) {
|
||||
option (google.api.http).get = "/planetmint/dao/reissuances";
|
||||
|
||||
}
|
||||
|
||||
// Queries a list of GetChallenge items.
|
||||
rpc GetChallenge (QueryGetChallengeRequest) returns (QueryGetChallengeResponse) {
|
||||
option (google.api.http).get = "/planetmint/dao/challenge/{height}";
|
||||
|
||||
}
|
||||
|
||||
// Queries a list of Challenges items.
|
||||
rpc Challenges (QueryChallengesRequest) returns (QueryChallengesResponse) {
|
||||
option (google.api.http).get = "/planetmint/dao/challenges";
|
||||
|
||||
}
|
||||
|
||||
// Queries a list of GetDistribution items.
|
||||
rpc GetDistribution (QueryGetDistributionRequest) returns (QueryGetDistributionResponse) {
|
||||
option (google.api.http).get = "/planetmint/dao/distribution/{height}";
|
||||
|
||||
}
|
||||
|
||||
// Queries a list of RedeemClaim items.
|
||||
rpc RedeemClaim (QueryGetRedeemClaimRequest) returns (QueryGetRedeemClaimResponse) {
|
||||
option (google.api.http).get = "/planetmint/dao/redeem_claim/{beneficiary}/{id}";
|
||||
|
||||
}
|
||||
rpc RedeemClaimAll (QueryAllRedeemClaimRequest) returns (QueryAllRedeemClaimResponse) {
|
||||
option (google.api.http).get = "/planetmint/dao/redeem_claim";
|
||||
|
||||
}
|
||||
|
||||
// Queries a list of RedeemClaimByLiquidTxHash items.
|
||||
rpc RedeemClaimByLiquidTxHash (QueryRedeemClaimByLiquidTxHashRequest) returns (QueryRedeemClaimByLiquidTxHashResponse) {
|
||||
option (google.api.http).get = "/planetmint/dao/redeem_claim_by_liquid_tx_hash/{liquidTxHash}";
|
||||
|
||||
}
|
||||
|
||||
// Queries a list of Distributions items.
|
||||
rpc Distributions (QueryDistributionsRequest) returns (QueryDistributionsResponse) {
|
||||
option (google.api.http).get = "/planetmint/dao/distributions";
|
||||
|
||||
}
|
||||
}
|
||||
@ -79,12 +123,72 @@ message QueryGetReissuanceResponse {
|
||||
Reissuance reissuance = 1;
|
||||
}
|
||||
|
||||
message QueryGetReissuancesRequest {
|
||||
message QueryReissuancesRequest {
|
||||
cosmos.base.query.v1beta1.PageRequest pagination = 1;
|
||||
}
|
||||
|
||||
message QueryGetReissuancesResponse {
|
||||
Reissuance reissuance = 1;
|
||||
cosmos.base.query.v1beta1.PageResponse pagination = 2;
|
||||
message QueryReissuancesResponse {
|
||||
repeated Reissuance reissuances = 1 [(gogoproto.nullable) = false, (amino.dont_omitempty) = true];
|
||||
cosmos.base.query.v1beta1.PageResponse pagination = 2;
|
||||
}
|
||||
|
||||
message QueryGetChallengeRequest {
|
||||
int64 height = 1;
|
||||
}
|
||||
|
||||
message QueryGetChallengeResponse {
|
||||
Challenge challenge = 1;
|
||||
}
|
||||
|
||||
message QueryChallengesRequest {
|
||||
cosmos.base.query.v1beta1.PageRequest pagination = 1;
|
||||
}
|
||||
|
||||
message QueryChallengesResponse {
|
||||
repeated Challenge challenges = 1 [(gogoproto.nullable) = false, (amino.dont_omitempty) = true];
|
||||
cosmos.base.query.v1beta1.PageResponse pagination = 2;
|
||||
}
|
||||
|
||||
message QueryGetDistributionRequest {
|
||||
int64 height = 1;
|
||||
}
|
||||
|
||||
message QueryGetDistributionResponse {
|
||||
DistributionOrder distribution = 1;
|
||||
}
|
||||
|
||||
message QueryGetRedeemClaimRequest {
|
||||
string beneficiary = 1;
|
||||
uint64 id = 2;
|
||||
}
|
||||
|
||||
message QueryGetRedeemClaimResponse {
|
||||
RedeemClaim redeemClaim = 1 [(gogoproto.nullable) = false];
|
||||
}
|
||||
|
||||
message QueryAllRedeemClaimRequest {
|
||||
cosmos.base.query.v1beta1.PageRequest pagination = 1;
|
||||
}
|
||||
|
||||
message QueryAllRedeemClaimResponse {
|
||||
repeated RedeemClaim redeemClaim = 1 [(gogoproto.nullable) = false];
|
||||
cosmos.base.query.v1beta1.PageResponse pagination = 2;
|
||||
}
|
||||
|
||||
message QueryRedeemClaimByLiquidTxHashRequest {
|
||||
string liquidTxHash = 1;
|
||||
}
|
||||
|
||||
message QueryRedeemClaimByLiquidTxHashResponse {
|
||||
RedeemClaim redeemClaim = 1;
|
||||
}
|
||||
|
||||
message QueryDistributionsRequest {
|
||||
cosmos.base.query.v1beta1.PageRequest pagination = 1;
|
||||
}
|
||||
|
||||
message QueryDistributionsResponse {
|
||||
repeated DistributionOrder distributions = 1 [(gogoproto.nullable) = false, (amino.dont_omitempty) = true];
|
||||
cosmos.base.query.v1beta1.PageResponse pagination = 2;
|
||||
}
|
||||
|
||||
|
14
proto/planetmintgo/dao/redeem_claim.proto
Normal file
14
proto/planetmintgo/dao/redeem_claim.proto
Normal file
@ -0,0 +1,14 @@
|
||||
syntax = "proto3";
|
||||
package planetmintgo.dao;
|
||||
|
||||
option go_package = "github.com/planetmint/planetmint-go/x/dao/types";
|
||||
|
||||
message RedeemClaim {
|
||||
uint64 id = 1;
|
||||
string beneficiary = 2;
|
||||
string liquidTxHash = 3;
|
||||
uint64 amount = 4;
|
||||
bool confirmed = 5;
|
||||
string creator = 6;
|
||||
}
|
||||
|
@ -6,7 +6,9 @@ option go_package = "github.com/planetmint/planetmint-go/x/dao/types";
|
||||
message Reissuance {
|
||||
|
||||
string proposer = 1;
|
||||
string rawtx = 2;
|
||||
string command = 2;
|
||||
string txID = 3;
|
||||
int64 blockHeight = 4;
|
||||
int64 firstIncludedPop = 5;
|
||||
int64 lastIncludedPop = 6;
|
||||
}
|
||||
|
@ -10,18 +10,23 @@ import "amino/amino.proto";
|
||||
import "gogoproto/gogo.proto";
|
||||
import "cosmos_proto/cosmos.proto";
|
||||
import "cosmos/msg/v1/msg.proto";
|
||||
import "planetmintgo/dao/redeem_claim.proto";
|
||||
|
||||
option go_package = "github.com/planetmint/planetmint-go/x/dao/types";
|
||||
|
||||
// Msg defines the Msg service.
|
||||
service Msg {
|
||||
rpc ReissueRDDLProposal (MsgReissueRDDLProposal ) returns (MsgReissueRDDLProposalResponse );
|
||||
rpc MintToken (MsgMintToken ) returns (MsgMintTokenResponse );
|
||||
rpc ReissueRDDLResult (MsgReissueRDDLResult ) returns (MsgReissueRDDLResultResponse );
|
||||
rpc DistributionResult (MsgDistributionResult ) returns (MsgDistributionResultResponse );
|
||||
rpc DistributionRequest (MsgDistributionRequest) returns (MsgDistributionRequestResponse);
|
||||
rpc UpdateParams (MsgUpdateParams ) returns (MsgUpdateParamsResponse );
|
||||
rpc ReportPopResult (MsgReportPopResult) returns (MsgReportPopResultResponse);
|
||||
rpc ReissueRDDLProposal (MsgReissueRDDLProposal) returns (MsgReissueRDDLProposalResponse);
|
||||
rpc MintToken (MsgMintToken ) returns (MsgMintTokenResponse );
|
||||
rpc ReissueRDDLResult (MsgReissueRDDLResult ) returns (MsgReissueRDDLResultResponse );
|
||||
rpc DistributionResult (MsgDistributionResult ) returns (MsgDistributionResultResponse );
|
||||
rpc DistributionRequest (MsgDistributionRequest) returns (MsgDistributionRequestResponse);
|
||||
rpc UpdateParams (MsgUpdateParams ) returns (MsgUpdateParamsResponse );
|
||||
rpc ReportPopResult (MsgReportPopResult ) returns (MsgReportPopResultResponse );
|
||||
rpc InitPop (MsgInitPop ) returns (MsgInitPopResponse );
|
||||
rpc CreateRedeemClaim (MsgCreateRedeemClaim ) returns (MsgCreateRedeemClaimResponse );
|
||||
rpc UpdateRedeemClaim (MsgUpdateRedeemClaim ) returns (MsgUpdateRedeemClaimResponse );
|
||||
rpc ConfirmRedeemClaim (MsgConfirmRedeemClaim ) returns (MsgConfirmRedeemClaimResponse );
|
||||
}
|
||||
message MsgReportPopResult {
|
||||
string creator = 1;
|
||||
@ -31,10 +36,12 @@ message MsgReportPopResult {
|
||||
message MsgReportPopResultResponse {}
|
||||
|
||||
message MsgReissueRDDLProposal {
|
||||
string creator = 1;
|
||||
string proposer = 2;
|
||||
string tx = 3;
|
||||
int64 blockHeight = 4;
|
||||
string creator = 1;
|
||||
string proposer = 2;
|
||||
string command = 3;
|
||||
int64 blockHeight = 4;
|
||||
int64 firstIncludedPop = 5;
|
||||
int64 lastIncludedPop = 6;
|
||||
}
|
||||
|
||||
message MsgReissueRDDLProposalResponse {}
|
||||
@ -54,12 +61,15 @@ message MsgReissueRDDLResult {
|
||||
}
|
||||
|
||||
message MsgReissueRDDLResultResponse {}
|
||||
|
||||
message MsgDistributionResult {
|
||||
string creator = 1;
|
||||
int64 lastPop = 2;
|
||||
string daoTxID = 3;
|
||||
string investorTxID = 4;
|
||||
string popTxID = 5;
|
||||
string creator = 1;
|
||||
int64 lastPop = 2;
|
||||
string daoTxID = 3;
|
||||
string investorTxID = 4;
|
||||
string popTxID = 5;
|
||||
string earlyInvestorTxID = 6;
|
||||
string strategicTxID = 7;
|
||||
}
|
||||
|
||||
message MsgDistributionResultResponse {}
|
||||
@ -73,14 +83,49 @@ message MsgDistributionRequestResponse {}
|
||||
|
||||
message MsgUpdateParams {
|
||||
option (cosmos.msg.v1.signer) = "authority";
|
||||
|
||||
|
||||
// authority is the address that controls the module (defaults to x/gov unless overwritten).
|
||||
string authority = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
|
||||
|
||||
// params defines the x/dao parameters to update.
|
||||
//
|
||||
|
||||
// NOTE: All parameters must be supplied.
|
||||
Params params = 2 [(gogoproto.nullable) = false, (amino.dont_omitempty) = true];
|
||||
}
|
||||
|
||||
message MsgUpdateParamsResponse {}
|
||||
|
||||
message MsgInitPop {
|
||||
string creator = 1;
|
||||
string initiator = 2;
|
||||
string challenger = 3;
|
||||
string challengee = 4;
|
||||
int64 height = 5;
|
||||
}
|
||||
|
||||
message MsgInitPopResponse {}
|
||||
|
||||
message MsgCreateRedeemClaim {
|
||||
string creator = 1;
|
||||
string beneficiary = 2;
|
||||
}
|
||||
|
||||
message MsgCreateRedeemClaimResponse {}
|
||||
|
||||
message MsgUpdateRedeemClaim {
|
||||
string creator = 1;
|
||||
uint64 id = 2;
|
||||
string beneficiary = 3;
|
||||
string liquidTxHash = 4;
|
||||
}
|
||||
|
||||
message MsgUpdateRedeemClaimResponse {}
|
||||
|
||||
message MsgConfirmRedeemClaim {
|
||||
string creator = 1;
|
||||
uint64 id = 2;
|
||||
string beneficiary = 3;
|
||||
}
|
||||
|
||||
message MsgConfirmRedeemClaimResponse {}
|
||||
|
||||
|
@ -8,5 +8,9 @@ option go_package = "github.com/planetmint/planetmint-go/x/machine/types";
|
||||
// Params defines the parameters for the module.
|
||||
message Params {
|
||||
option (gogoproto.goproto_stringer) = false;
|
||||
|
||||
string asset_registry_scheme =1;
|
||||
string asset_registry_domain =2;
|
||||
string asset_registry_path =3;
|
||||
uint64 dao_machine_funding_amount = 4;
|
||||
string dao_machine_funding_denom = 5;
|
||||
}
|
||||
|
@ -22,25 +22,36 @@ service Query {
|
||||
|
||||
// Queries a list of GetMachineByPublicKey items.
|
||||
rpc GetMachineByPublicKey (QueryGetMachineByPublicKeyRequest) returns (QueryGetMachineByPublicKeyResponse) {
|
||||
option (google.api.http).get = "/planetmint/machine/get_machine_by_public_key/{publicKey}";
|
||||
option (google.api.http).get = "/planetmint/machine/public_key/{publicKey}";
|
||||
|
||||
}
|
||||
|
||||
// Queries a list of GetTrustAnchorStatus items.
|
||||
rpc GetTrustAnchorStatus (QueryGetTrustAnchorStatusRequest) returns (QueryGetTrustAnchorStatusResponse) {
|
||||
option (google.api.http).get = "/planetmint/machine/get_trust_anchor_status/{machineid}";
|
||||
option (google.api.http).get = "/planetmint/machine/trust_anchor/status/{machineid}";
|
||||
|
||||
}
|
||||
|
||||
// Queries a list of GetMachineByAddress items.
|
||||
rpc GetMachineByAddress (QueryGetMachineByAddressRequest) returns (QueryGetMachineByAddressResponse) {
|
||||
option (google.api.http).get = "/planetmint/machine/get_machine_by_address/{address}";
|
||||
option (google.api.http).get = "/planetmint/machine/address/{address}";
|
||||
|
||||
}
|
||||
|
||||
// Queries a list of GetLiquidAssetsByMachineid items.
|
||||
rpc GetLiquidAssetsByMachineid (QueryGetLiquidAssetsByMachineidRequest) returns (QueryGetLiquidAssetsByMachineidResponse) {
|
||||
option (google.api.http).get = "/planetmint/planetmint-go/machine/get_liquid_assets_by_machineid/{machineID}";
|
||||
option (google.api.http).get = "/planetmint/machine/liquid_assets/{machineID}";
|
||||
|
||||
}
|
||||
|
||||
// Queries a list of ActiveTrustAnchorCount items.
|
||||
rpc ActiveTrustAnchorCount (QueryActiveTrustAnchorCountRequest) returns (QueryActiveTrustAnchorCountResponse) {
|
||||
option (google.api.http).get = "/planetmint/machine/active_trust_anchor_count";
|
||||
}
|
||||
|
||||
// Queries a list of ActivatedTrustAnchorCount items.
|
||||
rpc ActivatedTrustAnchorCount (QueryActivatedTrustAnchorCountRequest) returns (QueryActivatedTrustAnchorCountResponse) {
|
||||
option (google.api.http).get = "/planetmint/machine/activated_trust_anchor_count";
|
||||
|
||||
}
|
||||
}
|
||||
@ -87,3 +98,15 @@ message QueryGetLiquidAssetsByMachineidResponse {
|
||||
LiquidAsset liquidAssetEntry = 1;
|
||||
}
|
||||
|
||||
message QueryActiveTrustAnchorCountRequest {}
|
||||
|
||||
message QueryActiveTrustAnchorCountResponse {
|
||||
uint64 count = 1;
|
||||
}
|
||||
|
||||
message QueryActivatedTrustAnchorCountRequest {}
|
||||
|
||||
message QueryActivatedTrustAnchorCountResponse {
|
||||
uint64 count = 1;
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,11 @@ package planetmintgo.machine;
|
||||
import "planetmintgo/machine/machine.proto";
|
||||
import "planetmintgo/machine/trust_anchor.proto";
|
||||
import "planetmintgo/machine/liquid_asset.proto";
|
||||
import "planetmintgo/machine/params.proto";
|
||||
import "amino/amino.proto";
|
||||
import "gogoproto/gogo.proto";
|
||||
import "cosmos_proto/cosmos.proto";
|
||||
import "cosmos/msg/v1/msg.proto";
|
||||
|
||||
option go_package = "github.com/planetmint/planetmint-go/x/machine/types";
|
||||
|
||||
@ -13,6 +18,7 @@ service Msg {
|
||||
rpc AttestMachine (MsgAttestMachine ) returns (MsgAttestMachineResponse );
|
||||
rpc RegisterTrustAnchor (MsgRegisterTrustAnchor) returns (MsgRegisterTrustAnchorResponse);
|
||||
rpc NotarizeLiquidAsset (MsgNotarizeLiquidAsset) returns (MsgNotarizeLiquidAssetResponse);
|
||||
rpc UpdateParams (MsgUpdateParams ) returns (MsgUpdateParamsResponse );
|
||||
}
|
||||
message MsgAttestMachine {
|
||||
string creator = 1;
|
||||
@ -35,3 +41,17 @@ message MsgNotarizeLiquidAsset {
|
||||
|
||||
message MsgNotarizeLiquidAssetResponse {}
|
||||
|
||||
message MsgUpdateParams {
|
||||
option (cosmos.msg.v1.signer) = "authority";
|
||||
|
||||
// authority is the address that controls the module (defaults to x/gov unless overwritten).
|
||||
string authority = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
|
||||
|
||||
// params defines the x/dao parameters to update.
|
||||
|
||||
// NOTE: All parameters must be supplied.
|
||||
Params params = 2 [(gogoproto.nullable) = false, (amino.dont_omitempty) = true];
|
||||
}
|
||||
|
||||
message MsgUpdateParamsResponse {}
|
||||
|
||||
|
75
readme.md
75
readme.md
@ -1,52 +1,65 @@
|
||||
# planetmintgo
|
||||
**planetmintgo** is a blockchain built using Cosmos SDK and Tendermint and created with [Ignite CLI](https://ignite.com/cli).
|
||||
# planetmint-go
|
||||
**planetmint** is a blockchain built using Cosmos SDK and CometBFT written in Go and created with [Ignite CLI](https://ignite.com/cli).
|
||||
|
||||
## Get started
|
||||
|
||||
```
|
||||
ignite chain serve
|
||||
```
|
||||
|
||||
`serve` command installs dependencies, builds, initializes, and starts your blockchain in development.
|
||||
|
||||
### Configure
|
||||
|
||||
Your blockchain in development can be configured with `config.yml`. To learn more, see the [Ignite CLI docs](https://docs.ignite.com).
|
||||
|
||||
### Web Frontend
|
||||
|
||||
Ignite CLI has scaffolded a Vue.js-based web app in the `vue` directory. Run the following commands to install dependencies and start the app:
|
||||
|
||||
```
|
||||
cd vue
|
||||
npm install
|
||||
npm run serve
|
||||
```
|
||||
|
||||
The frontend app is built using the `@starport/vue` and `@starport/vuex` packages. For details, see the [monorepo for Ignite front-end development](https://github.com/ignite/web).
|
||||
|
||||
## Release
|
||||
To release a new version of your blockchain, create and push a new tag with `v` prefix. A new draft release with the configured targets will be created.
|
||||
|
||||
```
|
||||
git tag v0.1
|
||||
git push origin v0.1
|
||||
```
|
||||
|
||||
After a draft release is created, make your final changes from the release page and publish it.
|
||||
|
||||
### Install
|
||||
To install the latest version of your blockchain node's binary, execute the following command on your machine:
|
||||
To install the latest version of this blockchain node's binary, execute the following command on your machine:
|
||||
```
|
||||
git clone https://github.com/planetmint/planetmint-go.git
|
||||
ignite chain build
|
||||
```
|
||||
|
||||
## Structure
|
||||
```
|
||||
curl https://get.ignite.com/username/planetmint-go@latest! | sudo bash
|
||||
- .github/ ... github workflows
|
||||
- app/ ... app wiring and tx ante handlers
|
||||
- clients/ ... clients for interactions with external services
|
||||
- cmd/ ... entry point, sdk config and top level commands
|
||||
- config/ ... custom planetmint config
|
||||
- docs/ ... openapi docs
|
||||
- errormsg/ ... custom error messages
|
||||
- lib/ ... tools for interacting with planetmint and trust wallet
|
||||
- monitor/ ... MQTT monitor
|
||||
- proto/ ... message and type definitions
|
||||
- tests/ ... e2e test suites
|
||||
- testutil/
|
||||
- tools/ ... sdk tools
|
||||
- util/
|
||||
- x/ ... custom planetmint modules
|
||||
```
|
||||
`username/planetmint-go` should match the `username` and `repo_name` of the Github repository to which the source code was pushed. Learn more about [the install process](https://github.com/allinbits/starport-installer).
|
||||
|
||||
## Testing
|
||||
Follow this [guide](https://docs.cosmos.network/v0.47/build/building-modules/testing) for general testing guidelines.
|
||||
|
||||
The E2E-tests found in the `tests/` folder setup a test network of n-Nodes and running transactions on said network. Tools to mock interactions with external services for these tests can be found in `testutil/network/`.
|
||||
|
||||
For Tests that involve multiple keepers mocks can be found in `x/<module>/testutil/expected_keepers_mocks.go`. These are manipulated in `testutil/keepers/`.
|
||||
|
||||
## Contributing
|
||||
For contributions refer to the RDDL enhancement proposals repository [here](https://github.com/rddl-network/REPs)
|
||||
|
||||
### Adding Module Capabilities
|
||||
Use the `ignite scaffold` [command](https://docs.ignite.com/references/cli#ignite-scaffold) to easily add modules and messages to the existing project. A more manual approach is to add to the `proto/` folder to setup messages and the corresponding message servers and running the `ignite generate proto-go` command.
|
||||
|
||||
### Migrations
|
||||
Module migrations must be registered in each respective module in the `AppModule.RegisterServices(cfg module.Configurator)` function. For each module that is to be upgraded in a migration the ConsensusVersion must be updated. In addition an `UpgradeHandler` needs to be added to the `App.setupUpgradeHandlers()`. Upgrade handlers have a name that needs to be added to an upgrade proposal which needs to be voted on by participating validators.
|
||||
|
||||
For more info see [here](https://docs.cosmos.network/v0.47/learn/advanced/upgrade).
|
||||
|
||||
## Learn more
|
||||
|
||||
- [Ignite CLI](https://ignite.com/cli)
|
||||
- [Tutorials](https://docs.ignite.com/guide)
|
||||
- [Planetmint docs](https://docs.rddl.io)
|
||||
- [Ignite CLI docs](https://docs.ignite.com)
|
||||
- [Cosmos SDK docs](https://docs.cosmos.network)
|
||||
- [Developer Chat](https://discord.gg/ignite)
|
||||
- [Developer Chat](https://discord.gg/uy4CA2Xw54)
|
||||
- [RDDL enhancement Proposals](https://github.com/rddl-network/REPs)
|
||||
|
@ -1,2 +1,2 @@
|
||||
sonar.projectKey=planetmint_planetmint-go_AYjnSLNdwwdSy162QoXI
|
||||
sonar.exclusions=docs/static/openapi.yml,x/**/*.pb.go,x/**/*.pb.gw.go,x/**/module.go,x/**/types/genesis_test.go,x/**/types/params.go,x/**/client/cli/query_params.go,tests/e2e/**/suite.go,app/simulation_test.go
|
||||
sonar.exclusions=docs/static/openapi.yml,x/**/*.pb.go,x/**/*.pb.gw.go,x/**/module.go,x/**/types/genesis_test.go,x/**/types/params.go,x/**/client/cli/query_params.go,tests/e2e/**/suite.go,app/simulation_test.go,x/**/client/cli/tx_update_params.go,x/**/types/message_update_params_test.go,x/**/keeper/message_server_update_params.go,x/**/types/message*test.go,x/**/module_simulation.go,x/**/simulation/*.go,testutil/network/network.go,testutil/network/util.go
|
||||
|
1
staticcheck.conf
Normal file
1
staticcheck.conf
Normal file
@ -0,0 +1 @@
|
||||
checks = ["all", "-SA1019", "-ST1000"]
|
@ -2,15 +2,16 @@ package asset
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/planetmint/planetmint-go/testutil/network"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
func TestE2ETestSuite(t *testing.T) {
|
||||
t.Parallel()
|
||||
cfg := network.DefaultConfig()
|
||||
cfg.NumValidators = 1
|
||||
func TestE2EAssetTestSuite(t *testing.T) {
|
||||
time.Sleep(2 * time.Second)
|
||||
cfg := network.LoaderDefaultConfig()
|
||||
cfg.NumValidators = 3
|
||||
suite.Run(t, NewE2ETestSuite(cfg))
|
||||
}
|
||||
|
@ -1,83 +0,0 @@
|
||||
package asset
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/planetmint/planetmint-go/testutil"
|
||||
"github.com/planetmint/planetmint-go/testutil/sample"
|
||||
|
||||
assettypes "github.com/planetmint/planetmint-go/x/asset/types"
|
||||
|
||||
txtypes "github.com/cosmos/cosmos-sdk/types/tx"
|
||||
)
|
||||
|
||||
// TestNotarizeAssetREST notarizes asset over REST endpoint
|
||||
func (s *E2ETestSuite) TestNotarizeAssetREST() {
|
||||
val := s.network.Validators[0]
|
||||
|
||||
// Create Msg
|
||||
k, err := val.ClientCtx.Keyring.Key(sample.Name)
|
||||
s.Require().NoError(err)
|
||||
|
||||
addr, err := k.GetAddress()
|
||||
s.Require().NoError(err)
|
||||
cid := sample.Asset()
|
||||
testCases := []struct {
|
||||
name string
|
||||
msg assettypes.MsgNotarizeAsset
|
||||
rawLog string
|
||||
expectCheckTxErr bool
|
||||
}{
|
||||
{
|
||||
"invalid address",
|
||||
assettypes.MsgNotarizeAsset{
|
||||
Creator: "invalid creator address",
|
||||
Cid: cid,
|
||||
},
|
||||
"invalid address",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"machine not found",
|
||||
assettypes.MsgNotarizeAsset{
|
||||
Creator: "plmnt1v5394e8vmfrp4qzdav7xkze0f567w3tsgxf09j",
|
||||
Cid: cid,
|
||||
},
|
||||
"machine not found",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"valid notarization",
|
||||
assettypes.MsgNotarizeAsset{
|
||||
Creator: addr.String(),
|
||||
Cid: cid,
|
||||
},
|
||||
"[]",
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
// Prepare Tx
|
||||
txBytes, err := testutil.PrepareTx(val, &tc.msg, sample.Name)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Broadcast Tx
|
||||
broadcastTxResponse, err := testutil.BroadcastTx(val, txBytes)
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
|
||||
tx, err := testutil.GetRequest(fmt.Sprintf("%s/cosmos/tx/v1beta1/txs/%s", val.APIAddress, broadcastTxResponse.TxResponse.TxHash))
|
||||
s.Require().NoError(err)
|
||||
|
||||
if !tc.expectCheckTxErr {
|
||||
var txRes txtypes.GetTxResponse
|
||||
err = val.ClientCtx.Codec.UnmarshalJSON(tx, &txRes)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Contains(txRes.TxResponse.RawLog, tc.rawLog)
|
||||
} else {
|
||||
s.Require().Contains(broadcastTxResponse.TxResponse.RawLog, tc.rawLog)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,29 +1,19 @@
|
||||
package asset
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/planetmint/planetmint-go/lib"
|
||||
"github.com/planetmint/planetmint-go/testutil/network"
|
||||
"github.com/planetmint/planetmint-go/testutil/sample"
|
||||
|
||||
clitestutil "github.com/planetmint/planetmint-go/testutil/cli"
|
||||
e2etestutil "github.com/planetmint/planetmint-go/testutil/e2e"
|
||||
assetcli "github.com/planetmint/planetmint-go/x/asset/client/cli"
|
||||
machinecli "github.com/planetmint/planetmint-go/x/machine/client/cli"
|
||||
assettypes "github.com/planetmint/planetmint-go/x/asset/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/hd"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
bank "github.com/cosmos/cosmos-sdk/x/bank/client/cli"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
var (
|
||||
pubKey string
|
||||
prvKey string
|
||||
)
|
||||
|
||||
// E2ETestSuite struct definition of asset suite
|
||||
type E2ETestSuite struct {
|
||||
suite.Suite
|
||||
@ -39,84 +29,16 @@ func NewE2ETestSuite(cfg network.Config) *E2ETestSuite {
|
||||
|
||||
// SetupSuite initializes asset E2ETestSuite
|
||||
func (s *E2ETestSuite) SetupSuite() {
|
||||
s.T().Log("setting up e2e test suite")
|
||||
s.T().Log("setting up e2e asset test suite")
|
||||
|
||||
s.network = network.New(s.T())
|
||||
val := s.network.Validators[0]
|
||||
|
||||
kb := val.ClientCtx.Keyring
|
||||
account, err := kb.NewAccount(sample.Name, sample.Mnemonic, keyring.DefaultBIP39Passphrase, sample.DefaultDerivationPath, hd.Secp256k1)
|
||||
s.network = network.Load(s.T(), s.cfg)
|
||||
err := e2etestutil.AttestMachine(s.network, sample.Name, sample.Mnemonic, 0, sample.FeeDenom)
|
||||
s.Require().NoError(err)
|
||||
|
||||
addr, _ := account.GetAddress()
|
||||
|
||||
// sending funds to machine to initialize account on chain
|
||||
args := []string{
|
||||
val.Moniker,
|
||||
addr.String(),
|
||||
sample.Amount,
|
||||
"--yes",
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, sample.Fees),
|
||||
}
|
||||
|
||||
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, bank.NewSendTxCmd(), args)
|
||||
s.Require().NoError(err)
|
||||
|
||||
txResponse, err := clitestutil.GetTxResponseFromOut(out)
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
rawLog, err := clitestutil.GetRawLogFromTxResponse(val, txResponse)
|
||||
s.Require().NoError(err)
|
||||
|
||||
assert.Contains(s.T(), rawLog, "cosmos.bank.v1beta1.MsgSend")
|
||||
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
|
||||
prvKey, pubKey = sample.KeyPair()
|
||||
|
||||
ta := sample.TrustAnchor(pubKey)
|
||||
taJSON, err := json.Marshal(&ta)
|
||||
s.Require().NoError(err)
|
||||
args = []string{
|
||||
fmt.Sprintf("--%s=%s", flags.FlagChainID, s.network.Config.ChainID),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, addr.String()),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, sample.Fees),
|
||||
"--yes",
|
||||
string(taJSON),
|
||||
}
|
||||
_, err = clitestutil.ExecTestCLICmd(val.ClientCtx, machinecli.CmdRegisterTrustAnchor(), args)
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
|
||||
machine := sample.Machine(sample.Name, pubKey, prvKey, addr.String())
|
||||
machineJSON, err := json.Marshal(&machine)
|
||||
s.Require().NoError(err)
|
||||
|
||||
args = []string{
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, sample.Name),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, sample.Fees),
|
||||
"--yes",
|
||||
string(machineJSON),
|
||||
}
|
||||
|
||||
out, err = clitestutil.ExecTestCLICmd(val.ClientCtx, machinecli.CmdAttestMachine(), args)
|
||||
s.Require().NoError(err)
|
||||
|
||||
txResponse, err = clitestutil.GetTxResponseFromOut(out)
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
rawLog, err = clitestutil.GetRawLogFromTxResponse(val, txResponse)
|
||||
s.Require().NoError(err)
|
||||
|
||||
assert.Contains(s.T(), rawLog, "planetmintgo.machine.MsgAttestMachine")
|
||||
}
|
||||
|
||||
// TearDownSuite clean up after testing
|
||||
func (s *E2ETestSuite) TearDownSuite() {
|
||||
s.T().Log("tearing down e2e test suite")
|
||||
s.T().Log("tearing down e2e asset test suite")
|
||||
}
|
||||
|
||||
// TestNotarizeAsset notarizes asset over cli
|
||||
@ -126,40 +48,46 @@ func (s *E2ETestSuite) TestNotarizeAsset() {
|
||||
s.Require().NoError(err)
|
||||
|
||||
addr, _ := k.GetAddress()
|
||||
cid := sample.Asset()
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
args []string
|
||||
msg *assettypes.MsgNotarizeAsset
|
||||
rawLog string
|
||||
expectCheckTxErr bool
|
||||
}{
|
||||
{
|
||||
"valid notarization",
|
||||
[]string{
|
||||
cid,
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, addr.String()),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, sample.Fees),
|
||||
"--yes",
|
||||
},
|
||||
assettypes.NewMsgNotarizeAsset(addr.String(), sample.Asset()),
|
||||
"[]",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"machine not found",
|
||||
assettypes.NewMsgNotarizeAsset("plmnt1v5394e8vmfrp4qzdav7xkze0f567w3tsgxf09j", sample.Asset()),
|
||||
"error during CheckTx or ReCheckTx: machine not found",
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, assetcli.CmdNotarizeAsset(), tc.args)
|
||||
s.Require().NoError(err)
|
||||
out, err := e2etestutil.BuildSignBroadcastTx(s.T(), addr, tc.msg)
|
||||
if tc.expectCheckTxErr {
|
||||
s.Require().Error(err)
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
|
||||
txResponse, err := clitestutil.GetTxResponseFromOut(out)
|
||||
txResponse, err := lib.GetTxResponseFromOut(out)
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
rawLog, err := clitestutil.GetRawLogFromTxResponse(val, txResponse)
|
||||
|
||||
if !tc.expectCheckTxErr {
|
||||
assert.Equal(s.T(), int(0), int(txResponse.Code))
|
||||
args := []string{sample.Asset()}
|
||||
asset, err := clitestutil.ExecTestCLICmd(val.ClientCtx, assetcli.GetCmdByCID(), args)
|
||||
s.Require().NoError(err)
|
||||
assert.Contains(s.T(), rawLog, tc.rawLog)
|
||||
assert.Contains(s.T(), asset.String(), sample.Asset())
|
||||
} else {
|
||||
assert.Contains(s.T(), txResponse.RawLog, tc.rawLog)
|
||||
}
|
||||
|
17
tests/e2e/dao/basic/cli_test.go
Normal file
17
tests/e2e/dao/basic/cli_test.go
Normal file
@ -0,0 +1,17 @@
|
||||
package basic
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/planetmint/planetmint-go/testutil/network"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
func TestE2EDaoTestSuite(t *testing.T) {
|
||||
time.Sleep(2 * time.Second)
|
||||
cfg := network.LoaderDefaultConfig()
|
||||
cfg.NumValidators = 3
|
||||
suite.Run(t, NewE2ETestSuite(cfg))
|
||||
}
|
212
tests/e2e/dao/basic/suite.go
Normal file
212
tests/e2e/dao/basic/suite.go
Normal file
@ -0,0 +1,212 @@
|
||||
package basic
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
bank "github.com/cosmos/cosmos-sdk/x/bank/client/cli"
|
||||
"github.com/planetmint/planetmint-go/lib"
|
||||
clitestutil "github.com/planetmint/planetmint-go/testutil/cli"
|
||||
e2etestutil "github.com/planetmint/planetmint-go/testutil/e2e"
|
||||
"github.com/planetmint/planetmint-go/testutil/network"
|
||||
"github.com/planetmint/planetmint-go/testutil/sample"
|
||||
daocli "github.com/planetmint/planetmint-go/x/dao/client/cli"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
"github.com/planetmint/planetmint-go/testutil/moduleobject"
|
||||
daotypes "github.com/planetmint/planetmint-go/x/dao/types"
|
||||
)
|
||||
|
||||
// E2ETestSuite struct definition of dao suite
|
||||
type E2ETestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
cfg network.Config
|
||||
network *network.Network
|
||||
reissuanceEpochs int64
|
||||
distributionOffset int64
|
||||
bobAddr sdk.AccAddress
|
||||
aliceAddr sdk.AccAddress
|
||||
}
|
||||
|
||||
// NewE2ETestSuite returns configured dao E2ETestSuite
|
||||
func NewE2ETestSuite(cfg network.Config) *E2ETestSuite {
|
||||
return &E2ETestSuite{cfg: cfg}
|
||||
}
|
||||
|
||||
// SetupSuite initializes dao E2ETestSuite
|
||||
func (s *E2ETestSuite) SetupSuite() {
|
||||
// set epochs: make sure to start after initial height of 7
|
||||
s.reissuanceEpochs = 25
|
||||
s.distributionOffset = 5
|
||||
|
||||
s.T().Log("setting up e2e dao test suite")
|
||||
|
||||
// Setup MintAddress parameter in genesis state
|
||||
// use sample.Mnemonic to make mint address deterministic for test
|
||||
s.cfg.Mnemonics = []string{sample.Mnemonic}
|
||||
valAddr, err := s.createValAccount(s.cfg)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// set accounts for alice and bob in genesis state
|
||||
var authGenState authtypes.GenesisState
|
||||
s.cfg.Codec.MustUnmarshalJSON(s.cfg.GenesisState[authtypes.ModuleName], &authGenState)
|
||||
|
||||
s.bobAddr = sample.Secp256k1AccAddress()
|
||||
s.aliceAddr = sample.Secp256k1AccAddress()
|
||||
|
||||
bob := authtypes.NewBaseAccount(s.bobAddr, nil, 0, 0)
|
||||
alice := authtypes.NewBaseAccount(s.aliceAddr, nil, 0, 0)
|
||||
|
||||
accounts, err := authtypes.PackAccounts(authtypes.GenesisAccounts{bob, alice})
|
||||
s.Require().NoError(err)
|
||||
|
||||
authGenState.Accounts = append(authGenState.Accounts, accounts...)
|
||||
s.cfg.GenesisState[authtypes.ModuleName] = s.cfg.Codec.MustMarshalJSON(&authGenState)
|
||||
|
||||
var daoGenState daotypes.GenesisState
|
||||
s.cfg.Codec.MustUnmarshalJSON(s.cfg.GenesisState[daotypes.ModuleName], &daoGenState)
|
||||
daoGenState.Params.DistributionOffset = s.distributionOffset
|
||||
daoGenState.Params.ReissuanceEpochs = s.reissuanceEpochs
|
||||
daoGenState.Params.MintAddress = valAddr.String()
|
||||
daoGenState.Params.ClaimAddress = valAddr.String()
|
||||
s.cfg.GenesisState[daotypes.ModuleName] = s.cfg.Codec.MustMarshalJSON(&daoGenState)
|
||||
|
||||
bbalances := sdk.NewCoins(
|
||||
sdk.NewCoin(daoGenState.Params.TokenDenom, math.NewInt(10000)),
|
||||
)
|
||||
|
||||
abalances := sdk.NewCoins(
|
||||
sdk.NewCoin(daoGenState.Params.TokenDenom, math.NewInt(10000)),
|
||||
)
|
||||
|
||||
accountBalances := []banktypes.Balance{
|
||||
{Address: s.bobAddr.String(), Coins: bbalances.Sort()},
|
||||
{Address: s.aliceAddr.String(), Coins: abalances.Sort()},
|
||||
}
|
||||
// set the balances in genesis state
|
||||
var bankGenState banktypes.GenesisState
|
||||
s.cfg.Codec.MustUnmarshalJSON(s.cfg.GenesisState[banktypes.ModuleName], &bankGenState)
|
||||
bankGenState.Balances = append(bankGenState.Balances, accountBalances...)
|
||||
s.cfg.GenesisState[banktypes.ModuleName] = s.cfg.Codec.MustMarshalJSON(&bankGenState)
|
||||
|
||||
s.network = network.Load(s.T(), s.cfg)
|
||||
|
||||
// create account for redeem claim test case
|
||||
account, err := e2etestutil.CreateAccount(s.network, sample.Name, sample.Mnemonic)
|
||||
s.Require().NoError(err)
|
||||
err = e2etestutil.FundAccount(s.network, account, sample.FeeDenom)
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
|
||||
// TearDownSuite clean up after testing
|
||||
func (s *E2ETestSuite) TearDownSuite() {
|
||||
s.T().Log("tearing down e2e dao test suite")
|
||||
}
|
||||
|
||||
func (s *E2ETestSuite) TestMintToken() {
|
||||
val := s.network.Validators[0]
|
||||
|
||||
mintRequest := moduleobject.MintRequest(s.aliceAddr.String(), 1000, "hash")
|
||||
msg1 := daotypes.NewMsgMintToken(val.Address.String(), &mintRequest)
|
||||
out, err := e2etestutil.BuildSignBroadcastTx(s.T(), val.Address, msg1)
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
rawLog, err := clitestutil.GetRawLogFromTxOut(val, out)
|
||||
s.Require().NoError(err)
|
||||
|
||||
assert.Contains(s.T(), rawLog, "planetmintgo.dao.MsgMintToken")
|
||||
|
||||
// assert that alice has actually received the minted tokens 10000 (initial supply) + 1000 (minted) = 11000 (total)
|
||||
output, err := clitestutil.ExecTestCLICmd(val.ClientCtx, bank.GetBalancesCmd(), []string{
|
||||
s.aliceAddr.String(),
|
||||
})
|
||||
out, ok := output.(*bytes.Buffer)
|
||||
if !ok {
|
||||
err = lib.ErrTypeAssertionFailed
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
assert.Contains(s.T(), out.String(), "plmnt")
|
||||
assert.Contains(s.T(), out.String(), "11000")
|
||||
s.Require().NoError(err)
|
||||
|
||||
// send mint token request from non mint address
|
||||
k, err := val.ClientCtx.Keyring.Key(sample.Name)
|
||||
s.Require().NoError(err)
|
||||
addr, _ := k.GetAddress()
|
||||
|
||||
msg1 = daotypes.NewMsgMintToken(addr.String(), &mintRequest)
|
||||
out, err = lib.BroadcastTxWithFileLock(addr, msg1)
|
||||
s.Require().NoError(err)
|
||||
|
||||
txResponse, err := lib.GetTxResponseFromOut(out)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(int(2), int(txResponse.Code))
|
||||
}
|
||||
|
||||
func (s *E2ETestSuite) createValAccount(cfg network.Config) (address sdk.AccAddress, err error) {
|
||||
buf := bufio.NewReader(os.Stdin)
|
||||
|
||||
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, s.T().TempDir(), buf, cfg.Codec, cfg.KeyringOptions...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
keyringAlgos, _ := kb.SupportedAlgorithms()
|
||||
algo, err := keyring.NewSigningAlgoFromString(cfg.SigningAlgo, keyringAlgos)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mnemonic := cfg.Mnemonics[0]
|
||||
|
||||
record, err := kb.NewAccount("node0", mnemonic, keyring.DefaultBIP39Passphrase, sdk.GetConfig().GetFullBIP44Path(), algo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
addr, err := record.GetAddress()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return addr, nil
|
||||
}
|
||||
|
||||
func (s *E2ETestSuite) TestReissuance() {
|
||||
val := s.network.Validators[0]
|
||||
|
||||
var err error
|
||||
latestHeight, err := s.network.LatestHeight()
|
||||
s.Require().NoError(err)
|
||||
|
||||
var wait int64
|
||||
for {
|
||||
latestHeight, err = s.network.WaitForHeight(latestHeight + 1)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// wait + for sending the reissuance result, i.e.:
|
||||
// 0: block 25: initializing RDDL reissuance broadcast tx succeeded
|
||||
// 1: block 26: sending the reissuance result broadcast tx succeeded
|
||||
// 2: block 27: confirmation
|
||||
wait = 2
|
||||
if latestHeight%s.reissuanceEpochs == wait {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// - because we waited on the reissuance result, see above
|
||||
intValue := strconv.FormatInt(latestHeight-wait, 10)
|
||||
_, err = clitestutil.ExecTestCLICmd(val.ClientCtx, daocli.GetCmdReissuance(), []string{intValue})
|
||||
s.Require().NoError(err)
|
||||
}
|
103
tests/e2e/dao/distribution/asset_distribution_suite.go
Normal file
103
tests/e2e/dao/distribution/asset_distribution_suite.go
Normal file
@ -0,0 +1,103 @@
|
||||
package distribution
|
||||
|
||||
import (
|
||||
"math"
|
||||
"strconv"
|
||||
|
||||
clitestutil "github.com/planetmint/planetmint-go/testutil/cli"
|
||||
"github.com/planetmint/planetmint-go/testutil/network"
|
||||
daocli "github.com/planetmint/planetmint-go/x/dao/client/cli"
|
||||
daotypes "github.com/planetmint/planetmint-go/x/dao/types"
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
type AssetDistributionE2ETestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
cfg network.Config
|
||||
network *network.Network
|
||||
reissaunceEpochs int64
|
||||
distributionOffset int64
|
||||
}
|
||||
|
||||
func NewAssetDistributionE2ETestSuite(cfg network.Config) *AssetDistributionE2ETestSuite {
|
||||
return &AssetDistributionE2ETestSuite{cfg: cfg}
|
||||
}
|
||||
|
||||
func (s *AssetDistributionE2ETestSuite) SetupSuite() {
|
||||
s.T().Log("setting up e2e dao distribution test suite")
|
||||
|
||||
// set epochs: make sure to start after initial height of 7
|
||||
s.distributionOffset = 5
|
||||
s.reissaunceEpochs = 10
|
||||
|
||||
var daoGenState daotypes.GenesisState
|
||||
s.cfg.Codec.MustUnmarshalJSON(s.cfg.GenesisState[daotypes.ModuleName], &daoGenState)
|
||||
daoGenState.Params.DistributionOffset = s.distributionOffset
|
||||
daoGenState.Params.ReissuanceEpochs = s.reissaunceEpochs
|
||||
s.cfg.GenesisState[daotypes.ModuleName] = s.cfg.Codec.MustMarshalJSON(&daoGenState)
|
||||
|
||||
s.network = network.Load(s.T(), s.cfg)
|
||||
}
|
||||
|
||||
func (s *AssetDistributionE2ETestSuite) TearDownSuite() {
|
||||
s.T().Log("tearing down e2e dao distribution test suites")
|
||||
}
|
||||
|
||||
func (s *AssetDistributionE2ETestSuite) TestAssetDistribution() {
|
||||
val := s.network.Validators[0]
|
||||
|
||||
latestHeight, err := s.network.LatestHeight()
|
||||
s.Require().NoError(err)
|
||||
|
||||
// wait so that we see exactly on reissuance/distribution round, e.g.
|
||||
// wait = ceil((10 - 5) / 2) = ceil(2.5) = 3
|
||||
wait := int64(math.Ceil((float64(s.reissaunceEpochs - s.distributionOffset)) / 2.0))
|
||||
height := s.reissaunceEpochs + s.distributionOffset + wait
|
||||
for {
|
||||
latestHeight, err = s.network.WaitForHeight(latestHeight + 1)
|
||||
s.Require().NoError(err)
|
||||
|
||||
if latestHeight == height {
|
||||
break
|
||||
}
|
||||
}
|
||||
errmsg := "rpc error: code = NotFound desc = distribution not found: key not found"
|
||||
testCases := []struct {
|
||||
name string
|
||||
requestHeight int64
|
||||
expectedErr string
|
||||
}{
|
||||
{
|
||||
"request height too low",
|
||||
s.distributionOffset,
|
||||
errmsg,
|
||||
},
|
||||
{
|
||||
"wrong request height",
|
||||
height,
|
||||
errmsg,
|
||||
},
|
||||
{
|
||||
"request height too high",
|
||||
2*s.reissaunceEpochs + s.distributionOffset,
|
||||
errmsg,
|
||||
},
|
||||
{
|
||||
"valid distribution request",
|
||||
s.reissaunceEpochs + s.distributionOffset,
|
||||
"",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
_, err = clitestutil.ExecTestCLICmd(val.ClientCtx, daocli.GetCmdDistribution(), []string{
|
||||
strconv.FormatInt(tc.requestHeight, 10),
|
||||
})
|
||||
if tc.expectedErr == "" {
|
||||
s.Require().NoError(err)
|
||||
} else {
|
||||
s.Require().Error(err)
|
||||
}
|
||||
}
|
||||
}
|
17
tests/e2e/dao/distribution/cli_test.go
Normal file
17
tests/e2e/dao/distribution/cli_test.go
Normal file
@ -0,0 +1,17 @@
|
||||
package distribution
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/planetmint/planetmint-go/testutil/network"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
func TestAssetDistributionE2EDaoTestSuite(t *testing.T) {
|
||||
time.Sleep(2 * time.Second)
|
||||
cfg := network.LoaderDefaultConfig()
|
||||
cfg.NumValidators = 3
|
||||
suite.Run(t, NewAssetDistributionE2ETestSuite(cfg))
|
||||
}
|
17
tests/e2e/dao/gas/cli_test.go
Normal file
17
tests/e2e/dao/gas/cli_test.go
Normal file
@ -0,0 +1,17 @@
|
||||
package gas
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/planetmint/planetmint-go/testutil/network"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
func TestConsumptionE2EDaoTestSuite(t *testing.T) {
|
||||
time.Sleep(2 * time.Second)
|
||||
cfg := network.LoaderDefaultConfig()
|
||||
cfg.NumValidators = 3
|
||||
suite.Run(t, NewConsumptionE2ETestSuite(cfg))
|
||||
}
|
172
tests/e2e/dao/gas/gas_consumption_suite.go
Normal file
172
tests/e2e/dao/gas/gas_consumption_suite.go
Normal file
@ -0,0 +1,172 @@
|
||||
package gas
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
"github.com/planetmint/planetmint-go/lib"
|
||||
clitestutil "github.com/planetmint/planetmint-go/testutil/cli"
|
||||
e2etestutil "github.com/planetmint/planetmint-go/testutil/e2e"
|
||||
"github.com/planetmint/planetmint-go/testutil/moduleobject"
|
||||
"github.com/planetmint/planetmint-go/testutil/network"
|
||||
"github.com/planetmint/planetmint-go/testutil/sample"
|
||||
daotypes "github.com/planetmint/planetmint-go/x/dao/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
type ConsumptionE2ETestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
cfg network.Config
|
||||
network *network.Network
|
||||
minterAddr sdk.AccAddress
|
||||
feeDenom string
|
||||
}
|
||||
|
||||
func NewConsumptionE2ETestSuite(cfg network.Config) *ConsumptionE2ETestSuite {
|
||||
return &ConsumptionE2ETestSuite{cfg: cfg}
|
||||
}
|
||||
|
||||
func (s *ConsumptionE2ETestSuite) createValAccount(cfg network.Config) (address sdk.AccAddress, err error) {
|
||||
buf := bufio.NewReader(os.Stdin)
|
||||
|
||||
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, s.T().TempDir(), buf, cfg.Codec, cfg.KeyringOptions...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
keyringAlgos, _ := kb.SupportedAlgorithms()
|
||||
algo, err := keyring.NewSigningAlgoFromString(cfg.SigningAlgo, keyringAlgos)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mnemonic := cfg.Mnemonics[0]
|
||||
|
||||
record, err := kb.NewAccount("node0", mnemonic, keyring.DefaultBIP39Passphrase, sdk.GetConfig().GetFullBIP44Path(), algo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
addr, err := record.GetAddress()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return addr, nil
|
||||
}
|
||||
|
||||
func (s *ConsumptionE2ETestSuite) SetupSuite() {
|
||||
s.T().Log("setting up e2e dao gas consumption test suite")
|
||||
|
||||
s.feeDenom = sample.FeeDenom
|
||||
s.cfg.Mnemonics = []string{sample.Mnemonic}
|
||||
addr, err := s.createValAccount(s.cfg)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// set accounts for alice and bob in genesis state
|
||||
var authGenState authtypes.GenesisState
|
||||
s.cfg.Codec.MustUnmarshalJSON(s.cfg.GenesisState[authtypes.ModuleName], &authGenState)
|
||||
s.minterAddr = addr
|
||||
minter := authtypes.NewBaseAccount(s.minterAddr, nil, 0, 0)
|
||||
accounts, err := authtypes.PackAccounts(authtypes.GenesisAccounts{minter})
|
||||
s.Require().NoError(err)
|
||||
authGenState.Accounts = append(authGenState.Accounts, accounts...)
|
||||
s.cfg.GenesisState[authtypes.ModuleName] = s.cfg.Codec.MustMarshalJSON(&authGenState)
|
||||
|
||||
var daoGenState daotypes.GenesisState
|
||||
s.cfg.Codec.MustUnmarshalJSON(s.cfg.GenesisState[daotypes.ModuleName], &daoGenState)
|
||||
daoGenState.Params.MintAddress = s.minterAddr.String()
|
||||
s.cfg.GenesisState[daotypes.ModuleName] = s.cfg.Codec.MustMarshalJSON(&daoGenState)
|
||||
|
||||
s.network = network.Load(s.T(), s.cfg)
|
||||
account, err := e2etestutil.CreateAccount(s.network, sample.Name, sample.Mnemonic)
|
||||
s.Require().NoError(err)
|
||||
err = e2etestutil.FundAccount(s.network, account, s.feeDenom)
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
|
||||
func (s *ConsumptionE2ETestSuite) TearDownSuite() {
|
||||
s.T().Log("tearing down e2e dao gas consumption test suites")
|
||||
}
|
||||
|
||||
func (s *ConsumptionE2ETestSuite) TestValidatorConsumption() {
|
||||
val := s.network.Validators[0]
|
||||
|
||||
k, err := val.ClientCtx.Keyring.Key(sample.Name)
|
||||
s.Require().NoError(err)
|
||||
addr, _ := k.GetAddress()
|
||||
|
||||
// send huge tx but as val and with no gas kv costs
|
||||
msgs := s.createMsgs(val.Address, addr, 10)
|
||||
|
||||
out, err := lib.BroadcastTxWithFileLock(val.Address, msgs...)
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
|
||||
_, err = clitestutil.GetRawLogFromTxOut(val, out)
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
|
||||
func (s *ConsumptionE2ETestSuite) TestNonValidatorConsumptionOverflow() {
|
||||
val := s.network.Validators[0]
|
||||
|
||||
k, err := val.ClientCtx.Keyring.Key(sample.Name)
|
||||
s.Require().NoError(err)
|
||||
|
||||
err = e2etestutil.FundAccount(s.network, k, s.feeDenom)
|
||||
s.Require().NoError(err)
|
||||
|
||||
addr, _ := k.GetAddress()
|
||||
|
||||
// exceed gas limit with too many msgs as non validator
|
||||
msgs := s.createMsgs(addr, val.Address, 10)
|
||||
|
||||
out, err := lib.BroadcastTxWithFileLock(addr, msgs...)
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
|
||||
_, err = clitestutil.GetRawLogFromTxOut(val, out)
|
||||
s.Require().Error(err)
|
||||
assert.Contains(s.T(), err.Error(), "out of gas")
|
||||
}
|
||||
|
||||
func (s *ConsumptionE2ETestSuite) createMsgs(from sdk.AccAddress, to sdk.AccAddress, n int) (msgs []sdk.Msg) {
|
||||
coins := sdk.NewCoins(sdk.NewInt64Coin(s.feeDenom, 10))
|
||||
for i := 0; i < n; i++ {
|
||||
msg := banktypes.NewMsgSend(from, to, coins)
|
||||
msgs = append(msgs, msg)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *ConsumptionE2ETestSuite) TestNetworkBasedTxGasLimit() {
|
||||
var gasAmountAboveGlobalGasLimit uint64 = 200000000
|
||||
libConfig := lib.GetConfig()
|
||||
libConfig.SetTxGas(gasAmountAboveGlobalGasLimit)
|
||||
|
||||
var msgs []sdk.Msg
|
||||
|
||||
for i := 0; i < 1000; i++ {
|
||||
mintRequest := moduleobject.MintRequest(s.minterAddr.String(), 1, "hash"+strconv.Itoa(i))
|
||||
msg := daotypes.NewMsgMintToken(s.minterAddr.String(), &mintRequest)
|
||||
msgs = append(msgs, msg)
|
||||
}
|
||||
|
||||
_, err := e2etestutil.BuildSignBroadcastTx(s.T(), s.minterAddr, msgs...)
|
||||
s.Require().Error(err)
|
||||
s.Assert().Contains(err.Error(), "out of gas in location: txSize; gasWanted: "+strconv.FormatUint(gasAmountAboveGlobalGasLimit, 10)+", gasUsed:")
|
||||
s.Assert().Contains(err.Error(), " out of gas")
|
||||
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
}
|
17
tests/e2e/dao/msgs/cli_test.go
Normal file
17
tests/e2e/dao/msgs/cli_test.go
Normal file
@ -0,0 +1,17 @@
|
||||
package msgs
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/planetmint/planetmint-go/testutil/network"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
func TestRestrictedMsgsE2EDaoTestSuite(t *testing.T) {
|
||||
time.Sleep(2 * time.Second)
|
||||
cfg := network.LoaderDefaultConfig()
|
||||
cfg.NumValidators = 3
|
||||
suite.Run(t, NewRestrictedMsgsE2ESuite(cfg))
|
||||
}
|
125
tests/e2e/dao/msgs/restricted_msgs_suite.go
Normal file
125
tests/e2e/dao/msgs/restricted_msgs_suite.go
Normal file
@ -0,0 +1,125 @@
|
||||
package msgs
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/planetmint/planetmint-go/lib"
|
||||
e2etestutil "github.com/planetmint/planetmint-go/testutil/e2e"
|
||||
"github.com/planetmint/planetmint-go/testutil/network"
|
||||
"github.com/planetmint/planetmint-go/testutil/sample"
|
||||
daotypes "github.com/planetmint/planetmint-go/x/dao/types"
|
||||
machinetypes "github.com/planetmint/planetmint-go/x/machine/types"
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
var msgs = []sdk.Msg{
|
||||
&daotypes.MsgInitPop{},
|
||||
&daotypes.MsgDistributionRequest{},
|
||||
&daotypes.MsgDistributionResult{},
|
||||
&daotypes.MsgReissueRDDLProposal{},
|
||||
&daotypes.MsgReissueRDDLResult{},
|
||||
&daotypes.MsgUpdateRedeemClaim{},
|
||||
&machinetypes.MsgRegisterTrustAnchor{},
|
||||
&machinetypes.MsgNotarizeLiquidAsset{},
|
||||
}
|
||||
|
||||
type RestrictedMsgsE2ESuite struct {
|
||||
suite.Suite
|
||||
|
||||
cfg network.Config
|
||||
network *network.Network
|
||||
}
|
||||
|
||||
func NewRestrictedMsgsE2ESuite(cfg network.Config) *RestrictedMsgsE2ESuite {
|
||||
return &RestrictedMsgsE2ESuite{cfg: cfg}
|
||||
}
|
||||
|
||||
func (s *RestrictedMsgsE2ESuite) SetupSuite() {
|
||||
s.T().Log("setting up e2e dao restricted msg test suite")
|
||||
|
||||
s.network = network.Load(s.T(), s.cfg)
|
||||
account, err := e2etestutil.CreateAccount(s.network, sample.Name, sample.Mnemonic)
|
||||
s.Require().NoError(err)
|
||||
err = e2etestutil.FundAccount(s.network, account, sample.FeeDenom)
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
|
||||
func (s *RestrictedMsgsE2ESuite) TearDownSuite() {
|
||||
s.T().Log("tearing down e2e dao restricted msg test suite")
|
||||
}
|
||||
|
||||
func (s *RestrictedMsgsE2ESuite) TestRestrictedMsgsValidator() {
|
||||
val := s.network.Validators[0]
|
||||
|
||||
msg := daotypes.NewMsgInitPop(val.Address.String(), val.Address.String(), val.Address.String(), val.Address.String(), 0)
|
||||
out, err := lib.BroadcastTxWithFileLock(val.Address, msg)
|
||||
s.Require().NoError(err)
|
||||
|
||||
txResponse, err := lib.GetTxResponseFromOut(out)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(int(0), int(txResponse.Code))
|
||||
}
|
||||
|
||||
func (s *RestrictedMsgsE2ESuite) TestRestrictedMsgsNonValidator() {
|
||||
val := s.network.Validators[0]
|
||||
|
||||
k, err := val.ClientCtx.Keyring.Key(sample.Name)
|
||||
s.Require().NoError(err)
|
||||
addr, _ := k.GetAddress()
|
||||
|
||||
for _, msg := range msgs {
|
||||
msg = setCreator(msg, addr.String())
|
||||
out, err := lib.BroadcastTxWithFileLock(addr, msg)
|
||||
s.Require().NoError(err)
|
||||
|
||||
txResponse, err := lib.GetTxResponseFromOut(out)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(int(18), int(txResponse.Code))
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
}
|
||||
}
|
||||
|
||||
func setCreator(msg sdk.Msg, creator string) sdk.Msg {
|
||||
switch sdk.MsgTypeURL(msg) {
|
||||
case "/planetmintgo.dao.MsgInitPop":
|
||||
msg, ok := msg.(*daotypes.MsgInitPop)
|
||||
if ok {
|
||||
msg.Creator = creator
|
||||
}
|
||||
case "/planetmintgo.dao.MsgDistributionRequest":
|
||||
msg, ok := msg.(*daotypes.MsgDistributionRequest)
|
||||
if ok {
|
||||
msg.Creator = creator
|
||||
}
|
||||
case "/planetmintgo.dao.MsgDistributionResult":
|
||||
msg, ok := msg.(*daotypes.MsgDistributionResult)
|
||||
if ok {
|
||||
msg.Creator = creator
|
||||
}
|
||||
case "/planetmintgo.dao.MsgReissueRDDLProposal":
|
||||
msg, ok := msg.(*daotypes.MsgReissueRDDLProposal)
|
||||
if ok {
|
||||
msg.Creator = creator
|
||||
}
|
||||
case "/planetmintgo.dao.MsgReissueRDDLResult":
|
||||
msg, ok := msg.(*daotypes.MsgReissueRDDLResult)
|
||||
if ok {
|
||||
msg.Creator = creator
|
||||
}
|
||||
case "/planetmintgo.dao.MsgUpdateRedeemClaim":
|
||||
msg, ok := msg.(*daotypes.MsgUpdateRedeemClaim)
|
||||
if ok {
|
||||
msg.Creator = creator
|
||||
}
|
||||
case "/planetmintgo.machine.MsgNotarizeLiquidAsset":
|
||||
msg, ok := msg.(*machinetypes.MsgNotarizeLiquidAsset)
|
||||
if ok {
|
||||
msg.Creator = creator
|
||||
}
|
||||
case "/planetmintgo.machine.MsgRegisterTrustAnchor":
|
||||
msg, ok := msg.(*machinetypes.MsgRegisterTrustAnchor)
|
||||
if ok {
|
||||
msg.Creator = creator
|
||||
}
|
||||
}
|
||||
return msg
|
||||
}
|
17
tests/e2e/dao/pop/cli_test.go
Normal file
17
tests/e2e/dao/pop/cli_test.go
Normal file
@ -0,0 +1,17 @@
|
||||
package pop
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/planetmint/planetmint-go/testutil/network"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
func TestPopE2EDaoTestSuite(t *testing.T) {
|
||||
time.Sleep(2 * time.Second)
|
||||
cfg := network.LoaderDefaultConfig()
|
||||
cfg.NumValidators = 3
|
||||
suite.Run(t, NewSelectionE2ETestSuite(cfg))
|
||||
}
|
404
tests/e2e/dao/pop/selection_suite.go
Normal file
404
tests/e2e/dao/pop/selection_suite.go
Normal file
@ -0,0 +1,404 @@
|
||||
package pop
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"log"
|
||||
"math"
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
sdkmath "cosmossdk.io/math"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
bank "github.com/cosmos/cosmos-sdk/x/bank/client/cli"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
"github.com/planetmint/planetmint-go/lib"
|
||||
"github.com/planetmint/planetmint-go/monitor"
|
||||
"github.com/planetmint/planetmint-go/testutil"
|
||||
clitestutil "github.com/planetmint/planetmint-go/testutil/cli"
|
||||
e2etestutil "github.com/planetmint/planetmint-go/testutil/e2e"
|
||||
"github.com/planetmint/planetmint-go/testutil/network"
|
||||
"github.com/planetmint/planetmint-go/testutil/sample"
|
||||
"github.com/planetmint/planetmint-go/util/mocks"
|
||||
daocli "github.com/planetmint/planetmint-go/x/dao/client/cli"
|
||||
daotypes "github.com/planetmint/planetmint-go/x/dao/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
var machines = []struct {
|
||||
name string
|
||||
mnemonic string
|
||||
address string
|
||||
}{
|
||||
{
|
||||
name: "R2D2",
|
||||
mnemonic: "number judge garbage lock village slush business upset suspect green wrestle puzzle foil tragic drum stereo ticket teach upper bone inject monkey deny portion",
|
||||
address: "plmnt1kp93kns6hs2066d8qw0uz84fw3vlthewt2ck6p",
|
||||
},
|
||||
{
|
||||
name: "C3PO",
|
||||
mnemonic: "letter plate husband impulse grid lake panel seminar try powder virtual run spice siege mutual enhance ripple country two boring have convince symptom fuel",
|
||||
address: "plmnt15wrx9eqegjtlvvx80huau7rkn3f44rdj969xrx",
|
||||
},
|
||||
}
|
||||
|
||||
type SelectionE2ETestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
cfg network.Config
|
||||
network *network.Network
|
||||
popEpochs int64
|
||||
reissuanceEpochs int64
|
||||
distributionOffset int64
|
||||
claimDenom string
|
||||
feeDenom string
|
||||
errormsg string
|
||||
}
|
||||
|
||||
func NewSelectionE2ETestSuite(cfg network.Config) *SelectionE2ETestSuite {
|
||||
testsuite := &SelectionE2ETestSuite{cfg: cfg}
|
||||
testsuite.errormsg = "--%s=%s"
|
||||
return testsuite
|
||||
}
|
||||
|
||||
func (s *SelectionE2ETestSuite) SetupSuite() {
|
||||
s.T().Log("setting up e2e dao pop selection test suite")
|
||||
|
||||
s.popEpochs = 10
|
||||
s.reissuanceEpochs = 60
|
||||
s.distributionOffset = 2
|
||||
s.claimDenom = "crddl"
|
||||
s.feeDenom = sample.FeeDenom
|
||||
s.cfg.Mnemonics = []string{sample.Mnemonic}
|
||||
valAddr, err := s.createValAccount(s.cfg)
|
||||
s.Require().NoError(err)
|
||||
|
||||
var daoGenState daotypes.GenesisState
|
||||
s.cfg.Codec.MustUnmarshalJSON(s.cfg.GenesisState[daotypes.ModuleName], &daoGenState)
|
||||
daoGenState.Params.PopEpochs = s.popEpochs
|
||||
daoGenState.Params.ReissuanceEpochs = s.reissuanceEpochs
|
||||
daoGenState.Params.DistributionOffset = s.distributionOffset
|
||||
daoGenState.Params.MqttResponseTimeout = 200
|
||||
daoGenState.Params.ClaimAddress = valAddr.String()
|
||||
s.cfg.GenesisState[daotypes.ModuleName] = s.cfg.Codec.MustMarshalJSON(&daoGenState)
|
||||
|
||||
// setting up stagedClaims that are not part of PoP issuance (i.e.: past unresolved claims)
|
||||
machineBalances := []banktypes.Balance{
|
||||
{Address: machines[0].address, Coins: sdk.NewCoins(sdk.NewCoin(daoGenState.Params.StagedDenom, sdkmath.NewInt(10000)))},
|
||||
{Address: machines[1].address, Coins: sdk.NewCoins(sdk.NewCoin(daoGenState.Params.StagedDenom, sdkmath.NewInt(10000)))},
|
||||
}
|
||||
|
||||
var bankGenState banktypes.GenesisState
|
||||
s.cfg.Codec.MustUnmarshalJSON(s.cfg.GenesisState[banktypes.ModuleName], &bankGenState)
|
||||
bankGenState.Balances = append(bankGenState.Balances, machineBalances...)
|
||||
s.cfg.GenesisState[banktypes.ModuleName] = s.cfg.Codec.MustMarshalJSON(&bankGenState)
|
||||
|
||||
s.network = network.Load(s.T(), s.cfg)
|
||||
}
|
||||
|
||||
// TearDownSuite clean up after testing
|
||||
func (s *SelectionE2ETestSuite) TearDownSuite() {
|
||||
s.T().Log("tearing down e2e dao pop selection test suite")
|
||||
}
|
||||
|
||||
func (s *SelectionE2ETestSuite) perpareLocalTest() testutil.BufferWriter {
|
||||
val := s.network.Validators[0]
|
||||
|
||||
latestHeight, err := s.network.LatestHeight()
|
||||
s.Require().NoError(err)
|
||||
|
||||
wait := int64(math.Ceil(float64(s.popEpochs) / 2.0))
|
||||
for {
|
||||
latestHeight, err = s.network.WaitForHeight(latestHeight + 1)
|
||||
s.Require().NoError(err)
|
||||
|
||||
if latestHeight%s.popEpochs == wait {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, daocli.GetCmdChallenge(), []string{
|
||||
strconv.FormatInt(latestHeight-wait, 10),
|
||||
})
|
||||
s.Require().NoError(err)
|
||||
return out
|
||||
}
|
||||
|
||||
type yamlChallenge struct {
|
||||
Initiator string `yaml:"initiator"`
|
||||
Challenger string `yaml:"challenger"`
|
||||
Challengee string `yaml:"challengee"`
|
||||
Height string `yaml:"height"`
|
||||
Success bool `yaml:"success"`
|
||||
Finished bool `yaml:"finished"`
|
||||
}
|
||||
|
||||
func (s *SelectionE2ETestSuite) sendPoPResult(storedChallenge []byte, success bool) {
|
||||
val := s.network.Validators[0]
|
||||
var wrapper struct {
|
||||
Challenge yamlChallenge `yaml:"challenge"`
|
||||
}
|
||||
|
||||
err := yaml.Unmarshal(storedChallenge, &wrapper)
|
||||
if err != nil {
|
||||
log.Fatalf("error: %v", err)
|
||||
}
|
||||
tmpChallenge := wrapper.Challenge
|
||||
var challenge daotypes.Challenge
|
||||
challenge.Challengee = tmpChallenge.Challengee
|
||||
challenge.Challenger = tmpChallenge.Challenger
|
||||
challenge.Initiator = tmpChallenge.Initiator
|
||||
challenge.Height, err = strconv.ParseInt(tmpChallenge.Height, 10, 64)
|
||||
s.Require().NoError(err)
|
||||
challenge.Finished = true
|
||||
challenge.Success = success
|
||||
|
||||
machineName := machines[0].name
|
||||
if challenge.Challenger != machines[0].address {
|
||||
machineName = machines[1].name
|
||||
}
|
||||
k, err := val.ClientCtx.Keyring.Key(machineName)
|
||||
s.Require().NoError(err)
|
||||
challengerAccAddress, _ := k.GetAddress()
|
||||
|
||||
msg := daotypes.NewMsgReportPopResult(challengerAccAddress.String(), &challenge)
|
||||
_, err = e2etestutil.BuildSignBroadcastTx(s.T(), challengerAccAddress, msg)
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
|
||||
func (s *SelectionE2ETestSuite) TestPopSelectionNoActors() {
|
||||
out := s.perpareLocalTest()
|
||||
|
||||
assert.NotContains(s.T(), out.String(), machines[0].address)
|
||||
assert.NotContains(s.T(), out.String(), machines[1].address)
|
||||
}
|
||||
|
||||
func (s *SelectionE2ETestSuite) TestPopSelectionOneActors() {
|
||||
err := monitor.AddParticipant(machines[0].address, time.Now().Unix())
|
||||
s.Require().NoError(err)
|
||||
err = e2etestutil.AttestMachine(s.network, machines[0].name, machines[0].mnemonic, 0, s.feeDenom)
|
||||
s.Require().NoError(err)
|
||||
|
||||
out := s.perpareLocalTest()
|
||||
|
||||
assert.NotContains(s.T(), out.String(), machines[0].address)
|
||||
assert.NotContains(s.T(), out.String(), machines[1].address)
|
||||
}
|
||||
|
||||
func (s *SelectionE2ETestSuite) TestPopSelectionTwoActors() {
|
||||
err := monitor.AddParticipant(machines[1].address, time.Now().Unix())
|
||||
s.Require().NoError(err)
|
||||
err = e2etestutil.AttestMachine(s.network, machines[1].name, machines[1].mnemonic, 1, s.feeDenom)
|
||||
s.Require().NoError(err)
|
||||
|
||||
out := s.perpareLocalTest()
|
||||
|
||||
assert.Contains(s.T(), out.String(), machines[0].address)
|
||||
assert.Contains(s.T(), out.String(), machines[1].address)
|
||||
s.sendPoPResult(out.Bytes(), true)
|
||||
}
|
||||
|
||||
func (s *SelectionE2ETestSuite) VerifyTokens(token string) {
|
||||
val := s.network.Validators[0]
|
||||
// check balance for crddl
|
||||
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, bank.GetCmdQueryTotalSupply(), []string{
|
||||
fmt.Sprintf(s.errormsg, bank.FlagDenom, token),
|
||||
})
|
||||
s.Require().NoError(err)
|
||||
assert.Contains(s.T(), out.String(), token)
|
||||
|
||||
// Account for 1 additional unfinished PoP when checking balances after distribution
|
||||
if token == s.claimDenom {
|
||||
assert.Equal(s.T(), "amount: \"18579472050\"\ndenom: "+token+"\n", out.String()) // Total supply 2 * 7990867578 (total supply) + 1 * 1997716894 (challenger) + 6 * 100000000 (validator) + 2 * 10000 (past unresolved claims) = 18579472050
|
||||
} else {
|
||||
assert.Equal(s.T(), "amount: \"18479472050\"\ndenom: "+token+"\n", out.String()) // Total supply 2 * 7990867578 (total supply) + 1 * 1997716894 (challenger) + 5 * 100000000 (validator) + 2 * 10000 (past unresolved claims) = 18479472050
|
||||
}
|
||||
|
||||
out, err = clitestutil.ExecTestCLICmd(val.ClientCtx, bank.GetBalancesCmd(), []string{
|
||||
machines[0].address,
|
||||
fmt.Sprintf(s.errormsg, bank.FlagDenom, token),
|
||||
})
|
||||
s.Require().NoError(err)
|
||||
assert.Contains(s.T(), out.String(), token)
|
||||
assert.Equal(s.T(), "amount: \"5993160682\"\ndenom: "+token+"\n", out.String()) // 3 * 1997716894 + 1 * 10000 = 5993160682
|
||||
|
||||
out, err = clitestutil.ExecTestCLICmd(val.ClientCtx, bank.GetBalancesCmd(), []string{
|
||||
machines[1].address,
|
||||
fmt.Sprintf(s.errormsg, bank.FlagDenom, token),
|
||||
})
|
||||
s.Require().NoError(err)
|
||||
assert.Contains(s.T(), out.String(), token)
|
||||
assert.Equal(s.T(), "amount: \"11986311368\"\ndenom: "+token+"\n", out.String()) // 2 * 5993150684 + 1 * 10000 = 11986311368
|
||||
|
||||
out, err = clitestutil.ExecTestCLICmd(val.ClientCtx, bank.GetBalancesCmd(), []string{
|
||||
val.Address.String(),
|
||||
fmt.Sprintf(s.errormsg, bank.FlagDenom, token),
|
||||
})
|
||||
s.Require().NoError(err)
|
||||
assert.Contains(s.T(), out.String(), token)
|
||||
|
||||
// Account for 1 additional unfinished PoP when checking balances after distribution
|
||||
if token == s.claimDenom {
|
||||
assert.Equal(s.T(), "amount: \"600000000\"\ndenom: "+token+"\n", out.String()) // 6 * 100000000
|
||||
} else {
|
||||
assert.Equal(s.T(), "amount: \"500000000\"\ndenom: "+token+"\n", out.String()) // 5 * 100000000
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SelectionE2ETestSuite) TestTokenDistribution1() {
|
||||
out := s.perpareLocalTest()
|
||||
|
||||
assert.Contains(s.T(), out.String(), machines[0].address)
|
||||
assert.Contains(s.T(), out.String(), machines[1].address)
|
||||
s.sendPoPResult(out.Bytes(), false)
|
||||
|
||||
out = s.perpareLocalTest()
|
||||
|
||||
assert.Contains(s.T(), out.String(), machines[0].address)
|
||||
assert.Contains(s.T(), out.String(), machines[1].address)
|
||||
s.sendPoPResult(out.Bytes(), true)
|
||||
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
|
||||
var daoGenState daotypes.GenesisState
|
||||
s.cfg.Codec.MustUnmarshalJSON(s.cfg.GenesisState[daotypes.ModuleName], &daoGenState)
|
||||
|
||||
s.VerifyTokens(daoGenState.Params.StagedDenom)
|
||||
|
||||
// send Reissuance and DistributionResult implicitly
|
||||
latestHeight, err := s.network.LatestHeight()
|
||||
s.Require().NoError(err)
|
||||
for {
|
||||
latestHeight, err := s.network.WaitForHeight(latestHeight + 1)
|
||||
s.Require().NoError(err)
|
||||
// s.Require().NoError(s.network.WaitForNextBlock())
|
||||
if latestHeight%s.reissuanceEpochs == s.distributionOffset {
|
||||
break
|
||||
}
|
||||
}
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
|
||||
s.VerifyTokens(daoGenState.Params.ClaimDenom)
|
||||
}
|
||||
|
||||
func (s *SelectionE2ETestSuite) TestTokenRedeemClaim() {
|
||||
val := s.network.Validators[0]
|
||||
|
||||
k, err := val.ClientCtx.Keyring.Key(machines[0].name)
|
||||
s.Require().NoError(err)
|
||||
addr, _ := k.GetAddress()
|
||||
|
||||
// Addr sends CreateRedeemClaim => accepted query redeem claim
|
||||
createClaimMsg := daotypes.NewMsgCreateRedeemClaim(addr.String(), "liquidAddress")
|
||||
out, err := lib.BroadcastTxWithFileLock(addr, createClaimMsg)
|
||||
s.Require().NoError(err)
|
||||
|
||||
txResponse, err := lib.GetTxResponseFromOut(out)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(int(0), int(txResponse.Code))
|
||||
|
||||
// WaitForBlock => Validator should implicitly send UpdateRedeemClaim
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
|
||||
// Claim burned on CreateRedeemClaim
|
||||
balanceOut, err := clitestutil.ExecTestCLICmd(val.ClientCtx, bank.GetBalancesCmd(), []string{
|
||||
addr.String(),
|
||||
fmt.Sprintf(s.errormsg, bank.FlagDenom, s.claimDenom),
|
||||
})
|
||||
s.Require().NoError(err)
|
||||
assert.Equal(s.T(), "amount: \"0\"\ndenom: crddl\n", balanceOut.String()) // consumes all claims
|
||||
|
||||
// Addr sends ConfirmRedeemClaim => rejected not claim address
|
||||
confirmMsg := daotypes.NewMsgConfirmRedeemClaim(addr.String(), 0, "liquidAddress")
|
||||
out, err = lib.BroadcastTxWithFileLock(addr, confirmMsg)
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
s.Require().NoError(s.network.WaitForNextBlock()) // added another waiting block to pass CI test cases (they are a bit slower)
|
||||
|
||||
_, err = clitestutil.GetRawLogFromTxOut(val, out)
|
||||
s.Require().ErrorContains(err, "failed to execute message; message index: 0: expected: plmnt19cl05ztgt8ey6v86hjjjn3thfmpu6q2xtveehc; got: plmnt1kp93kns6hs2066d8qw0uz84fw3vlthewt2ck6p: invalid claim address")
|
||||
|
||||
// Validator with Claim Address sends ConfirmRedeemClaim => accepted
|
||||
valConfirmMsg := daotypes.NewMsgConfirmRedeemClaim(val.Address.String(), 0, "liquidAddress")
|
||||
out, err = lib.BroadcastTxWithFileLock(val.Address, valConfirmMsg)
|
||||
s.Require().NoError(err)
|
||||
|
||||
txResponse, err = lib.GetTxResponseFromOut(out)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(int(0), int(txResponse.Code))
|
||||
|
||||
// WaitForBlock before query (2 blocks since 3 validators)
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
|
||||
// QueryRedeemClaim
|
||||
qOut, err := clitestutil.ExecTestCLICmd(val.ClientCtx, daocli.GetCmdShowRedeemClaim(), []string{"liquidAddress", "0"})
|
||||
s.Require().NoError(err)
|
||||
assert.Equal(s.T(), "redeemClaim:\n amount: \"5993160682\"\n beneficiary: liquidAddress\n confirmed: true\n creator: plmnt1kp93kns6hs2066d8qw0uz84fw3vlthewt2ck6p\n id: \"0\"\n liquidTxHash: \"0000000000000000000000000000000000000000000000000000000000000000\"\n", qOut.String())
|
||||
|
||||
qOut, err = clitestutil.ExecTestCLICmd(val.ClientCtx, daocli.GetCmdRedeemClaimByLiquidTxHash(), []string{"0000000000000000000000000000000000000000000000000000000000000000"})
|
||||
s.Require().NoError(err)
|
||||
assert.Equal(s.T(), "redeemClaim:\n amount: \"5993160682\"\n beneficiary: liquidAddress\n confirmed: true\n creator: plmnt1kp93kns6hs2066d8qw0uz84fw3vlthewt2ck6p\n id: \"0\"\n liquidTxHash: \"0000000000000000000000000000000000000000000000000000000000000000\"\n", qOut.String())
|
||||
|
||||
// Make sure "Publish" has been called with PoPInit cmnd
|
||||
calls := mocks.GetCallLog()
|
||||
|
||||
var popInitCalls []mocks.Call
|
||||
regex := regexp.MustCompile(`cmnd\/[a-zA-Z0-9]{15,50}\/PoPInit`)
|
||||
for _, call := range calls {
|
||||
if call.FuncName != "Publish" {
|
||||
continue
|
||||
}
|
||||
|
||||
cmnd, ok := call.Params[0].(string)
|
||||
if !ok {
|
||||
assert.True(s.T(), ok) // fails test case if !ok
|
||||
continue
|
||||
}
|
||||
|
||||
if regex.MatchString(cmnd) {
|
||||
popInitCalls = append(popInitCalls, call)
|
||||
}
|
||||
}
|
||||
assert.Greater(s.T(), len(popInitCalls), 0)
|
||||
}
|
||||
|
||||
func (s *SelectionE2ETestSuite) createValAccount(cfg network.Config) (address sdk.AccAddress, err error) {
|
||||
buf := bufio.NewReader(os.Stdin)
|
||||
|
||||
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, s.T().TempDir(), buf, cfg.Codec, cfg.KeyringOptions...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
keyringAlgos, _ := kb.SupportedAlgorithms()
|
||||
algo, err := keyring.NewSigningAlgoFromString(cfg.SigningAlgo, keyringAlgos)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mnemonic := cfg.Mnemonics[0]
|
||||
|
||||
record, err := kb.NewAccount("node0", mnemonic, keyring.DefaultBIP39Passphrase, sdk.GetConfig().GetFullBIP44Path(), algo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
addr, err := record.GetAddress()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return addr, nil
|
||||
}
|
@ -1,273 +0,0 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/hd"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
bank "github.com/cosmos/cosmos-sdk/x/bank/client/cli"
|
||||
"github.com/planetmint/planetmint-go/config"
|
||||
clitestutil "github.com/planetmint/planetmint-go/testutil/cli"
|
||||
"github.com/planetmint/planetmint-go/testutil/network"
|
||||
"github.com/planetmint/planetmint-go/testutil/sample"
|
||||
daocli "github.com/planetmint/planetmint-go/x/dao/client/cli"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
daotypes "github.com/planetmint/planetmint-go/x/dao/types"
|
||||
)
|
||||
|
||||
var (
|
||||
bobAddr sdk.AccAddress
|
||||
aliceAddr sdk.AccAddress
|
||||
)
|
||||
|
||||
// E2ETestSuite struct definition of dao suite
|
||||
type E2ETestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
cfg network.Config
|
||||
network *network.Network
|
||||
}
|
||||
|
||||
// NewE2ETestSuite returns configured dao E2ETestSuite
|
||||
func NewE2ETestSuite(cfg network.Config) *E2ETestSuite {
|
||||
return &E2ETestSuite{cfg: cfg}
|
||||
}
|
||||
|
||||
// SetupSuite initializes dao E2ETestSuite
|
||||
func (s *E2ETestSuite) SetupSuite() {
|
||||
// set FeeDenom to node0token because the sending account is initialized with no plmnt tokens
|
||||
conf := config.GetConfig()
|
||||
conf.FeeDenom = "node0token"
|
||||
conf.SetPlanetmintConfig(conf)
|
||||
|
||||
s.T().Log("setting up e2e test suite")
|
||||
|
||||
// set accounts for alice and bob in genesis state
|
||||
var authGenState authtypes.GenesisState
|
||||
s.cfg.Codec.MustUnmarshalJSON(s.cfg.GenesisState[authtypes.ModuleName], &authGenState)
|
||||
|
||||
bobAddr = sample.Secp256k1AccAddress()
|
||||
aliceAddr = sample.Secp256k1AccAddress()
|
||||
|
||||
bob := authtypes.NewBaseAccount(bobAddr, nil, 0, 0)
|
||||
alice := authtypes.NewBaseAccount(aliceAddr, nil, 0, 0)
|
||||
|
||||
accounts, err := authtypes.PackAccounts(authtypes.GenesisAccounts{bob, alice})
|
||||
s.Require().NoError(err)
|
||||
|
||||
authGenState.Accounts = append(authGenState.Accounts, accounts...)
|
||||
s.cfg.GenesisState[authtypes.ModuleName] = s.cfg.Codec.MustMarshalJSON(&authGenState)
|
||||
|
||||
// set the balances in genesis state
|
||||
var bankGenState banktypes.GenesisState
|
||||
s.cfg.Codec.MustUnmarshalJSON(s.cfg.GenesisState[banktypes.ModuleName], &bankGenState)
|
||||
|
||||
bbalances := sdk.NewCoins(
|
||||
sdk.NewCoin(conf.TokenDenom, math.NewInt(10000)),
|
||||
sdk.NewCoin(conf.StakeDenom, math.NewInt(10000)),
|
||||
)
|
||||
|
||||
abalances := sdk.NewCoins(
|
||||
sdk.NewCoin(conf.TokenDenom, math.NewInt(10000)),
|
||||
sdk.NewCoin(conf.StakeDenom, math.NewInt(5000)),
|
||||
)
|
||||
|
||||
accountBalances := []banktypes.Balance{
|
||||
{Address: bobAddr.String(), Coins: bbalances.Sort()},
|
||||
{Address: aliceAddr.String(), Coins: abalances.Sort()},
|
||||
}
|
||||
bankGenState.Balances = append(bankGenState.Balances, accountBalances...)
|
||||
s.cfg.GenesisState[banktypes.ModuleName] = s.cfg.Codec.MustMarshalJSON(&bankGenState)
|
||||
|
||||
// Setup MintAddress parameter in genesis state
|
||||
// use sample.Mnemonic to make mint address deterministic for test
|
||||
s.cfg.Mnemonics = []string{sample.Mnemonic}
|
||||
|
||||
// set MintAddress in GenesisState
|
||||
var daoGenState daotypes.GenesisState
|
||||
s.cfg.Codec.MustUnmarshalJSON(s.cfg.GenesisState[daotypes.ModuleName], &daoGenState)
|
||||
valAddr, err := s.createValAccount(s.cfg)
|
||||
s.Require().NoError(err)
|
||||
|
||||
daoGenState.Params.MintAddress = valAddr.String()
|
||||
s.cfg.GenesisState[daotypes.ModuleName] = s.cfg.Codec.MustMarshalJSON(&daoGenState)
|
||||
|
||||
s.cfg.MinGasPrices = fmt.Sprintf("0.000006%s", conf.FeeDenom)
|
||||
s.network = network.New(s.T(), s.cfg)
|
||||
}
|
||||
|
||||
// TearDownSuite clean up after testing
|
||||
func (s *E2ETestSuite) TearDownSuite() {
|
||||
s.T().Log("tearing down e2e test suite")
|
||||
}
|
||||
|
||||
func (s *E2ETestSuite) TestDistributeCollectedFees() {
|
||||
conf := config.GetConfig()
|
||||
val := s.network.Validators[0]
|
||||
|
||||
// sending funds to alice and pay some fees to be distributed
|
||||
args := []string{
|
||||
val.Moniker,
|
||||
aliceAddr.String(),
|
||||
"1000stake",
|
||||
"--yes",
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("10%s", conf.FeeDenom)),
|
||||
}
|
||||
_, err := clitestutil.ExecTestCLICmd(val.ClientCtx, bank.NewSendTxCmd(), args)
|
||||
s.Require().NoError(err)
|
||||
|
||||
err = s.network.WaitForNextBlock()
|
||||
s.Require().NoError(err)
|
||||
|
||||
_, err = clitestutil.ExecTestCLICmd(val.ClientCtx, bank.NewSendTxCmd(), args)
|
||||
s.Require().NoError(err)
|
||||
|
||||
err = s.network.WaitForNextBlock()
|
||||
s.Require().NoError(err)
|
||||
|
||||
err = s.network.WaitForNextBlock()
|
||||
s.Require().NoError(err)
|
||||
|
||||
// assert that alice has 6 of 20 paid fee tokens based on 5000 stake of 15000 total stake
|
||||
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, bank.GetBalancesCmd(), []string{
|
||||
aliceAddr.String(),
|
||||
})
|
||||
assert.Contains(s.T(), out.String(), "node0token")
|
||||
assert.Contains(s.T(), out.String(), "6")
|
||||
s.Require().NoError(err)
|
||||
|
||||
// assert that bob has 13 of 20 paid fee tokens based on 10000 stake of 15000 total stake
|
||||
out, err = clitestutil.ExecTestCLICmd(val.ClientCtx, bank.GetBalancesCmd(), []string{
|
||||
bobAddr.String(),
|
||||
})
|
||||
assert.Contains(s.T(), out.String(), "node0token")
|
||||
assert.Contains(s.T(), out.String(), "13")
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
|
||||
func (s *E2ETestSuite) TestMintToken() {
|
||||
conf := config.GetConfig()
|
||||
val := s.network.Validators[0]
|
||||
|
||||
mintRequest := sample.MintRequest(aliceAddr.String(), 1000, "hash")
|
||||
mrJSON, err := json.Marshal(&mintRequest)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// send mint token request from mint address
|
||||
args := []string{
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Moniker),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("10%s", conf.FeeDenom)),
|
||||
"--yes",
|
||||
string(mrJSON),
|
||||
}
|
||||
|
||||
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, daocli.CmdMintToken(), args)
|
||||
s.Require().NoError(err)
|
||||
|
||||
txResponse, err := clitestutil.GetTxResponseFromOut(out)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(int(0), int(txResponse.Code))
|
||||
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
rawLog, err := clitestutil.GetRawLogFromTxResponse(val, txResponse)
|
||||
s.Require().NoError(err)
|
||||
|
||||
assert.Contains(s.T(), rawLog, "planetmintgo.dao.MsgMintToken")
|
||||
|
||||
// assert that alice has actually received the minted tokens 10000 (initial supply) + 1000 (minted) = 11000 (total)
|
||||
out, err = clitestutil.ExecTestCLICmd(val.ClientCtx, bank.GetBalancesCmd(), []string{
|
||||
aliceAddr.String(),
|
||||
})
|
||||
assert.Contains(s.T(), out.String(), "plmnt")
|
||||
assert.Contains(s.T(), out.String(), "11000")
|
||||
s.Require().NoError(err)
|
||||
|
||||
// send mint token request from non mint address
|
||||
kb := val.ClientCtx.Keyring
|
||||
account, err := kb.NewAccount(sample.Name, sample.Mnemonic, keyring.DefaultBIP39Passphrase, sample.DefaultDerivationPath, hd.Secp256k1)
|
||||
s.Require().NoError(err)
|
||||
|
||||
addr, _ := account.GetAddress()
|
||||
|
||||
// sending funds to account to initialize on chain
|
||||
args = []string{
|
||||
val.Moniker,
|
||||
addr.String(),
|
||||
sample.Amount,
|
||||
"--yes",
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("10%s", conf.FeeDenom)),
|
||||
}
|
||||
_, err = clitestutil.ExecTestCLICmd(val.ClientCtx, bank.NewSendTxCmd(), args)
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
|
||||
args = []string{
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, addr.String()),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, fmt.Sprintf("10%s", conf.FeeDenom)),
|
||||
"--yes",
|
||||
string(mrJSON),
|
||||
}
|
||||
|
||||
out, err = clitestutil.ExecTestCLICmd(val.ClientCtx, daocli.CmdMintToken(), args)
|
||||
s.Require().NoError(err)
|
||||
|
||||
txResponse, err = clitestutil.GetTxResponseFromOut(out)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(int(2), int(txResponse.Code))
|
||||
}
|
||||
|
||||
func (s *E2ETestSuite) createValAccount(cfg network.Config) (address sdk.AccAddress, err error) {
|
||||
buf := bufio.NewReader(os.Stdin)
|
||||
|
||||
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, s.T().TempDir(), buf, cfg.Codec, cfg.KeyringOptions...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
keyringAlgos, _ := kb.SupportedAlgorithms()
|
||||
algo, err := keyring.NewSigningAlgoFromString(cfg.SigningAlgo, keyringAlgos)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mnemonic := cfg.Mnemonics[0]
|
||||
|
||||
record, err := kb.NewAccount("node0", mnemonic, keyring.DefaultBIP39Passphrase, sdk.GetConfig().GetFullBIP44Path(), algo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
addr, err := record.GetAddress()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return addr, nil
|
||||
}
|
||||
|
||||
func (s *E2ETestSuite) TestReissuance() {
|
||||
conf := config.GetConfig()
|
||||
val := s.network.Validators[0]
|
||||
|
||||
var err error
|
||||
for i := 0; i < conf.PoPEpochs+10; i++ {
|
||||
err = s.network.WaitForNextBlock()
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
var height int64
|
||||
height, _ = s.network.LatestHeight()
|
||||
intValue := strconv.FormatInt(height, 10)
|
||||
_, _ = clitestutil.ExecTestCLICmd(val.ClientCtx, daocli.CmdGetReissuance(), []string{intValue})
|
||||
}
|
@ -2,15 +2,16 @@ package machine
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/planetmint/planetmint-go/testutil/network"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
func TestE2ETestSuite(t *testing.T) {
|
||||
t.Parallel()
|
||||
cfg := network.DefaultConfig()
|
||||
cfg.NumValidators = 1
|
||||
func TestE2EMachineTestSuite(t *testing.T) {
|
||||
time.Sleep(2 * time.Second)
|
||||
cfg := network.LoaderDefaultConfig()
|
||||
cfg.NumValidators = 3
|
||||
suite.Run(t, NewE2ETestSuite(cfg))
|
||||
}
|
||||
|
@ -1,70 +0,0 @@
|
||||
package machine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/planetmint/planetmint-go/testutil"
|
||||
"github.com/planetmint/planetmint-go/testutil/sample"
|
||||
machinetypes "github.com/planetmint/planetmint-go/x/machine/types"
|
||||
|
||||
txtypes "github.com/cosmos/cosmos-sdk/types/tx"
|
||||
)
|
||||
|
||||
func (s *E2ETestSuite) TestAttestMachineREST() {
|
||||
val := s.network.Validators[0]
|
||||
baseURL := val.APIAddress
|
||||
|
||||
// Query Sequence Number
|
||||
k, err := val.ClientCtx.Keyring.Key(sample.Name)
|
||||
s.Require().NoError(err)
|
||||
|
||||
addr, err := k.GetAddress()
|
||||
s.Require().NoError(err)
|
||||
|
||||
prvKey, pubKey := sample.KeyPair(1)
|
||||
|
||||
// Register TA
|
||||
ta := sample.TrustAnchor(pubKey)
|
||||
taMsg := machinetypes.MsgRegisterTrustAnchor{
|
||||
Creator: addr.String(),
|
||||
TrustAnchor: &ta,
|
||||
}
|
||||
txBytes, err := testutil.PrepareTx(val, &taMsg, sample.Name)
|
||||
s.Require().NoError(err)
|
||||
|
||||
_, err = testutil.BroadcastTx(val, txBytes)
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
|
||||
// Create Attest Machine TX
|
||||
machine := sample.Machine(sample.Name, pubKey, prvKey, addr.String())
|
||||
msg := machinetypes.MsgAttestMachine{
|
||||
Creator: addr.String(),
|
||||
Machine: &machine,
|
||||
}
|
||||
|
||||
txBytes, err = testutil.PrepareTx(val, &msg, sample.Name)
|
||||
s.Require().NoError(err)
|
||||
|
||||
broadcastTxResponse, err := testutil.BroadcastTx(val, txBytes)
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
tx, err := testutil.GetRequest(fmt.Sprintf("%s/cosmos/tx/v1beta1/txs/%s", val.APIAddress, broadcastTxResponse.TxResponse.TxHash))
|
||||
s.Require().NoError(err)
|
||||
|
||||
var txRes txtypes.GetTxResponse
|
||||
err = val.ClientCtx.Codec.UnmarshalJSON(tx, &txRes)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(uint32(0), txRes.TxResponse.Code)
|
||||
|
||||
queryMachineURL := fmt.Sprintf("%s/planetmint/machine/get_machine_by_public_key/%s", baseURL, pubKey)
|
||||
queryMachineRes, err := testutil.GetRequest(queryMachineURL)
|
||||
s.Require().NoError(err)
|
||||
|
||||
var qmRes machinetypes.QueryGetMachineByPublicKeyResponse
|
||||
err = val.ClientCtx.Codec.UnmarshalJSON(queryMachineRes, &qmRes)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(&machine, qmRes.Machine)
|
||||
}
|
@ -1,29 +1,35 @@
|
||||
package machine
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"bytes"
|
||||
|
||||
"github.com/planetmint/planetmint-go/lib"
|
||||
clitestutil "github.com/planetmint/planetmint-go/testutil/cli"
|
||||
"github.com/planetmint/planetmint-go/testutil/network"
|
||||
"github.com/planetmint/planetmint-go/testutil/sample"
|
||||
machinecli "github.com/planetmint/planetmint-go/x/machine/client/cli"
|
||||
machinetypes "github.com/planetmint/planetmint-go/x/machine/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/hd"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
txcli "github.com/cosmos/cosmos-sdk/x/auth/tx"
|
||||
bank "github.com/cosmos/cosmos-sdk/x/bank/client/cli"
|
||||
feegrant "github.com/cosmos/cosmos-sdk/x/feegrant/client/cli"
|
||||
"github.com/cosmos/cosmos-sdk/x/feegrant"
|
||||
e2etestutil "github.com/planetmint/planetmint-go/testutil/e2e"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"github.com/planetmint/planetmint-go/testutil/moduleobject"
|
||||
)
|
||||
|
||||
// E2ETestSuite struct definition of machine suite
|
||||
type E2ETestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
cfg network.Config
|
||||
network *network.Network
|
||||
cfg network.Config
|
||||
network *network.Network
|
||||
feeDenom string
|
||||
}
|
||||
|
||||
// NewE2ETestSuite returns configured machine E2ETestSuite
|
||||
@ -33,41 +39,21 @@ func NewE2ETestSuite(cfg network.Config) *E2ETestSuite {
|
||||
|
||||
// SetupSuite initializes machine E2ETestSuite
|
||||
func (s *E2ETestSuite) SetupSuite() {
|
||||
s.T().Log("setting up e2e test suite")
|
||||
s.T().Log("setting up e2e machine test suite")
|
||||
|
||||
s.network = network.New(s.T())
|
||||
val := s.network.Validators[0]
|
||||
s.feeDenom = sample.FeeDenom
|
||||
s.network = network.Load(s.T(), s.cfg)
|
||||
|
||||
kb := val.ClientCtx.Keyring
|
||||
account, err := kb.NewAccount(sample.Name, sample.Mnemonic, keyring.DefaultBIP39Passphrase, sample.DefaultDerivationPath, hd.Secp256k1)
|
||||
// create machine account for attestation
|
||||
account, err := e2etestutil.CreateAccount(s.network, sample.Name, sample.Mnemonic)
|
||||
s.Require().NoError(err)
|
||||
|
||||
addr, _ := account.GetAddress()
|
||||
|
||||
// sending funds to machine to initialize account on chain
|
||||
args := []string{
|
||||
val.Moniker,
|
||||
addr.String(),
|
||||
sample.Amount,
|
||||
"--yes",
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, sample.Fees),
|
||||
}
|
||||
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, bank.NewSendTxCmd(), args)
|
||||
err = e2etestutil.FundAccount(s.network, account, s.feeDenom)
|
||||
s.Require().NoError(err)
|
||||
|
||||
txResponse, err := clitestutil.GetTxResponseFromOut(out)
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
rawLog, err := clitestutil.GetRawLogFromTxResponse(val, txResponse)
|
||||
s.Require().NoError(err)
|
||||
|
||||
assert.Contains(s.T(), rawLog, "cosmos.bank.v1beta1.MsgSend")
|
||||
}
|
||||
|
||||
// TearDownSuite clean up after testing
|
||||
func (s *E2ETestSuite) TearDownSuite() {
|
||||
s.T().Log("tearing down e2e test suite")
|
||||
s.T().Log("tearing down e2e machine test suite")
|
||||
}
|
||||
|
||||
// TestAttestMachine attests machine and query attested machine from chain
|
||||
@ -77,24 +63,14 @@ func (s *E2ETestSuite) TestAttestMachine() {
|
||||
// register Ta
|
||||
prvKey, pubKey := sample.KeyPair()
|
||||
|
||||
ta := sample.TrustAnchor(pubKey)
|
||||
taJSON, err := json.Marshal(&ta)
|
||||
s.Require().NoError(err)
|
||||
args := []string{
|
||||
fmt.Sprintf("--%s=%s", flags.FlagChainID, s.network.Config.ChainID),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, sample.Name),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, sample.Fees),
|
||||
"--yes",
|
||||
string(taJSON),
|
||||
}
|
||||
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, machinecli.CmdRegisterTrustAnchor(), args)
|
||||
s.Require().NoError(err)
|
||||
|
||||
txResponse, err := clitestutil.GetTxResponseFromOut(out)
|
||||
ta := moduleobject.TrustAnchor(pubKey)
|
||||
msg1 := machinetypes.NewMsgRegisterTrustAnchor(val.Address.String(), &ta)
|
||||
out, err := e2etestutil.BuildSignBroadcastTx(s.T(), val.Address, msg1)
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
rawLog, err := clitestutil.GetRawLogFromTxResponse(val, txResponse)
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
rawLog, err := clitestutil.GetRawLogFromTxOut(val, out)
|
||||
s.Require().NoError(err)
|
||||
|
||||
assert.Contains(s.T(), rawLog, "planetmintgo.machine.MsgRegisterTrustAnchor")
|
||||
@ -103,84 +79,88 @@ func (s *E2ETestSuite) TestAttestMachine() {
|
||||
s.Require().NoError(err)
|
||||
addr, _ := k.GetAddress()
|
||||
|
||||
machine := sample.Machine(sample.Name, pubKey, prvKey, addr.String())
|
||||
machineJSON, err := json.Marshal(&machine)
|
||||
// Check preAttestationBalance in order to verify that it doesn't change after machine attestation
|
||||
preAttestationBalanceOutput, err := clitestutil.ExecTestCLICmd(val.ClientCtx, bank.GetBalancesCmd(), []string{
|
||||
addr.String(),
|
||||
})
|
||||
s.Require().NoError(err)
|
||||
|
||||
args = []string{
|
||||
fmt.Sprintf("--%s=%s", flags.FlagChainID, s.network.Config.ChainID),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, sample.Name),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, sample.Fees),
|
||||
"--yes",
|
||||
string(machineJSON),
|
||||
preAttestationBalance, ok := preAttestationBalanceOutput.(*bytes.Buffer)
|
||||
if !ok {
|
||||
err = lib.ErrTypeAssertionFailed
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
assert.Contains(s.T(), preAttestationBalance.String(), "10000")
|
||||
|
||||
out, err = clitestutil.ExecTestCLICmd(val.ClientCtx, machinecli.CmdAttestMachine(), args)
|
||||
s.Require().NoError(err)
|
||||
|
||||
txResponse, err = clitestutil.GetTxResponseFromOut(out)
|
||||
machine := moduleobject.Machine(sample.Name, pubKey, prvKey, addr.String())
|
||||
msg2 := machinetypes.NewMsgAttestMachine(addr.String(), &machine)
|
||||
out, err = e2etestutil.BuildSignBroadcastTx(s.T(), addr, msg2)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// give machine attestation some time to issue the liquid asset
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
rawLog, err = clitestutil.GetRawLogFromTxResponse(val, txResponse)
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
|
||||
rawLog, err = clitestutil.GetRawLogFromTxOut(val, out)
|
||||
s.Require().NoError(err)
|
||||
|
||||
assert.Contains(s.T(), rawLog, "planetmintgo.machine.MsgAttestMachine")
|
||||
|
||||
args = []string{
|
||||
args := []string{
|
||||
pubKey,
|
||||
}
|
||||
|
||||
_, err = clitestutil.ExecTestCLICmd(val.ClientCtx, machinecli.CmdGetMachineByPublicKey(), args)
|
||||
_, err = clitestutil.ExecTestCLICmd(val.ClientCtx, machinecli.GetCmdMachineByPublicKey(), args)
|
||||
s.Require().NoError(err)
|
||||
txResponse, err := lib.GetTxResponseFromOut(out)
|
||||
s.Require().NoError(err)
|
||||
|
||||
txResp, err := txcli.QueryTx(val.ClientCtx, txResponse.TxHash)
|
||||
s.Require().NoError(err)
|
||||
|
||||
assert.Contains(s.T(), txResp.TxHash, txResponse.TxHash)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Check postAttestationBalance it should be the preAttestationBalance + th 8800 tokens being donated to the machine (no fees are taken)
|
||||
postAttestationBalanceOutput, err := clitestutil.ExecTestCLICmd(val.ClientCtx, bank.GetBalancesCmd(), []string{
|
||||
addr.String(),
|
||||
})
|
||||
s.Require().NoError(err)
|
||||
postAttestationBalance, ok := postAttestationBalanceOutput.(*bytes.Buffer)
|
||||
if !ok {
|
||||
err = lib.ErrTypeAssertionFailed
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
assert.Contains(s.T(), postAttestationBalance.String(), "18800")
|
||||
}
|
||||
|
||||
func (s *E2ETestSuite) TestInvalidAttestMachine() {
|
||||
val := s.network.Validators[0]
|
||||
|
||||
// already used in REST test case
|
||||
prvKey, pubKey := sample.KeyPair(1)
|
||||
// already used in previous test case
|
||||
prvKey, pubKey := sample.KeyPair()
|
||||
|
||||
k, err := val.ClientCtx.Keyring.Key(sample.Name)
|
||||
s.Require().NoError(err)
|
||||
addr, _ := k.GetAddress()
|
||||
|
||||
machine := sample.Machine(sample.Name, pubKey, prvKey, addr.String())
|
||||
machineJSON, err := json.Marshal(&machine)
|
||||
machine := moduleobject.Machine(sample.Name, pubKey, prvKey, addr.String())
|
||||
s.Require().NoError(err)
|
||||
|
||||
args := []string{
|
||||
fmt.Sprintf("--%s=%s", flags.FlagChainID, s.network.Config.ChainID),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, sample.Name),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, sample.Fees),
|
||||
"--yes",
|
||||
string(machineJSON),
|
||||
}
|
||||
|
||||
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, machinecli.CmdAttestMachine(), args)
|
||||
s.Require().NoError(err)
|
||||
|
||||
txResponse, err := clitestutil.GetTxResponseFromOut(out)
|
||||
msg := machinetypes.NewMsgAttestMachine(addr.String(), &machine)
|
||||
out, _ := lib.BroadcastTxWithFileLock(addr, msg)
|
||||
txResponse, err := lib.GetTxResponseFromOut(out)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(int(txResponse.Code), int(4))
|
||||
|
||||
unregisteredPubKey, unregisteredPrivKey := sample.KeyPair(2)
|
||||
machine = sample.Machine(sample.Name, unregisteredPubKey, unregisteredPrivKey, addr.String())
|
||||
machineJSON, err = json.Marshal(&machine)
|
||||
machine = moduleobject.Machine(sample.Name, unregisteredPubKey, unregisteredPrivKey, addr.String())
|
||||
s.Require().NoError(err)
|
||||
|
||||
args = []string{
|
||||
fmt.Sprintf("--%s=%s", flags.FlagChainID, s.network.Config.ChainID),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, sample.Name),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, sample.Fees),
|
||||
"--yes",
|
||||
string(machineJSON),
|
||||
}
|
||||
|
||||
out, err = clitestutil.ExecTestCLICmd(val.ClientCtx, machinecli.CmdAttestMachine(), args)
|
||||
s.Require().NoError(err)
|
||||
|
||||
txResponse, err = clitestutil.GetTxResponseFromOut(out)
|
||||
msg = machinetypes.NewMsgAttestMachine(addr.String(), &machine)
|
||||
out, _ = lib.BroadcastTxWithFileLock(addr, msg)
|
||||
txResponse, err = lib.GetTxResponseFromOut(out)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(int(txResponse.Code), int(3))
|
||||
}
|
||||
@ -199,59 +179,57 @@ func (s *E2ETestSuite) TestMachineAllowanceAttestation() {
|
||||
// register TA
|
||||
prvKey, pubKey := sample.KeyPair(3)
|
||||
|
||||
ta := sample.TrustAnchor(pubKey)
|
||||
taJSON, err := json.Marshal(&ta)
|
||||
ta := moduleobject.TrustAnchor(pubKey)
|
||||
msg1 := machinetypes.NewMsgRegisterTrustAnchor(val.Address.String(), &ta)
|
||||
_, err = e2etestutil.BuildSignBroadcastTx(s.T(), val.Address, msg1)
|
||||
s.Require().NoError(err)
|
||||
args := []string{
|
||||
fmt.Sprintf("--%s=%s", flags.FlagChainID, s.network.Config.ChainID),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Moniker),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, sample.Fees),
|
||||
"--yes",
|
||||
string(taJSON),
|
||||
}
|
||||
_, err = clitestutil.ExecTestCLICmd(val.ClientCtx, machinecli.CmdRegisterTrustAnchor(), args)
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
|
||||
// create allowance for machine
|
||||
args = []string{
|
||||
val.Moniker, // granter
|
||||
addr.String(), // grantee
|
||||
fmt.Sprintf("--%s=%s", feegrant.FlagAllowedMsgs, "/planetmintgo.machine.MsgAttestMachine"),
|
||||
fmt.Sprintf("--%s=%s", feegrant.FlagSpendLimit, "2stake"),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, sample.Fees),
|
||||
"--yes",
|
||||
allowedMsgs := []string{"/planetmintgo.machine.MsgAttestMachine"}
|
||||
limit := sdk.NewCoins(sdk.NewInt64Coin(s.feeDenom, 2))
|
||||
basic := feegrant.BasicAllowance{
|
||||
SpendLimit: limit,
|
||||
}
|
||||
|
||||
_, err = clitestutil.ExecTestCLICmd(val.ClientCtx, feegrant.NewCmdFeeGrant(), args)
|
||||
var grant feegrant.FeeAllowanceI
|
||||
grant = &basic
|
||||
grant, err = feegrant.NewAllowedMsgAllowance(grant, allowedMsgs)
|
||||
s.Require().NoError(err)
|
||||
|
||||
msg2, err := feegrant.NewMsgGrantAllowance(grant, val.Address, addr)
|
||||
s.Require().NoError(err)
|
||||
_, err = e2etestutil.BuildSignBroadcastTx(s.T(), val.Address, msg2)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
|
||||
// attest machine with fee granter without funding the machine account first
|
||||
machine := sample.Machine(sample.Name, pubKey, prvKey, addr.String())
|
||||
machineJSON, err := json.Marshal(&machine)
|
||||
machine := moduleobject.Machine(sample.Name, pubKey, prvKey, addr.String())
|
||||
s.Require().NoError(err)
|
||||
|
||||
args = []string{
|
||||
fmt.Sprintf("--%s=%s", flags.FlagChainID, s.network.Config.ChainID),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFrom, addr.String()),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFees, sample.Fees),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagFeeGranter, val.Address.String()),
|
||||
"--yes",
|
||||
string(machineJSON),
|
||||
}
|
||||
// name and address of private key with which to sign
|
||||
clientCtx := val.ClientCtx.
|
||||
WithFeeGranterAddress(val.Address)
|
||||
libConfig := lib.GetConfig()
|
||||
libConfig.SetClientCtx(clientCtx)
|
||||
|
||||
msg3 := machinetypes.NewMsgAttestMachine(addr.String(), &machine)
|
||||
_, err = e2etestutil.BuildSignBroadcastTx(s.T(), addr, msg3)
|
||||
|
||||
// reset clientCtx to validator ctx
|
||||
libConfig.SetClientCtx(val.ClientCtx)
|
||||
|
||||
_, err = clitestutil.ExecTestCLICmd(val.ClientCtx, machinecli.CmdAttestMachine(), args)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// give machine attestation some time to issue the liquid asset
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
|
||||
args = []string{
|
||||
args := []string{
|
||||
pubKey,
|
||||
}
|
||||
|
||||
_, err = clitestutil.ExecTestCLICmd(val.ClientCtx, machinecli.CmdGetMachineByPublicKey(), args)
|
||||
_, err = clitestutil.ExecTestCLICmd(val.ClientCtx, machinecli.GetCmdMachineByPublicKey(), args)
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
|
@ -1,74 +1,81 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/planetmint/planetmint-go/testutil"
|
||||
"regexp"
|
||||
"errors"
|
||||
|
||||
"github.com/planetmint/planetmint-go/lib"
|
||||
"github.com/planetmint/planetmint-go/testutil"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/testutil/network"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
|
||||
"github.com/planetmint/planetmint-go/testutil/network"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
// ExecTestCLICmd builds the client context, mocks the output and executes the command.
|
||||
func ExecTestCLICmd(clientCtx client.Context, cmd *cobra.Command, extraArgs []string) (testutil.BufferWriter, error) {
|
||||
func ExecTestCLICmd(clientCtx client.Context, cmd *cobra.Command, extraArgs []string) (out testutil.BufferWriter, err error) {
|
||||
cmd.SetArgs(extraArgs)
|
||||
|
||||
_, out := testutil.ApplyMockIO(cmd)
|
||||
_, out = testutil.ApplyMockIO(cmd)
|
||||
clientCtx = clientCtx.WithOutput(out)
|
||||
|
||||
ctx := context.Background()
|
||||
ctx = context.WithValue(ctx, client.ClientContextKey, &clientCtx)
|
||||
|
||||
if err := cmd.ExecuteContext(ctx); err != nil {
|
||||
return out, err
|
||||
if err = cmd.ExecuteContext(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return out, nil
|
||||
output, ok := out.(*bytes.Buffer)
|
||||
if !ok {
|
||||
err = lib.ErrTypeAssertionFailed
|
||||
return
|
||||
}
|
||||
|
||||
txResponse, err := lib.GetTxResponseFromOut(output)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if txResponse.Code != 0 {
|
||||
err = errors.New(txResponse.RawLog)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetTxResponseFromOut converts strings to numbers and unmarshalles out into TxResponse struct
|
||||
func GetTxResponseFromOut(out testutil.BufferWriter) (sdk.TxResponse, error) {
|
||||
var txResponse sdk.TxResponse
|
||||
|
||||
m := regexp.MustCompile(`"([0-9]+?)"`)
|
||||
str := m.ReplaceAllString(out.String(), "${1}")
|
||||
|
||||
// We might have YAML here, so we need to convert to JSON first, because TxResponse struct lacks `yaml:"height,omitempty"`, etc.
|
||||
// Since JSON is a subset of YAML, passing JSON through YAMLToJSON is a no-op and the result is the byte array of the JSON again.
|
||||
j, err := yaml.YAMLToJSON([]byte(str))
|
||||
// GetRawLogFromTxOut queries the TxHash of out from the chain and returns the RawLog from the answer.
|
||||
func GetRawLogFromTxOut(val *network.Validator, out *bytes.Buffer) (rawLog string, err error) {
|
||||
txResponse, err := lib.GetTxResponseFromOut(out)
|
||||
if err != nil {
|
||||
return txResponse, err
|
||||
return
|
||||
}
|
||||
|
||||
err = json.Unmarshal(j, &txResponse)
|
||||
if err != nil {
|
||||
return txResponse, err
|
||||
if txResponse.Code != 0 {
|
||||
err = errors.New(txResponse.RawLog)
|
||||
return
|
||||
}
|
||||
|
||||
return txResponse, nil
|
||||
}
|
||||
|
||||
// GetRawLogFromTxResponse queries the TxHash of txResponse from the chain and returns the RawLog from the answer.
|
||||
func GetRawLogFromTxResponse(val *network.Validator, txResponse sdk.TxResponse) (string, error) {
|
||||
args := []string{
|
||||
txResponse.TxHash,
|
||||
}
|
||||
|
||||
out, err := ExecTestCLICmd(val.ClientCtx, authcmd.QueryTxCmd(), args)
|
||||
output, err := ExecTestCLICmd(val.ClientCtx, authcmd.QueryTxCmd(), args)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return
|
||||
}
|
||||
|
||||
txRes, err := GetTxResponseFromOut(out)
|
||||
if err != nil {
|
||||
return "", err
|
||||
out, ok := output.(*bytes.Buffer)
|
||||
if !ok {
|
||||
err = lib.ErrTypeAssertionFailed
|
||||
return
|
||||
}
|
||||
|
||||
return txRes.RawLog, nil
|
||||
txRes, err := lib.GetTxResponseFromOut(out)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
rawLog = txRes.RawLog
|
||||
return
|
||||
}
|
||||
|
116
testutil/e2e/e2e.go
Normal file
116
testutil/e2e/e2e.go
Normal file
@ -0,0 +1,116 @@
|
||||
package e2e
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/crypto/hd"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
"github.com/planetmint/planetmint-go/lib"
|
||||
clitestutil "github.com/planetmint/planetmint-go/testutil/cli"
|
||||
"github.com/planetmint/planetmint-go/testutil/moduleobject"
|
||||
"github.com/planetmint/planetmint-go/testutil/network"
|
||||
"github.com/planetmint/planetmint-go/testutil/sample"
|
||||
machinetypes "github.com/planetmint/planetmint-go/x/machine/types"
|
||||
)
|
||||
|
||||
func CreateAccount(network *network.Network, name string, mnemonic string) (account *keyring.Record, err error) {
|
||||
val := network.Validators[0]
|
||||
|
||||
kb := val.ClientCtx.Keyring
|
||||
account, err = kb.NewAccount(name, mnemonic, keyring.DefaultBIP39Passphrase, sample.DefaultDerivationPath, hd.Secp256k1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return account, nil
|
||||
}
|
||||
|
||||
func FundAccount(network *network.Network, account *keyring.Record, tokenDenom string) (err error) {
|
||||
val := network.Validators[0]
|
||||
|
||||
addr, err := account.GetAddress()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// sending funds to account to initialize account on chain
|
||||
coin := sdk.NewCoins(sdk.NewInt64Coin(tokenDenom, 10000))
|
||||
msg := banktypes.NewMsgSend(val.Address, addr, coin)
|
||||
out, err := lib.BroadcastTxWithFileLock(val.Address, msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = network.WaitForNextBlock()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = network.WaitForNextBlock()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rawLog, err := clitestutil.GetRawLogFromTxOut(val, out)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !strings.Contains(rawLog, "cosmos.bank.v1beta1.MsgSend") {
|
||||
err = errors.New("failed to fund account")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func AttestMachine(network *network.Network, name string, mnemonic string, num int, tokenDenom string) (err error) {
|
||||
val := network.Validators[0]
|
||||
|
||||
account, err := CreateAccount(network, name, mnemonic)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = FundAccount(network, account, tokenDenom)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// register Ta
|
||||
prvKey, pubKey := sample.KeyPair(num)
|
||||
ta := moduleobject.TrustAnchor(pubKey)
|
||||
registerMsg := machinetypes.NewMsgRegisterTrustAnchor(val.Address.String(), &ta)
|
||||
_, err = lib.BroadcastTxWithFileLock(val.Address, registerMsg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = network.WaitForNextBlock()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
addr, err := account.GetAddress()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
machine := moduleobject.Machine(name, pubKey, prvKey, addr.String())
|
||||
attestMsg := machinetypes.NewMsgAttestMachine(addr.String(), &machine)
|
||||
_, err = lib.BroadcastTxWithFileLock(addr, attestMsg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = network.WaitForNextBlock()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = network.WaitForNextBlock()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
29
testutil/e2e/tx.go
Normal file
29
testutil/e2e/tx.go
Normal file
@ -0,0 +1,29 @@
|
||||
package e2e
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/planetmint/planetmint-go/lib"
|
||||
)
|
||||
|
||||
// BuildSignBroadcastTx builds, signs and broadcasts transaction to the network.
|
||||
func BuildSignBroadcastTx(t *testing.T, addr sdk.AccAddress, msgs ...sdk.Msg) (out *bytes.Buffer, err error) {
|
||||
out, err = lib.BroadcastTxWithFileLock(addr, msgs...)
|
||||
if err != nil {
|
||||
t.Log("broadcast tx failed: " + err.Error())
|
||||
return
|
||||
}
|
||||
txResponse, err := lib.GetTxResponseFromOut(out)
|
||||
if err != nil {
|
||||
t.Log("getting tx response from out failed: " + err.Error())
|
||||
return
|
||||
}
|
||||
if txResponse.Code != 0 {
|
||||
err = errors.New(txResponse.RawLog)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
5
testutil/errormsg/error.go
Normal file
5
testutil/errormsg/error.go
Normal file
@ -0,0 +1,5 @@
|
||||
package errormsg
|
||||
|
||||
var (
|
||||
ErrorInvalidAddress = "invalid_address"
|
||||
)
|
@ -4,6 +4,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/planetmint/planetmint-go/config"
|
||||
"github.com/planetmint/planetmint-go/testutil/moduleobject"
|
||||
"github.com/planetmint/planetmint-go/testutil/sample"
|
||||
"github.com/planetmint/planetmint-go/x/asset/keeper"
|
||||
"github.com/planetmint/planetmint-go/x/asset/types"
|
||||
@ -49,15 +50,15 @@ func AssetKeeper(t testing.TB) (*keeper.Keeper, sdk.Context) {
|
||||
ctrl := gomock.NewController(t)
|
||||
mk := assettestutils.NewMockMachineKeeper(ctrl)
|
||||
sk, pk := sample.KeyPair()
|
||||
_, ppk := sample.ExtendedKeyPair(config.PlmntNetParams)
|
||||
_, lpk := sample.ExtendedKeyPair(config.LiquidNetParams)
|
||||
_, ppk := moduleobject.ExtendedKeyPair(config.PlmntNetParams)
|
||||
_, lpk := moduleobject.ExtendedKeyPair(config.LiquidNetParams)
|
||||
|
||||
id := sample.MachineIndex(pk, ppk, lpk)
|
||||
id := moduleobject.MachineIndex(pk, ppk, lpk)
|
||||
mk.EXPECT().GetMachineIndexByPubKey(ctx, pk).Return(id, true).AnyTimes()
|
||||
mk.EXPECT().GetMachineIndexByPubKey(ctx, ppk).Return(id, true).AnyTimes()
|
||||
mk.EXPECT().GetMachineIndexByPubKey(ctx, sk).Return(id, false).AnyTimes()
|
||||
mk.EXPECT().GetMachine(ctx, id).Return(sample.Machine(pk, pk, sk, ""), true).AnyTimes()
|
||||
mk.EXPECT().GetMachine(ctx, sk).Return(sample.Machine(pk, pk, sk, ""), false).AnyTimes()
|
||||
mk.EXPECT().GetMachine(ctx, id).Return(moduleobject.Machine(pk, pk, sk, ""), true).AnyTimes()
|
||||
mk.EXPECT().GetMachine(ctx, sk).Return(moduleobject.Machine(pk, pk, sk, ""), false).AnyTimes()
|
||||
|
||||
k := keeper.NewKeeper(
|
||||
cdc,
|
||||
|
@ -15,18 +15,16 @@ import (
|
||||
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
|
||||
typesparams "github.com/cosmos/cosmos-sdk/x/params/types"
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/planetmint/planetmint-go/config"
|
||||
"github.com/planetmint/planetmint-go/testutil/sample"
|
||||
"github.com/planetmint/planetmint-go/monitor"
|
||||
monitormocks "github.com/planetmint/planetmint-go/monitor/mocks"
|
||||
"github.com/planetmint/planetmint-go/x/dao/keeper"
|
||||
daotestutil "github.com/planetmint/planetmint-go/x/dao/testutil"
|
||||
"github.com/planetmint/planetmint-go/x/dao/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
daotestutil "github.com/planetmint/planetmint-go/x/dao/testutil"
|
||||
)
|
||||
|
||||
func DaoKeeper(t testing.TB) (*keeper.Keeper, sdk.Context) {
|
||||
cfg := config.GetConfig()
|
||||
|
||||
monitor.SetMqttMonitorInstance(&monitormocks.MockMQTTMonitorClientI{})
|
||||
storeKey := sdk.NewKVStoreKey(types.StoreKey)
|
||||
memStoreKey := storetypes.NewMemoryStoreKey(types.MemStoreKey)
|
||||
challengeStoreKey := storetypes.NewMemoryStoreKey(types.ChallengeKey)
|
||||
@ -58,11 +56,11 @@ func DaoKeeper(t testing.TB) (*keeper.Keeper, sdk.Context) {
|
||||
ctrl := gomock.NewController(t)
|
||||
bk := daotestutil.NewMockBankKeeper(ctrl)
|
||||
|
||||
amt := sdk.NewCoins(sdk.NewCoin(cfg.TokenDenom, sdk.NewIntFromUint64(1000)))
|
||||
beneficiaryAddr, _ := sdk.AccAddressFromBech32(sample.ConstBech32Addr)
|
||||
|
||||
bk.EXPECT().MintCoins(ctx, types.ModuleName, amt).Return(nil).AnyTimes()
|
||||
bk.EXPECT().SendCoinsFromModuleToAccount(ctx, types.ModuleName, beneficiaryAddr, amt).Return(nil).AnyTimes()
|
||||
bk.EXPECT().MintCoins(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
|
||||
bk.EXPECT().BurnCoins(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
|
||||
bk.EXPECT().SendCoinsFromModuleToAccount(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
|
||||
bk.EXPECT().SendCoinsFromAccountToModule(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
|
||||
bk.EXPECT().GetBalance(gomock.Any(), gomock.Any(), gomock.Any()).Return(sdk.NewCoin("crddl", sdk.NewInt(10000))).AnyTimes()
|
||||
|
||||
k := keeper.NewKeeper(
|
||||
cdc,
|
||||
@ -71,10 +69,13 @@ func DaoKeeper(t testing.TB) (*keeper.Keeper, sdk.Context) {
|
||||
challengeStoreKey,
|
||||
mintRequestHashStoreKey,
|
||||
mintRequestAddressStoreKey,
|
||||
nil, // TODO: mount and add store/key
|
||||
paramsSubspace,
|
||||
bk,
|
||||
nil,
|
||||
nil,
|
||||
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
|
||||
"",
|
||||
)
|
||||
|
||||
// Initialize params
|
||||
|
@ -14,6 +14,8 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/store"
|
||||
storetypes "github.com/cosmos/cosmos-sdk/store/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
|
||||
typesparams "github.com/cosmos/cosmos-sdk/x/params/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@ -58,12 +60,14 @@ func MachineKeeper(t testing.TB) (*keeper.Keeper, sdk.Context) {
|
||||
addressStoreKey,
|
||||
memStoreKey,
|
||||
paramsSubspace,
|
||||
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
|
||||
"",
|
||||
)
|
||||
|
||||
ctx := sdk.NewContext(stateStore, tmproto.Header{}, false, log.NewNopLogger())
|
||||
|
||||
// Initialize params
|
||||
k.SetParams(ctx, types.DefaultParams())
|
||||
_ = k.SetParams(ctx, types.DefaultParams())
|
||||
|
||||
return k, ctx
|
||||
}
|
||||
|
66
testutil/mocks/rddl_claim_service_client_mock.go
Normal file
66
testutil/mocks/rddl_claim_service_client_mock.go
Normal file
@ -0,0 +1,66 @@
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: ./clients/claim_client.go
|
||||
|
||||
// Package mocks is a generated GoMock package.
|
||||
package mocks
|
||||
|
||||
import (
|
||||
context "context"
|
||||
reflect "reflect"
|
||||
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
"github.com/rddl-network/rddl-claim-service/types"
|
||||
)
|
||||
|
||||
// MockIRCClient is a mock of IRCClient interface.
|
||||
type MockIRCClient struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockIRCClientMockRecorder
|
||||
}
|
||||
|
||||
// MockIRCClientMockRecorder is the mock recorder for MockIRCClient.
|
||||
type MockIRCClientMockRecorder struct {
|
||||
mock *MockIRCClient
|
||||
}
|
||||
|
||||
// NewMockIRCClient creates a new mock instance.
|
||||
func NewMockIRCClient(ctrl *gomock.Controller) *MockIRCClient {
|
||||
mock := &MockIRCClient{ctrl: ctrl}
|
||||
mock.recorder = &MockIRCClientMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockIRCClient) EXPECT() *MockIRCClientMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// GetClaim mocks base method.
|
||||
func (m *MockIRCClient) GetClaim(ctx context.Context, id int) (types.GetClaimResponse, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetClaim", ctx, id)
|
||||
ret0, _ := ret[0].(types.GetClaimResponse)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetClaim indicates an expected call of GetClaim.
|
||||
func (mr *MockIRCClientMockRecorder) GetClaim(ctx, id interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetClaim", reflect.TypeOf((*MockIRCClient)(nil).GetClaim), ctx, id)
|
||||
}
|
||||
|
||||
// PostClaim mocks base method.
|
||||
func (m *MockIRCClient) PostClaim(ctx context.Context, req types.PostClaimRequest) (types.PostClaimResponse, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "PostClaim", ctx, req)
|
||||
ret0, _ := ret[0].(types.PostClaimResponse)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// PostClaim indicates an expected call of PostClaim.
|
||||
func (mr *MockIRCClientMockRecorder) PostClaim(ctx, req interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PostClaim", reflect.TypeOf((*MockIRCClient)(nil).PostClaim), ctx, req)
|
||||
}
|
110
testutil/mocks/shamir_coordinator_client_mock.go
Normal file
110
testutil/mocks/shamir_coordinator_client_mock.go
Normal file
@ -0,0 +1,110 @@
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: ./clients/shamir_coordinator_client.go
|
||||
|
||||
// Package mocks is a generated GoMock package.
|
||||
package mocks
|
||||
|
||||
import (
|
||||
context "context"
|
||||
reflect "reflect"
|
||||
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
"github.com/rddl-network/shamir-coordinator-service/types"
|
||||
)
|
||||
|
||||
// MockISCClient is a mock of ISCClient interface.
|
||||
type MockISCClient struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockISCClientMockRecorder
|
||||
}
|
||||
|
||||
// MockISCClientMockRecorder is the mock recorder for MockISCClient.
|
||||
type MockISCClientMockRecorder struct {
|
||||
mock *MockISCClient
|
||||
}
|
||||
|
||||
// NewMockISCClient creates a new mock instance.
|
||||
func NewMockISCClient(ctrl *gomock.Controller) *MockISCClient {
|
||||
mock := &MockISCClient{ctrl: ctrl}
|
||||
mock.recorder = &MockISCClientMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockISCClient) EXPECT() *MockISCClientMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// GetMnemonics mocks base method.
|
||||
func (m *MockISCClient) GetMnemonics(ctx context.Context) (types.MnemonicsResponse, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetMnemonics", ctx)
|
||||
ret0, _ := ret[0].(types.MnemonicsResponse)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetMnemonics indicates an expected call of GetMnemonics.
|
||||
func (mr *MockISCClientMockRecorder) GetMnemonics(ctx interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMnemonics", reflect.TypeOf((*MockISCClient)(nil).GetMnemonics), ctx)
|
||||
}
|
||||
|
||||
// IssueMachineNFT mocks base method.
|
||||
func (m *MockISCClient) IssueMachineNFT(ctx context.Context, name, machineAddress, domain string) (types.IssueMachineNFTResponse, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "IssueMachineNFT", ctx, name, machineAddress, domain)
|
||||
ret0, _ := ret[0].(types.IssueMachineNFTResponse)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// IssueMachineNFT indicates an expected call of IssueMachineNFT.
|
||||
func (mr *MockISCClientMockRecorder) IssueMachineNFT(ctx, name, machineAddress, domain interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IssueMachineNFT", reflect.TypeOf((*MockISCClient)(nil).IssueMachineNFT), ctx, name, machineAddress, domain)
|
||||
}
|
||||
|
||||
// PostMnemonics mocks base method.
|
||||
func (m *MockISCClient) PostMnemonics(ctx context.Context, secret string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "PostMnemonics", ctx, secret)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// PostMnemonics indicates an expected call of PostMnemonics.
|
||||
func (mr *MockISCClientMockRecorder) PostMnemonics(ctx, secret interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PostMnemonics", reflect.TypeOf((*MockISCClient)(nil).PostMnemonics), ctx, secret)
|
||||
}
|
||||
|
||||
// ReIssueAsset mocks base method.
|
||||
func (m *MockISCClient) ReIssueAsset(ctx context.Context, asset, amount string) (types.ReIssueResponse, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ReIssueAsset", ctx, asset, amount)
|
||||
ret0, _ := ret[0].(types.ReIssueResponse)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// ReIssueAsset indicates an expected call of ReIssueAsset.
|
||||
func (mr *MockISCClientMockRecorder) ReIssueAsset(ctx, asset, amount interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReIssueAsset", reflect.TypeOf((*MockISCClient)(nil).ReIssueAsset), ctx, asset, amount)
|
||||
}
|
||||
|
||||
// SendTokens mocks base method.
|
||||
func (m *MockISCClient) SendTokens(ctx context.Context, recipient, amount, asset string) (types.SendTokensResponse, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SendTokens", ctx, recipient, amount, asset)
|
||||
ret0, _ := ret[0].(types.SendTokensResponse)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// SendTokens indicates an expected call of SendTokens.
|
||||
func (mr *MockISCClientMockRecorder) SendTokens(ctx, recipient, amount, asset interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendTokens", reflect.TypeOf((*MockISCClient)(nil).SendTokens), ctx, recipient, amount, asset)
|
||||
}
|
132
testutil/moduleobject/sampleobject.go
Normal file
132
testutil/moduleobject/sampleobject.go
Normal file
@ -0,0 +1,132 @@
|
||||
package moduleobject
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"strconv"
|
||||
|
||||
"github.com/btcsuite/btcd/btcutil/hdkeychain"
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/planetmint/planetmint-go/config"
|
||||
"github.com/planetmint/planetmint-go/testutil/sample"
|
||||
daotypes "github.com/planetmint/planetmint-go/x/dao/types"
|
||||
machinetypes "github.com/planetmint/planetmint-go/x/machine/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
|
||||
"github.com/cosmos/go-bip39"
|
||||
)
|
||||
|
||||
func ExtendedKeyPair(cfg chaincfg.Params) (string, string) {
|
||||
seed, err := bip39.NewSeedWithErrorChecking(sample.Mnemonic, keyring.DefaultBIP39Passphrase)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
xprivKey, err := hdkeychain.NewMaster(seed, &cfg)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
xpubKey, err := xprivKey.Neuter()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return xprivKey.String(), xpubKey.String()
|
||||
}
|
||||
|
||||
// Machine creates a new machine object
|
||||
// TODO: make address deterministic for test cases
|
||||
func Machine(name, pubKey string, prvKey string, address string) machinetypes.Machine {
|
||||
metadata := Metadata()
|
||||
_, liquidPubKey := ExtendedKeyPair(config.LiquidNetParams)
|
||||
_, planetmintPubKey := ExtendedKeyPair(config.PlmntNetParams)
|
||||
|
||||
prvKeyBytes, _ := hex.DecodeString(prvKey)
|
||||
sk := &secp256k1.PrivKey{Key: prvKeyBytes}
|
||||
pubKeyBytes, _ := hex.DecodeString(pubKey)
|
||||
sign, _ := sk.Sign(pubKeyBytes)
|
||||
signatureHex := hex.EncodeToString(sign)
|
||||
|
||||
if address == "" {
|
||||
address = sample.Secp256k1AccAddress().String()
|
||||
}
|
||||
|
||||
m := machinetypes.Machine{
|
||||
Name: name,
|
||||
Ticker: name + "_ticker",
|
||||
Domain: "testnet-assets.rddl.iok",
|
||||
Reissue: true,
|
||||
Amount: 1000,
|
||||
Precision: 8,
|
||||
IssuerPlanetmint: planetmintPubKey,
|
||||
IssuerLiquid: liquidPubKey,
|
||||
MachineId: pubKey,
|
||||
Metadata: &metadata,
|
||||
Type: 1,
|
||||
MachineIdSignature: signatureHex,
|
||||
Address: address,
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func MachineRandom(name, pubKey string, prvKey string, address string, random int) machinetypes.Machine {
|
||||
metadata := Metadata()
|
||||
_, liquidPubKey := ExtendedKeyPair(config.LiquidNetParams)
|
||||
_, planetmintPubKey := ExtendedKeyPair(config.PlmntNetParams)
|
||||
|
||||
prvKeyBytes, _ := hex.DecodeString(prvKey)
|
||||
sk := &secp256k1.PrivKey{Key: prvKeyBytes}
|
||||
pubKeyBytes, _ := hex.DecodeString(pubKey)
|
||||
sign, _ := sk.Sign(pubKeyBytes)
|
||||
signatureHex := hex.EncodeToString(sign)
|
||||
|
||||
if address == "" {
|
||||
address = sample.Secp256k1AccAddress().String()
|
||||
}
|
||||
|
||||
m := machinetypes.Machine{
|
||||
Name: name + strconv.Itoa(random),
|
||||
Ticker: name + strconv.Itoa(random) + "_ticker",
|
||||
Domain: "testnet-assets.rddl.io",
|
||||
Reissue: true,
|
||||
Amount: 1000,
|
||||
Precision: 8,
|
||||
IssuerPlanetmint: planetmintPubKey,
|
||||
IssuerLiquid: liquidPubKey,
|
||||
MachineId: pubKey,
|
||||
Metadata: &metadata,
|
||||
Type: 1,
|
||||
MachineIdSignature: signatureHex,
|
||||
Address: address,
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func MachineIndex(pubKey string, planetmintPubKey string, liquidPubKey string) machinetypes.MachineIndex {
|
||||
return machinetypes.MachineIndex{
|
||||
MachineId: pubKey,
|
||||
IssuerPlanetmint: planetmintPubKey,
|
||||
IssuerLiquid: liquidPubKey,
|
||||
}
|
||||
}
|
||||
|
||||
func Metadata() machinetypes.Metadata {
|
||||
return machinetypes.Metadata{
|
||||
Gps: "{\"Latitude\":\"-48.876667\",\"Longitude\":\"-123.393333\"}",
|
||||
Device: "{\"Manufacturer\": \"RDDL\",\"Serial\":\"AdnT2uyt\"}",
|
||||
AssetDefinition: "{\"Version\": \"0.1\"}",
|
||||
AdditionalDataCID: "CID",
|
||||
}
|
||||
}
|
||||
|
||||
func TrustAnchor(pubkey string) machinetypes.TrustAnchor {
|
||||
return machinetypes.TrustAnchor{
|
||||
Pubkey: pubkey,
|
||||
}
|
||||
}
|
||||
|
||||
func MintRequest(beneficiaryAddr string, amount uint64, txhash string) daotypes.MintRequest {
|
||||
return daotypes.MintRequest{
|
||||
Beneficiary: beneficiaryAddr,
|
||||
Amount: amount,
|
||||
LiquidTxHash: txhash,
|
||||
}
|
||||
}
|
137
testutil/network/loader.go
Normal file
137
testutil/network/loader.go
Normal file
@ -0,0 +1,137 @@
|
||||
package network
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
tmdb "github.com/cometbft/cometbft-db"
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/hd"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
servertypes "github.com/cosmos/cosmos-sdk/server/types"
|
||||
pruningtypes "github.com/cosmos/cosmos-sdk/store/pruning/types"
|
||||
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/planetmint/planetmint-go/app"
|
||||
"github.com/planetmint/planetmint-go/clients/claim"
|
||||
"github.com/planetmint/planetmint-go/clients/shamir/coordinator"
|
||||
"github.com/planetmint/planetmint-go/monitor"
|
||||
monitormocks "github.com/planetmint/planetmint-go/monitor/mocks"
|
||||
clientmocks "github.com/planetmint/planetmint-go/testutil/mocks"
|
||||
"github.com/planetmint/planetmint-go/testutil/sample"
|
||||
"github.com/planetmint/planetmint-go/util"
|
||||
"github.com/planetmint/planetmint-go/util/mocks"
|
||||
elements "github.com/rddl-network/elements-rpc"
|
||||
elementsmocks "github.com/rddl-network/elements-rpc/utils/mocks"
|
||||
rcctypes "github.com/rddl-network/rddl-claim-service/types"
|
||||
scctypes "github.com/rddl-network/shamir-coordinator-service/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// Load creates instance with fully configured cosmos network.
|
||||
// Accepts optional config, that will be used in place of the DefaultConfig() if provided.
|
||||
func Load(t *testing.T, configs ...Config) *Network {
|
||||
if len(configs) > 1 {
|
||||
panic("at most one config should be provided")
|
||||
}
|
||||
var cfg Config
|
||||
if len(configs) == 0 {
|
||||
cfg = LoaderDefaultConfig()
|
||||
} else {
|
||||
cfg = configs[0]
|
||||
}
|
||||
validatorTmpDir := t.TempDir()
|
||||
|
||||
// use mock client for testing
|
||||
util.MQTTClient = &mocks.MockMQTTClient{}
|
||||
monitor.MonitorMQTTClient = &mocks.MockMQTTClient{}
|
||||
monitor.SetMqttMonitorInstance(&monitormocks.MockMQTTMonitorClientI{})
|
||||
elements.Client = &elementsmocks.MockClient{}
|
||||
util.RegisterAssetServiceHTTPClient = &mocks.MockClient{}
|
||||
ctrl := gomock.NewController(t)
|
||||
claimMock := clientmocks.NewMockIRCClient(ctrl)
|
||||
claimMock.EXPECT().PostClaim(gomock.Any(), gomock.Any()).AnyTimes().Return(rcctypes.PostClaimResponse{
|
||||
TxID: "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
}, nil)
|
||||
claim.RCClient = claimMock
|
||||
|
||||
shamirMock := clientmocks.NewMockISCClient(ctrl)
|
||||
shamirMock.EXPECT().SendTokens(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(scctypes.SendTokensResponse{
|
||||
TxID: "7add40beb27df701e02ee85089c5bc0021bc813823fedb5f1dcb5debda7f3da9",
|
||||
}, nil)
|
||||
shamirMock.EXPECT().ReIssueAsset(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(scctypes.ReIssueResponse{
|
||||
TxID: "7add40beb27df701e02ee85089c5bc0021bc813823fedb5f1dcb5debda7f3da9",
|
||||
}, nil)
|
||||
shamirMock.EXPECT().IssueMachineNFT(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(scctypes.IssueMachineNFTResponse{
|
||||
HexTX: "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
Contract: `{"entity":{"domain":"testnet-assets.rddl.io"}, "issuer_pubkey":"02", "machine_addr":"addr","name":"machine","precicion":8,"version":1}`,
|
||||
Asset: "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
}, nil)
|
||||
coordinator.SCClient = shamirMock
|
||||
|
||||
// enable application logger in tests
|
||||
appLogger := util.GetAppLogger()
|
||||
appLogger.SetTestingLogger(t)
|
||||
|
||||
net, err := New(t, validatorTmpDir, cfg)
|
||||
// this is only done to support multi validator test
|
||||
// race conditions(load/unload) on the CI
|
||||
if err != nil && strings.Contains(err.Error(), "bind: address already in use") {
|
||||
net, err = New(t, validatorTmpDir, cfg)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = net.WaitForHeight(1)
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(net.Cleanup)
|
||||
return net
|
||||
}
|
||||
|
||||
// LoaderDefaultConfig will initialize config for the network with custom application,
|
||||
// genesis and single validator. All other parameters are inherited from cosmos-sdk/testutil/network.DefaultConfig
|
||||
func LoaderDefaultConfig() Config {
|
||||
var (
|
||||
encoding = app.MakeEncodingConfig()
|
||||
chainID = "chain-foobarbaz"
|
||||
)
|
||||
return Config{
|
||||
Codec: encoding.Marshaler,
|
||||
TxConfig: encoding.TxConfig,
|
||||
LegacyAmino: encoding.Amino,
|
||||
InterfaceRegistry: encoding.InterfaceRegistry,
|
||||
AccountRetriever: authtypes.AccountRetriever{},
|
||||
AppConstructor: func(val ValidatorI) servertypes.Application {
|
||||
return app.New(
|
||||
val.GetCtx().Logger,
|
||||
tmdb.NewMemDB(),
|
||||
nil,
|
||||
true,
|
||||
map[int64]bool{},
|
||||
val.GetCtx().Config.RootDir,
|
||||
0,
|
||||
encoding,
|
||||
simtestutil.EmptyAppOptions{},
|
||||
baseapp.SetPruning(pruningtypes.NewPruningOptionsFromString(val.GetAppConfig().Pruning)),
|
||||
baseapp.SetMinGasPrices(val.GetAppConfig().MinGasPrices),
|
||||
baseapp.SetChainID(chainID),
|
||||
)
|
||||
},
|
||||
GenesisState: app.ModuleBasics.DefaultGenesis(encoding.Marshaler),
|
||||
TimeoutCommit: 2 * time.Second,
|
||||
ChainID: chainID,
|
||||
NumValidators: 1,
|
||||
BondDenom: sdk.DefaultBondDenom,
|
||||
MinGasPrices: "0.000003" + sample.FeeDenom,
|
||||
AccountTokens: sdk.TokensFromConsensusPower(10000, sdk.DefaultPowerReduction),
|
||||
StakingTokens: sdk.TokensFromConsensusPower(500, sdk.DefaultPowerReduction),
|
||||
BondedTokens: sdk.TokensFromConsensusPower(100, sdk.DefaultPowerReduction),
|
||||
PruningStrategy: pruningtypes.PruningOptionNothing,
|
||||
CleanupDir: true,
|
||||
SigningAlgo: string(hd.Secp256k1Type),
|
||||
KeyringOptions: []keyring.Option{},
|
||||
AccountDenom: sample.FeeDenom,
|
||||
}
|
||||
}
|
@ -1,101 +1,829 @@
|
||||
package network
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
tmdb "github.com/cometbft/cometbft-db"
|
||||
dbm "github.com/cometbft/cometbft-db"
|
||||
tmrand "github.com/cometbft/cometbft/libs/rand"
|
||||
"github.com/cometbft/cometbft/node"
|
||||
tmclient "github.com/cometbft/cometbft/rpc/client"
|
||||
"github.com/planetmint/planetmint-go/config"
|
||||
"github.com/planetmint/planetmint-go/lib"
|
||||
"github.com/planetmint/planetmint-go/testutil/sample"
|
||||
"github.com/planetmint/planetmint-go/util"
|
||||
"github.com/spf13/cobra"
|
||||
"google.golang.org/grpc"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
tmlog "github.com/cometbft/cometbft/libs/log"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/configurator"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||
|
||||
"cosmossdk.io/depinject"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/client/grpc/tmservice"
|
||||
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/hd"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
"github.com/cosmos/cosmos-sdk/runtime"
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
"github.com/cosmos/cosmos-sdk/server/api"
|
||||
srvconfig "github.com/cosmos/cosmos-sdk/server/config"
|
||||
servertypes "github.com/cosmos/cosmos-sdk/server/types"
|
||||
pruningtypes "github.com/cosmos/cosmos-sdk/store/pruning/types"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/network"
|
||||
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/planetmint/planetmint-go/app"
|
||||
"github.com/planetmint/planetmint-go/config"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/genutil"
|
||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
)
|
||||
|
||||
// package-wide network lock to only allow one test network at a time
|
||||
var lock = new(sync.Mutex)
|
||||
|
||||
// AppConstructor defines a function which accepts a network configuration and
|
||||
// creates an ABCI Application to provide to Tendermint.
|
||||
type (
|
||||
AppConstructor = func(val ValidatorI) servertypes.Application
|
||||
TestFixtureFactory = func() TestFixture
|
||||
)
|
||||
|
||||
type TestFixture struct {
|
||||
AppConstructor AppConstructor
|
||||
GenesisState map[string]json.RawMessage
|
||||
EncodingConfig moduletestutil.TestEncodingConfig
|
||||
}
|
||||
|
||||
// Config defines the necessary configuration used to bootstrap and start an
|
||||
// in-process local testing network.
|
||||
type Config struct {
|
||||
Codec codec.Codec
|
||||
LegacyAmino *codec.LegacyAmino // TODO: Remove!
|
||||
InterfaceRegistry codectypes.InterfaceRegistry
|
||||
|
||||
TxConfig client.TxConfig
|
||||
AccountRetriever client.AccountRetriever
|
||||
AppConstructor AppConstructor // the ABCI application constructor
|
||||
GenesisState map[string]json.RawMessage // custom genesis state to provide
|
||||
TimeoutCommit time.Duration // the consensus commitment timeout
|
||||
ChainID string // the network chain-id
|
||||
NumValidators int // the total number of validators to create and bond
|
||||
Mnemonics []string // custom user-provided validator operator mnemonics
|
||||
BondDenom string // the staking bond denomination
|
||||
MinGasPrices string // the minimum gas prices each validator will accept
|
||||
AccountTokens math.Int // the amount of unique validator tokens (e.g. 1000node0)
|
||||
StakingTokens math.Int // the amount of tokens each validator has available to stake
|
||||
BondedTokens math.Int // the amount of tokens each validator stakes
|
||||
PruningStrategy string // the pruning strategy each validator will have
|
||||
EnableTMLogging bool // enable Tendermint logging to STDOUT
|
||||
CleanupDir bool // remove base temporary directory during cleanup
|
||||
SigningAlgo string // signing algorithm for keys
|
||||
KeyringOptions []keyring.Option // keyring configuration options
|
||||
RPCAddress string // RPC listen address (including port)
|
||||
APIAddress string // REST API listen address (including port)
|
||||
GRPCAddress string // GRPC server listen address (including port)
|
||||
PrintMnemonic bool // print the mnemonic of first validator as log output for testing
|
||||
AccountDenom string // the denominator of the account tokens
|
||||
}
|
||||
|
||||
// DefaultConfig returns a sane default configuration suitable for nearly all
|
||||
// testing requirements.
|
||||
func DefaultConfig(factory TestFixtureFactory) Config {
|
||||
fixture := factory()
|
||||
|
||||
return Config{
|
||||
Codec: fixture.EncodingConfig.Codec,
|
||||
TxConfig: fixture.EncodingConfig.TxConfig,
|
||||
LegacyAmino: fixture.EncodingConfig.Amino,
|
||||
InterfaceRegistry: fixture.EncodingConfig.InterfaceRegistry,
|
||||
AccountRetriever: authtypes.AccountRetriever{},
|
||||
AppConstructor: fixture.AppConstructor,
|
||||
GenesisState: fixture.GenesisState,
|
||||
TimeoutCommit: 2 * time.Second,
|
||||
ChainID: "chain-" + tmrand.Str(6),
|
||||
NumValidators: 4,
|
||||
BondDenom: sdk.DefaultBondDenom,
|
||||
MinGasPrices: "0.000006" + sample.FeeDenom,
|
||||
AccountTokens: sdk.TokensFromConsensusPower(1000, sdk.DefaultPowerReduction),
|
||||
StakingTokens: sdk.TokensFromConsensusPower(500, sdk.DefaultPowerReduction),
|
||||
BondedTokens: sdk.TokensFromConsensusPower(100, sdk.DefaultPowerReduction),
|
||||
PruningStrategy: pruningtypes.PruningOptionNothing,
|
||||
CleanupDir: true,
|
||||
SigningAlgo: string(hd.Secp256k1Type),
|
||||
KeyringOptions: []keyring.Option{},
|
||||
PrintMnemonic: false,
|
||||
AccountDenom: sample.FeeDenom,
|
||||
}
|
||||
}
|
||||
|
||||
// MinimumAppConfig defines the minimum of modules required for a call to New to succeed
|
||||
func MinimumAppConfig() depinject.Config {
|
||||
return configurator.NewAppConfig(
|
||||
configurator.AuthModule(),
|
||||
configurator.ParamsModule(),
|
||||
configurator.BankModule(),
|
||||
configurator.GenutilModule(),
|
||||
configurator.StakingModule(),
|
||||
configurator.ConsensusModule(),
|
||||
configurator.TxModule())
|
||||
}
|
||||
|
||||
func DefaultConfigWithAppConfig(appConfig depinject.Config) (Config, error) {
|
||||
var (
|
||||
appBuilder *runtime.AppBuilder
|
||||
txConfig client.TxConfig
|
||||
legacyAmino *codec.LegacyAmino
|
||||
cdc codec.Codec
|
||||
interfaceRegistry codectypes.InterfaceRegistry
|
||||
)
|
||||
|
||||
if err := depinject.Inject(appConfig,
|
||||
&appBuilder,
|
||||
&txConfig,
|
||||
&cdc,
|
||||
&legacyAmino,
|
||||
&interfaceRegistry,
|
||||
); err != nil {
|
||||
return Config{}, err
|
||||
}
|
||||
|
||||
cfg := DefaultConfig(func() TestFixture {
|
||||
return TestFixture{}
|
||||
})
|
||||
cfg.Codec = cdc
|
||||
cfg.TxConfig = txConfig
|
||||
cfg.LegacyAmino = legacyAmino
|
||||
cfg.InterfaceRegistry = interfaceRegistry
|
||||
cfg.GenesisState = appBuilder.DefaultGenesis()
|
||||
cfg.AppConstructor = func(val ValidatorI) servertypes.Application {
|
||||
// we build a unique app instance for every validator here
|
||||
var appBuilder *runtime.AppBuilder
|
||||
if err := depinject.Inject(appConfig, &appBuilder); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
app := appBuilder.Build(
|
||||
val.GetCtx().Logger,
|
||||
dbm.NewMemDB(),
|
||||
nil,
|
||||
baseapp.SetPruning(pruningtypes.NewPruningOptionsFromString(val.GetAppConfig().Pruning)),
|
||||
baseapp.SetMinGasPrices(val.GetAppConfig().MinGasPrices),
|
||||
baseapp.SetChainID(cfg.ChainID),
|
||||
)
|
||||
|
||||
testdata.RegisterQueryServer(app.GRPCQueryRouter(), testdata.QueryImpl{})
|
||||
|
||||
if err := app.Load(true); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return app
|
||||
}
|
||||
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
type (
|
||||
Network = network.Network
|
||||
Config = network.Config
|
||||
// Network defines a local in-process testing network using SimApp. It can be
|
||||
// configured to start any number of validators, each with its own RPC and API
|
||||
// clients. Typically, this test network would be used in client and integration
|
||||
// testing where user input is expected.
|
||||
//
|
||||
// Note, due to Tendermint constraints in regards to RPC functionality, there
|
||||
// may only be one test network running at a time. Thus, any caller must be
|
||||
// sure to Cleanup after testing is finished in order to allow other tests
|
||||
// to create networks. In addition, only the first validator will have a valid
|
||||
// RPC and API server/client.
|
||||
Network struct {
|
||||
Logger Logger
|
||||
BaseDir string
|
||||
Validators []*Validator
|
||||
|
||||
Config Config
|
||||
}
|
||||
|
||||
// Validator defines an in-process Tendermint validator node. Through this object,
|
||||
// a client can make RPC and API calls and interact with any client command
|
||||
// or handler.
|
||||
Validator struct {
|
||||
AppConfig *srvconfig.Config
|
||||
ClientCtx client.Context
|
||||
Ctx *server.Context
|
||||
Dir string
|
||||
NodeID string
|
||||
PubKey cryptotypes.PubKey
|
||||
Moniker string
|
||||
APIAddress string
|
||||
RPCAddress string
|
||||
P2PAddress string
|
||||
Address sdk.AccAddress
|
||||
ValAddress sdk.ValAddress
|
||||
RPCClient tmclient.Client
|
||||
|
||||
tmNode *node.Node
|
||||
api *api.Server
|
||||
grpc *grpc.Server
|
||||
grpcWeb *http.Server
|
||||
}
|
||||
|
||||
// ValidatorI expose a validator's context and configuration
|
||||
ValidatorI interface {
|
||||
GetCtx() *server.Context
|
||||
GetAppConfig() *srvconfig.Config
|
||||
}
|
||||
|
||||
// Logger is a network logger interface that exposes testnet-level Log() methods for an in-process testing network
|
||||
// This is not to be confused with logging that may happen at an individual node or validator level
|
||||
Logger interface {
|
||||
Log(args ...interface{})
|
||||
Logf(format string, args ...interface{})
|
||||
}
|
||||
)
|
||||
|
||||
// New creates instance with fully configured cosmos network.
|
||||
// Accepts optional config, that will be used in place of the DefaultConfig() if provided.
|
||||
func New(t *testing.T, configs ...Config) *Network {
|
||||
if len(configs) > 1 {
|
||||
panic("at most one config should be provided")
|
||||
}
|
||||
var cfg network.Config
|
||||
if len(configs) == 0 {
|
||||
cfg = DefaultConfig()
|
||||
} else {
|
||||
cfg = configs[0]
|
||||
}
|
||||
validatorTmpDir := t.TempDir()
|
||||
var (
|
||||
_ Logger = (*testing.T)(nil)
|
||||
_ Logger = (*CLILogger)(nil)
|
||||
_ ValidatorI = Validator{}
|
||||
)
|
||||
|
||||
// set the proper root dir for the test environment so that the abci.go logic works
|
||||
appConfig := config.GetConfig()
|
||||
appConfig.SetRoot(validatorTmpDir + "/node0/simd")
|
||||
|
||||
net, err := network.New(t, validatorTmpDir, cfg)
|
||||
|
||||
appConfig.ValidatorAddress = net.Validators[0].Address.String()
|
||||
|
||||
require.NoError(t, err)
|
||||
_, err = net.WaitForHeight(1)
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(net.Cleanup)
|
||||
return net
|
||||
func (v Validator) GetCtx() *server.Context {
|
||||
return v.Ctx
|
||||
}
|
||||
|
||||
// DefaultConfig will initialize config for the network with custom application,
|
||||
// genesis and single validator. All other parameters are inherited from cosmos-sdk/testutil/network.DefaultConfig
|
||||
func DefaultConfig() network.Config {
|
||||
func (v Validator) GetAppConfig() *srvconfig.Config {
|
||||
return v.AppConfig
|
||||
}
|
||||
|
||||
// CLILogger wraps a cobra.Command and provides command logging methods.
|
||||
type CLILogger struct {
|
||||
cmd *cobra.Command
|
||||
}
|
||||
|
||||
// Log logs given args.
|
||||
func (s CLILogger) Log(args ...interface{}) {
|
||||
s.cmd.Println(args...)
|
||||
}
|
||||
|
||||
// Logf logs given args according to a format specifier.
|
||||
func (s CLILogger) Logf(format string, args ...interface{}) {
|
||||
s.cmd.Printf(format, args...)
|
||||
}
|
||||
|
||||
// NewCLILogger creates a new CLILogger.
|
||||
func NewCLILogger(cmd *cobra.Command) CLILogger {
|
||||
return CLILogger{cmd}
|
||||
}
|
||||
|
||||
// New creates a new Network for integration tests or in-process testnets run via the CLI
|
||||
func New(l Logger, baseDir string, cfg Config) (*Network, error) {
|
||||
// only one caller/test can create and use a network at a time
|
||||
l.Log("acquiring test network lock")
|
||||
lock.Lock()
|
||||
|
||||
network := &Network{
|
||||
Logger: l,
|
||||
BaseDir: baseDir,
|
||||
Validators: make([]*Validator, cfg.NumValidators),
|
||||
Config: cfg,
|
||||
}
|
||||
|
||||
l.Logf("preparing test network with chain-id \"%s\"\n", cfg.ChainID)
|
||||
|
||||
monikers := make([]string, cfg.NumValidators)
|
||||
nodeIDs := make([]string, cfg.NumValidators)
|
||||
valPubKeys := make([]cryptotypes.PubKey, cfg.NumValidators)
|
||||
|
||||
var (
|
||||
encoding = app.MakeEncodingConfig()
|
||||
chainID = "chain-foobarbaz"
|
||||
genAccounts []authtypes.GenesisAccount
|
||||
genBalances []banktypes.Balance
|
||||
genFiles []string
|
||||
)
|
||||
return network.Config{
|
||||
Codec: encoding.Marshaler,
|
||||
TxConfig: encoding.TxConfig,
|
||||
LegacyAmino: encoding.Amino,
|
||||
InterfaceRegistry: encoding.InterfaceRegistry,
|
||||
AccountRetriever: authtypes.AccountRetriever{},
|
||||
AppConstructor: func(val network.ValidatorI) servertypes.Application {
|
||||
return app.New(
|
||||
val.GetCtx().Logger,
|
||||
tmdb.NewMemDB(),
|
||||
nil,
|
||||
true,
|
||||
map[int64]bool{},
|
||||
val.GetCtx().Config.RootDir,
|
||||
0,
|
||||
encoding,
|
||||
simtestutil.EmptyAppOptions{},
|
||||
baseapp.SetPruning(pruningtypes.NewPruningOptionsFromString(val.GetAppConfig().Pruning)),
|
||||
baseapp.SetMinGasPrices(val.GetAppConfig().MinGasPrices),
|
||||
baseapp.SetChainID(chainID),
|
||||
)
|
||||
},
|
||||
GenesisState: app.ModuleBasics.DefaultGenesis(encoding.Marshaler),
|
||||
TimeoutCommit: 2 * time.Second,
|
||||
ChainID: chainID,
|
||||
NumValidators: 1,
|
||||
BondDenom: sdk.DefaultBondDenom,
|
||||
MinGasPrices: fmt.Sprintf("0.000003%s", sdk.DefaultBondDenom),
|
||||
AccountTokens: sdk.TokensFromConsensusPower(1000, sdk.DefaultPowerReduction),
|
||||
StakingTokens: sdk.TokensFromConsensusPower(500, sdk.DefaultPowerReduction),
|
||||
BondedTokens: sdk.TokensFromConsensusPower(100, sdk.DefaultPowerReduction),
|
||||
PruningStrategy: pruningtypes.PruningOptionNothing,
|
||||
CleanupDir: true,
|
||||
SigningAlgo: string(hd.Secp256k1Type),
|
||||
KeyringOptions: []keyring.Option{},
|
||||
|
||||
buf := bufio.NewReader(os.Stdin)
|
||||
|
||||
// generate private keys, node IDs, and initial transactions
|
||||
for i := 0; i < cfg.NumValidators; i++ {
|
||||
appCfg := srvconfig.DefaultConfig()
|
||||
appCfg.Pruning = cfg.PruningStrategy
|
||||
appCfg.MinGasPrices = cfg.MinGasPrices
|
||||
appCfg.API.Enable = true
|
||||
appCfg.API.Swagger = false
|
||||
appCfg.Telemetry.Enabled = false
|
||||
|
||||
ctx := server.NewDefaultContext()
|
||||
tmCfg := ctx.Config
|
||||
tmCfg.Consensus.TimeoutCommit = cfg.TimeoutCommit
|
||||
tmCfg.Consensus.TimeoutPrecommit = cfg.TimeoutCommit
|
||||
tmCfg.Consensus.TimeoutPrevote = cfg.TimeoutCommit
|
||||
tmCfg.Consensus.TimeoutPropose = cfg.TimeoutCommit
|
||||
|
||||
// Only allow the first validator to expose an RPC, API and gRPC
|
||||
// server/client due to Tendermint in-process constraints.
|
||||
apiAddr := ""
|
||||
tmCfg.RPC.ListenAddress = ""
|
||||
appCfg.GRPC.Enable = false
|
||||
appCfg.GRPCWeb.Enable = false
|
||||
apiListenAddr := ""
|
||||
if i == 0 {
|
||||
if cfg.APIAddress != "" {
|
||||
apiListenAddr = cfg.APIAddress
|
||||
} else {
|
||||
var err error
|
||||
apiListenAddr, _, err = server.FreeTCPAddr()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
appCfg.API.Address = apiListenAddr
|
||||
apiURL, err := url.Parse(apiListenAddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
apiAddr = net.JoinHostPort("http://"+apiURL.Hostname(), apiURL.Port())
|
||||
|
||||
if cfg.RPCAddress != "" {
|
||||
// The above code is likely declaring a variable or constant named "tmCfg" in the Go programming
|
||||
// language. However, without more context or code, it is difficult to determine the exact purpose
|
||||
// or functionality of this code.
|
||||
tmCfg.RPC.ListenAddress = cfg.RPCAddress
|
||||
} else {
|
||||
rpcAddr, _, err := server.FreeTCPAddr()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tmCfg.RPC.ListenAddress = rpcAddr
|
||||
}
|
||||
|
||||
if cfg.GRPCAddress != "" {
|
||||
appCfg.GRPC.Address = cfg.GRPCAddress
|
||||
} else {
|
||||
_, grpcPort, err := server.FreeTCPAddr()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
appCfg.GRPC.Address = "0.0.0.0:" + grpcPort
|
||||
}
|
||||
appCfg.GRPC.Enable = true
|
||||
|
||||
_, grpcWebPort, err := server.FreeTCPAddr()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
appCfg.GRPCWeb.Address = "0.0.0.0:" + grpcWebPort
|
||||
appCfg.GRPCWeb.Enable = true
|
||||
}
|
||||
|
||||
logger := tmlog.NewNopLogger()
|
||||
if cfg.EnableTMLogging {
|
||||
logger = tmlog.NewTMLogger(tmlog.NewSyncWriter(os.Stdout))
|
||||
}
|
||||
|
||||
ctx.Logger = logger
|
||||
|
||||
nodeDirName := fmt.Sprintf("node%d", i)
|
||||
nodeDir := filepath.Join(network.BaseDir, nodeDirName, "simd")
|
||||
clientDir := filepath.Join(network.BaseDir, nodeDirName, "simcli")
|
||||
gentxsDir := filepath.Join(network.BaseDir, "gentxs")
|
||||
|
||||
err := os.MkdirAll(filepath.Join(nodeDir, "config"), 0o755)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = os.MkdirAll(clientDir, 0o755)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tmCfg.SetRoot(nodeDir)
|
||||
tmCfg.Moniker = nodeDirName
|
||||
monikers[i] = nodeDirName
|
||||
|
||||
proxyAddr, _, err := server.FreeTCPAddr()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tmCfg.ProxyApp = proxyAddr
|
||||
|
||||
p2pAddr, _, err := server.FreeTCPAddr()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tmCfg.P2P.ListenAddress = p2pAddr
|
||||
tmCfg.P2P.AddrBookStrict = false
|
||||
tmCfg.P2P.AllowDuplicateIP = true
|
||||
|
||||
nodeID, pubKey, err := genutil.InitializeNodeValidatorFiles(tmCfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nodeIDs[i] = nodeID
|
||||
valPubKeys[i] = pubKey
|
||||
|
||||
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, clientDir, buf, cfg.Codec, cfg.KeyringOptions...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
keyringAlgos, _ := kb.SupportedAlgorithms()
|
||||
algo, err := keyring.NewSigningAlgoFromString(cfg.SigningAlgo, keyringAlgos)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var mnemonic string
|
||||
if i < len(cfg.Mnemonics) {
|
||||
mnemonic = cfg.Mnemonics[i]
|
||||
}
|
||||
|
||||
addr, secret, err := testutil.GenerateSaveCoinKey(kb, nodeDirName, mnemonic, true, algo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// if PrintMnemonic is set to true, we print the first validator node's secret to the network's logger
|
||||
// for debugging and manual testing
|
||||
if cfg.PrintMnemonic && i == 0 {
|
||||
printMnemonic(l, secret)
|
||||
}
|
||||
|
||||
info := map[string]string{"secret": secret}
|
||||
infoBz, err := json.Marshal(info)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// save private key seed words
|
||||
err = writeFile(fmt.Sprintf("%v.json", "key_seed"), clientDir, infoBz)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
balances := sdk.NewCoins(
|
||||
sdk.NewCoin(cfg.AccountDenom, cfg.AccountTokens),
|
||||
sdk.NewCoin(cfg.BondDenom, cfg.StakingTokens),
|
||||
)
|
||||
|
||||
genFiles = append(genFiles, tmCfg.GenesisFile())
|
||||
genBalances = append(genBalances, banktypes.Balance{Address: addr.String(), Coins: balances.Sort()})
|
||||
genAccounts = append(genAccounts, authtypes.NewBaseAccount(addr, nil, 0, 0))
|
||||
|
||||
commission, err := sdk.NewDecFromStr("0.5")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
createValMsg, err := stakingtypes.NewMsgCreateValidator(
|
||||
sdk.ValAddress(addr),
|
||||
valPubKeys[i],
|
||||
sdk.NewCoin(cfg.BondDenom, cfg.BondedTokens),
|
||||
stakingtypes.NewDescription(nodeDirName, "", "", "", ""),
|
||||
stakingtypes.NewCommissionRates(commission, math.LegacyOneDec(), math.LegacyOneDec()),
|
||||
math.OneInt(),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
p2pURL, err := url.Parse(p2pAddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
memo := fmt.Sprintf("%s@%s:%s", nodeIDs[i], p2pURL.Hostname(), p2pURL.Port())
|
||||
fee := sdk.NewCoins(sdk.NewCoin(cfg.AccountDenom, sdk.NewInt(0)))
|
||||
txBuilder := cfg.TxConfig.NewTxBuilder()
|
||||
err = txBuilder.SetMsgs(createValMsg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
txBuilder.SetFeeAmount(fee) // Arbitrary fee
|
||||
txBuilder.SetGasLimit(1000000) // Need at least 100386
|
||||
txBuilder.SetMemo(memo)
|
||||
|
||||
txFactory := tx.Factory{}
|
||||
txFactory = txFactory.
|
||||
WithChainID(cfg.ChainID).
|
||||
WithMemo(memo).
|
||||
WithKeybase(kb).
|
||||
WithTxConfig(cfg.TxConfig)
|
||||
|
||||
err = tx.Sign(txFactory, nodeDirName, txBuilder, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
txBz, err := cfg.TxConfig.TxJSONEncoder()(txBuilder.GetTx())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = writeFile(fmt.Sprintf("%v.json", nodeDirName), gentxsDir, txBz)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
srvconfig.WriteConfigFile(filepath.Join(nodeDir, "config", "app.toml"), appCfg)
|
||||
|
||||
clientCtx := client.Context{}.
|
||||
WithKeyringDir(clientDir).
|
||||
WithKeyring(kb).
|
||||
WithHomeDir(tmCfg.RootDir).
|
||||
WithChainID(cfg.ChainID).
|
||||
WithInterfaceRegistry(cfg.InterfaceRegistry).
|
||||
WithCodec(cfg.Codec).
|
||||
WithLegacyAmino(cfg.LegacyAmino).
|
||||
WithTxConfig(cfg.TxConfig).
|
||||
WithAccountRetriever(cfg.AccountRetriever)
|
||||
|
||||
// Provide ChainID here since we can't modify it in the Comet config.
|
||||
ctx.Viper.Set(flags.FlagChainID, cfg.ChainID)
|
||||
|
||||
network.Validators[i] = &Validator{
|
||||
AppConfig: appCfg,
|
||||
ClientCtx: clientCtx,
|
||||
Ctx: ctx,
|
||||
Dir: filepath.Join(network.BaseDir, nodeDirName),
|
||||
NodeID: nodeID,
|
||||
PubKey: pubKey,
|
||||
Moniker: nodeDirName,
|
||||
RPCAddress: tmCfg.RPC.ListenAddress,
|
||||
P2PAddress: tmCfg.P2P.ListenAddress,
|
||||
APIAddress: apiAddr,
|
||||
Address: addr,
|
||||
ValAddress: sdk.ValAddress(addr),
|
||||
}
|
||||
}
|
||||
|
||||
err := initGenFiles(cfg, genAccounts, genBalances, genFiles)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = collectGenFiles(cfg, network.Validators, network.BaseDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
l.Log("starting test network...")
|
||||
for idx, v := range network.Validators {
|
||||
err := startInProcess(cfg, v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
l.Log("started validator", idx)
|
||||
if idx == 0 {
|
||||
os.Setenv(config.ValAddr, network.Validators[0].Address.String())
|
||||
// set missing validator client context values for sending txs
|
||||
var output bytes.Buffer
|
||||
network.Validators[0].ClientCtx.BroadcastMode = "sync"
|
||||
network.Validators[0].ClientCtx.FromAddress = network.Validators[0].Address
|
||||
network.Validators[0].ClientCtx.FromName = network.Validators[0].Moniker
|
||||
network.Validators[0].ClientCtx.NodeURI = network.Validators[0].RPCAddress
|
||||
network.Validators[0].ClientCtx.Output = &output
|
||||
network.Validators[0].ClientCtx.SkipConfirm = true
|
||||
|
||||
libConfig := lib.GetConfig()
|
||||
libConfig.SetClientCtx(network.Validators[0].ClientCtx)
|
||||
libConfig.SetRoot(network.Validators[0].ClientCtx.HomeDir)
|
||||
}
|
||||
}
|
||||
|
||||
height := int64(0)
|
||||
for height < 7 {
|
||||
height, err = network.LatestHeight()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
l.Log("started test network at height:", height)
|
||||
|
||||
// Ensure we cleanup incase any test was abruptly halted (e.g. SIGINT) as any
|
||||
// defer in a test would not be called.
|
||||
server.TrapSignal(network.Cleanup)
|
||||
|
||||
return network, nil
|
||||
}
|
||||
|
||||
// LatestHeight returns the latest height of the network or an error if the
|
||||
// query fails or no validators exist.
|
||||
func (n *Network) LatestHeight() (int64, error) {
|
||||
if len(n.Validators) == 0 {
|
||||
return 0, errors.New("no validators available")
|
||||
}
|
||||
|
||||
ticker := time.NewTicker(time.Second)
|
||||
defer ticker.Stop()
|
||||
|
||||
timeout := time.NewTimer(time.Second * 5)
|
||||
defer timeout.Stop()
|
||||
|
||||
var latestHeight int64
|
||||
val := n.Validators[0]
|
||||
queryClient := tmservice.NewServiceClient(val.ClientCtx)
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-timeout.C:
|
||||
return latestHeight, errors.New("timeout exceeded waiting for block")
|
||||
case <-ticker.C:
|
||||
res, err := queryClient.GetLatestBlock(context.Background(), &tmservice.GetLatestBlockRequest{})
|
||||
if err == nil && res != nil {
|
||||
return res.SdkBlock.Header.Height, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WaitForHeight performs a blocking check where it waits for a block to be
|
||||
// committed after a given block. If that height is not reached within a timeout,
|
||||
// an error is returned. Regardless, the latest height queried is returned.
|
||||
func (n *Network) WaitForHeight(h int64) (int64, error) {
|
||||
return n.WaitForHeightWithTimeout(h, 10*time.Second)
|
||||
}
|
||||
|
||||
// WaitForHeightWithTimeout is the same as WaitForHeight except the caller can
|
||||
// provide a custom timeout.
|
||||
func (n *Network) WaitForHeightWithTimeout(h int64, t time.Duration) (int64, error) {
|
||||
ticker := time.NewTicker(time.Second)
|
||||
defer ticker.Stop()
|
||||
|
||||
timeout := time.NewTimer(t)
|
||||
defer timeout.Stop()
|
||||
|
||||
if len(n.Validators) == 0 {
|
||||
return 0, errors.New("no validators available")
|
||||
}
|
||||
|
||||
var latestHeight int64
|
||||
val := n.Validators[0]
|
||||
queryClient := tmservice.NewServiceClient(val.ClientCtx)
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-timeout.C:
|
||||
return latestHeight, errors.New("timeout exceeded waiting for block")
|
||||
case <-ticker.C:
|
||||
|
||||
res, err := queryClient.GetLatestBlock(context.Background(), &tmservice.GetLatestBlockRequest{})
|
||||
if err == nil && res != nil {
|
||||
latestHeight = res.GetSdkBlock().Header.Height
|
||||
if latestHeight >= h {
|
||||
return latestHeight, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// RetryForBlocks will wait for the next block and execute the function provided.
|
||||
// It will do this until the function returns a nil error or until the number of
|
||||
// blocks has been reached.
|
||||
func (n *Network) RetryForBlocks(retryFunc func() error, blocks int) error {
|
||||
for i := 0; i < blocks; i++ {
|
||||
err := n.WaitForNextBlock()
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
err = retryFunc()
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
// we've reached the last block to wait, return the error
|
||||
if i == blocks-1 {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// WaitForNextBlock waits for the next block to be committed, returning an error
|
||||
// upon failure.
|
||||
func (n *Network) WaitForNextBlock() error {
|
||||
lastBlock, err := n.LatestHeight()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = n.WaitForHeight(lastBlock + 1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Cleanup removes the root testing (temporary) directory and stops both the
|
||||
// Tendermint and API services. It allows other callers to create and start
|
||||
// test networks. This method must be called when a test is finished, typically
|
||||
// in a defer.
|
||||
func (n *Network) Cleanup() {
|
||||
defer func() {
|
||||
lock.Unlock()
|
||||
n.Logger.Log("released test network lock")
|
||||
}()
|
||||
|
||||
n.Logger.Log("cleaning up test network...")
|
||||
n.Logger.Log("Stage 1 APIs...")
|
||||
for i := len(n.Validators) - 1; i >= 0; i-- {
|
||||
v := n.Validators[i]
|
||||
if v.api != nil {
|
||||
_ = v.api.Close()
|
||||
}
|
||||
|
||||
if v.grpc != nil {
|
||||
v.grpc.Stop()
|
||||
if v.grpcWeb != nil {
|
||||
_ = v.grpcWeb.Close()
|
||||
}
|
||||
}
|
||||
}
|
||||
n.Logger.Log("Stage 2 CometBFT...")
|
||||
for i := len(n.Validators) - 1; i >= 0; i-- {
|
||||
v := n.Validators[i]
|
||||
if v.tmNode != nil && v.tmNode.IsRunning() {
|
||||
_ = v.tmNode.Stop()
|
||||
}
|
||||
}
|
||||
|
||||
n.Logger.Log("Stage 3 Application Threads...")
|
||||
// waiting for all threads to be terminated
|
||||
util.TerminationWaitGroup.Wait()
|
||||
|
||||
// Give a brief pause for things to finish closing in other processes. Hopefully this helps with the address-in-use errors.
|
||||
// 100ms chosen randomly.
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
n.Logger.Log("Stage 4 Files...")
|
||||
if n.Config.CleanupDir {
|
||||
_ = os.RemoveAll(n.BaseDir)
|
||||
}
|
||||
|
||||
n.Logger.Log("finished cleaning up test network")
|
||||
}
|
||||
|
||||
// printMnemonic prints a provided mnemonic seed phrase on a network logger
|
||||
// for debugging and manual testing
|
||||
func printMnemonic(l Logger, secret string) {
|
||||
lines := []string{
|
||||
"THIS MNEMONIC IS FOR TESTING PURPOSES ONLY",
|
||||
"DO NOT USE IN PRODUCTION",
|
||||
"",
|
||||
strings.Join(strings.Fields(secret)[0:8], " "),
|
||||
strings.Join(strings.Fields(secret)[8:16], " "),
|
||||
strings.Join(strings.Fields(secret)[16:24], " "),
|
||||
}
|
||||
|
||||
lineLengths := make([]int, len(lines))
|
||||
for i, line := range lines {
|
||||
lineLengths[i] = len(line)
|
||||
}
|
||||
|
||||
maxLineLength := 0
|
||||
for _, lineLen := range lineLengths {
|
||||
if lineLen > maxLineLength {
|
||||
maxLineLength = lineLen
|
||||
}
|
||||
}
|
||||
|
||||
l.Log("\n")
|
||||
l.Log(strings.Repeat("+", maxLineLength+8))
|
||||
for _, line := range lines {
|
||||
l.Logf("++ %s ++\n", centerText(line, maxLineLength))
|
||||
}
|
||||
l.Log(strings.Repeat("+", maxLineLength+8))
|
||||
l.Log("\n")
|
||||
}
|
||||
|
||||
// centerText centers text across a fixed width, filling either side with whitespace buffers
|
||||
func centerText(text string, width int) string {
|
||||
textLen := len(text)
|
||||
leftBuffer := strings.Repeat(" ", (width-textLen)/2)
|
||||
rightBuffer := strings.Repeat(" ", (width-textLen)/2+(width-textLen)%2)
|
||||
|
||||
return fmt.Sprintf("%s%s%s", leftBuffer, text, rightBuffer)
|
||||
}
|
||||
|
204
testutil/network/util.go
Normal file
204
testutil/network/util.go
Normal file
@ -0,0 +1,204 @@
|
||||
package network
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/cometbft/cometbft/node"
|
||||
"github.com/cometbft/cometbft/p2p"
|
||||
pvm "github.com/cometbft/cometbft/privval"
|
||||
"github.com/cometbft/cometbft/proxy"
|
||||
"github.com/cometbft/cometbft/rpc/client/local"
|
||||
"github.com/cometbft/cometbft/types"
|
||||
tmtime "github.com/cometbft/cometbft/types/time"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/server/api"
|
||||
servergrpc "github.com/cosmos/cosmos-sdk/server/grpc"
|
||||
srvtypes "github.com/cosmos/cosmos-sdk/server/types"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/genutil"
|
||||
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
|
||||
)
|
||||
|
||||
func startInProcess(cfg Config, val *Validator) error {
|
||||
logger := val.Ctx.Logger
|
||||
tmCfg := val.Ctx.Config
|
||||
tmCfg.Instrumentation.Prometheus = false
|
||||
|
||||
if err := val.AppConfig.ValidateBasic(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nodeKey, err := p2p.LoadOrGenNodeKey(tmCfg.NodeKeyFile())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
app := cfg.AppConstructor(*val)
|
||||
genDocProvider := node.DefaultGenesisDocProviderFunc(tmCfg)
|
||||
|
||||
tmNode, err := node.NewNode( //resleak:notresource
|
||||
tmCfg,
|
||||
pvm.LoadOrGenFilePV(tmCfg.PrivValidatorKeyFile(), tmCfg.PrivValidatorStateFile()),
|
||||
nodeKey,
|
||||
proxy.NewLocalClientCreator(app),
|
||||
genDocProvider,
|
||||
node.DefaultDBProvider,
|
||||
node.DefaultMetricsProvider(tmCfg.Instrumentation),
|
||||
logger.With("module", val.Moniker),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := tmNode.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
val.tmNode = tmNode
|
||||
|
||||
if val.RPCAddress != "" {
|
||||
val.RPCClient = local.New(tmNode)
|
||||
}
|
||||
|
||||
// We'll need a RPC client if the validator exposes a gRPC or REST endpoint.
|
||||
if val.APIAddress != "" || val.AppConfig.GRPC.Enable {
|
||||
val.ClientCtx = val.ClientCtx.
|
||||
WithClient(val.RPCClient)
|
||||
|
||||
app.RegisterTxService(val.ClientCtx)
|
||||
app.RegisterTendermintService(val.ClientCtx)
|
||||
app.RegisterNodeService(val.ClientCtx)
|
||||
}
|
||||
|
||||
if val.APIAddress != "" {
|
||||
apiSrv := api.New(val.ClientCtx, logger.With("module", "api-server"))
|
||||
app.RegisterAPIRoutes(apiSrv, val.AppConfig.API)
|
||||
|
||||
errCh := make(chan error)
|
||||
|
||||
go func() {
|
||||
if err := apiSrv.Start(*val.AppConfig); err != nil {
|
||||
errCh <- err
|
||||
}
|
||||
}()
|
||||
|
||||
select {
|
||||
case err := <-errCh:
|
||||
return err
|
||||
case <-time.After(srvtypes.ServerStartTime): // assume server started successfully
|
||||
}
|
||||
|
||||
val.api = apiSrv
|
||||
}
|
||||
|
||||
if val.AppConfig.GRPC.Enable {
|
||||
grpcSrv, err := servergrpc.StartGRPCServer(val.ClientCtx, app, val.AppConfig.GRPC)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
val.grpc = grpcSrv
|
||||
|
||||
if val.AppConfig.GRPCWeb.Enable {
|
||||
val.grpcWeb, err = servergrpc.StartGRPCWeb(grpcSrv, *val.AppConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func collectGenFiles(cfg Config, vals []*Validator, outputDir string) error {
|
||||
genTime := tmtime.Now()
|
||||
|
||||
for i := 0; i < cfg.NumValidators; i++ {
|
||||
tmCfg := vals[i].Ctx.Config
|
||||
|
||||
nodeDir := filepath.Join(outputDir, vals[i].Moniker, "simd")
|
||||
gentxsDir := filepath.Join(outputDir, "gentxs")
|
||||
|
||||
tmCfg.Moniker = vals[i].Moniker
|
||||
tmCfg.SetRoot(nodeDir)
|
||||
|
||||
initCfg := genutiltypes.NewInitConfig(cfg.ChainID, gentxsDir, vals[i].NodeID, vals[i].PubKey)
|
||||
|
||||
genFile := tmCfg.GenesisFile()
|
||||
genDoc, err := types.GenesisDocFromFile(genFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
appState, err := genutil.GenAppStateFromConfig(cfg.Codec, cfg.TxConfig,
|
||||
tmCfg, initCfg, *genDoc, banktypes.GenesisBalancesIterator{}, genutiltypes.DefaultMessageValidator)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// overwrite each validator's genesis file to have a canonical genesis time
|
||||
if err := genutil.ExportGenesisFileWithTime(genFile, cfg.ChainID, nil, appState, genTime); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func initGenFiles(cfg Config, genAccounts []authtypes.GenesisAccount, genBalances []banktypes.Balance, genFiles []string) error {
|
||||
// set the accounts in the genesis state
|
||||
var authGenState authtypes.GenesisState
|
||||
cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[authtypes.ModuleName], &authGenState)
|
||||
|
||||
accounts, err := authtypes.PackAccounts(genAccounts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
authGenState.Accounts = append(authGenState.Accounts, accounts...)
|
||||
cfg.GenesisState[authtypes.ModuleName] = cfg.Codec.MustMarshalJSON(&authGenState)
|
||||
|
||||
// set the balances in the genesis state
|
||||
var bankGenState banktypes.GenesisState
|
||||
cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[banktypes.ModuleName], &bankGenState)
|
||||
|
||||
bankGenState.Balances = append(bankGenState.Balances, genBalances...)
|
||||
cfg.GenesisState[banktypes.ModuleName] = cfg.Codec.MustMarshalJSON(&bankGenState)
|
||||
|
||||
appGenStateJSON, err := json.MarshalIndent(cfg.GenesisState, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
genDoc := types.GenesisDoc{
|
||||
ChainID: cfg.ChainID,
|
||||
AppState: appGenStateJSON,
|
||||
Validators: nil,
|
||||
}
|
||||
|
||||
// generate empty genesis files for each validator and save
|
||||
for i := 0; i < cfg.NumValidators; i++ {
|
||||
if err := genDoc.SaveAs(genFiles[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeFile(name string, dir string, contents []byte) error {
|
||||
file := filepath.Join(dir, name)
|
||||
|
||||
if err := os.MkdirAll(dir, 0o755); err != nil {
|
||||
return fmt.Errorf("could not create directory %q: %w", dir, err)
|
||||
}
|
||||
|
||||
if err := os.WriteFile(file, contents, 0o644); err != nil { //nolint: gosec
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
167
testutil/rest.go
167
testutil/rest.go
@ -1,167 +0,0 @@
|
||||
package testutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/network"
|
||||
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
txtypes "github.com/cosmos/cosmos-sdk/types/tx"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
|
||||
xauthsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||
)
|
||||
|
||||
// GetRequest defines a wrapper around an HTTP GET request with a provided URL.
|
||||
// An error is returned if the request or reading the body fails.
|
||||
func GetRequest(url string) ([]byte, error) {
|
||||
res, err := http.Get(url) //nolint:gosec,noctx // only used for testing
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
_ = res.Body.Close()
|
||||
}()
|
||||
|
||||
body, err := io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return body, nil
|
||||
}
|
||||
|
||||
// PostRequest defines a wrapper around an HTTP POST request with a provided URL and data.
|
||||
// An error is returned if the request or reading the body fails.
|
||||
func PostRequest(url, contentType string, data []byte) ([]byte, error) {
|
||||
res, err := http.Post(url, contentType, bytes.NewBuffer(data)) //nolint:gosec,noctx // only used for testing
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error while sending post request: %w", err)
|
||||
}
|
||||
defer func() {
|
||||
_ = res.Body.Close()
|
||||
}()
|
||||
|
||||
bz, err := io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error reading response body: %w", err)
|
||||
}
|
||||
|
||||
return bz, nil
|
||||
}
|
||||
|
||||
func PrepareTx(val *network.Validator, msg sdk.Msg, signer string) ([]byte, error) {
|
||||
k, err := val.ClientCtx.Keyring.Key(signer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
addr, err := k.GetAddress()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
reqAccountInfo := fmt.Sprintf("%s/cosmos/auth/v1beta1/account_info/%s", val.APIAddress, addr.String())
|
||||
respAccountInfo, err := GetRequest(reqAccountInfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var resAccountInfo authtypes.QueryAccountInfoResponse
|
||||
err = val.ClientCtx.Codec.UnmarshalJSON(respAccountInfo, &resAccountInfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
txBuilder := val.ClientCtx.TxConfig.NewTxBuilder()
|
||||
err = txBuilder.SetMsgs(msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
txBuilder.SetGasLimit(200000)
|
||||
txBuilder.SetFeeAmount(sdk.Coins{sdk.NewInt64Coin("stake", 2)})
|
||||
txBuilder.SetTimeoutHeight(0)
|
||||
|
||||
pk, err := k.GetPubKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sk := k.GetLocal().PrivKey
|
||||
|
||||
var priv cryptotypes.PrivKey
|
||||
err = val.ClientCtx.Codec.UnpackAny(sk, &priv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sigV2 := signing.SignatureV2{
|
||||
PubKey: pk,
|
||||
Data: &signing.SingleSignatureData{
|
||||
SignMode: val.ClientCtx.TxConfig.SignModeHandler().DefaultMode(),
|
||||
Signature: nil,
|
||||
},
|
||||
Sequence: resAccountInfo.Info.Sequence,
|
||||
}
|
||||
|
||||
err = txBuilder.SetSignatures(sigV2)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
signerData := xauthsigning.SignerData{
|
||||
ChainID: val.ClientCtx.ChainID,
|
||||
AccountNumber: resAccountInfo.Info.AccountNumber,
|
||||
Sequence: resAccountInfo.Info.Sequence,
|
||||
}
|
||||
sigV2, err = tx.SignWithPrivKey(
|
||||
val.ClientCtx.TxConfig.SignModeHandler().DefaultMode(), signerData,
|
||||
txBuilder, priv, val.ClientCtx.TxConfig, resAccountInfo.Info.Sequence,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = txBuilder.SetSignatures(sigV2)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
txBytes, err := val.ClientCtx.TxConfig.TxEncoder()(txBuilder.GetTx())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return txBytes, nil
|
||||
}
|
||||
|
||||
func BroadcastTx(val *network.Validator, txBytes []byte) (*txtypes.BroadcastTxResponse, error) {
|
||||
broadcastTxURL := fmt.Sprintf("%s/cosmos/tx/v1beta1/txs", val.APIAddress)
|
||||
req := txtypes.BroadcastTxRequest{
|
||||
TxBytes: txBytes,
|
||||
Mode: txtypes.BroadcastMode_BROADCAST_MODE_SYNC,
|
||||
}
|
||||
|
||||
broadCastTxBody, err := val.ClientCtx.Codec.MarshalJSON(&req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
broadCastTxResponse, err := PostRequest(broadcastTxURL, "application/json", broadCastTxBody)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var bctRes txtypes.BroadcastTxResponse
|
||||
err = val.ClientCtx.Codec.UnmarshalJSON(broadCastTxResponse, &bctRes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &bctRes, nil
|
||||
}
|
@ -4,17 +4,9 @@ import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
|
||||
"github.com/planetmint/planetmint-go/config"
|
||||
daotypes "github.com/planetmint/planetmint-go/x/dao/types"
|
||||
machinetypes "github.com/planetmint/planetmint-go/x/machine/types"
|
||||
|
||||
"github.com/btcsuite/btcd/btcutil/hdkeychain"
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/go-bip39"
|
||||
)
|
||||
|
||||
// Mnemonic sample mnemonic to use in tests
|
||||
@ -26,16 +18,13 @@ const PubKey = "021cd2a59c6f9402ce09effba89b3deb6bb5863733e625f22c06204918061db4
|
||||
// Name is the name of the sample machine to use in tests
|
||||
const Name = "machine"
|
||||
|
||||
// Amount is the amount to transfer to the machine account
|
||||
const Amount = "1000stake"
|
||||
|
||||
// Fees is the amount of fees to use in tests
|
||||
const Fees = "1stake"
|
||||
// FeeDenom is the fee denomination for e2e test cases
|
||||
const FeeDenom = "plmnt"
|
||||
|
||||
// DefaultDerivationPath is the BIP44Prefix for PLMNT (see https://github.com/satoshilabs/slips/blob/master/slip-0044.md)
|
||||
const DefaultDerivationPath = "m/44'/8680'/0'/0/0"
|
||||
|
||||
// ConstantBech32Addr for mocks
|
||||
// ConstBech32Addr constant bech32 address for mocks
|
||||
const ConstBech32Addr = "plmnt10mq5nj8jhh27z7ejnz2ql3nh0qhzjnfvy50877"
|
||||
|
||||
// KeyPair returns a sample private / public keypair
|
||||
@ -63,88 +52,7 @@ func Secp256k1AccAddress() sdk.AccAddress {
|
||||
return sdk.AccAddress(addr)
|
||||
}
|
||||
|
||||
// TODO: make address deterministic for test cases
|
||||
func Machine(name, pubKey string, prvKey string, address string) machinetypes.Machine {
|
||||
metadata := Metadata()
|
||||
_, liquidPubKey := ExtendedKeyPair(config.LiquidNetParams)
|
||||
_, planetmintPubKey := ExtendedKeyPair(config.PlmntNetParams)
|
||||
|
||||
prvKeyBytes, _ := hex.DecodeString(prvKey)
|
||||
sk := &secp256k1.PrivKey{Key: prvKeyBytes}
|
||||
pubKeyBytes, _ := hex.DecodeString(pubKey)
|
||||
sign, _ := sk.Sign(pubKeyBytes)
|
||||
signatureHex := hex.EncodeToString(sign)
|
||||
|
||||
if address == "" {
|
||||
address = Secp256k1AccAddress().String()
|
||||
}
|
||||
|
||||
m := machinetypes.Machine{
|
||||
Name: name,
|
||||
Ticker: name + "_ticker",
|
||||
Domain: "lab.r3c.network",
|
||||
Reissue: true,
|
||||
Amount: 1000,
|
||||
Precision: 8,
|
||||
IssuerPlanetmint: planetmintPubKey,
|
||||
IssuerLiquid: liquidPubKey,
|
||||
MachineId: pubKey,
|
||||
Metadata: &metadata,
|
||||
Type: 1,
|
||||
MachineIdSignature: signatureHex,
|
||||
Address: address,
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func MachineIndex(pubKey string, planetmintPubKey string, liquidPubKey string) machinetypes.MachineIndex {
|
||||
return machinetypes.MachineIndex{
|
||||
MachineId: pubKey,
|
||||
IssuerPlanetmint: planetmintPubKey,
|
||||
IssuerLiquid: liquidPubKey,
|
||||
}
|
||||
}
|
||||
|
||||
func Metadata() machinetypes.Metadata {
|
||||
return machinetypes.Metadata{
|
||||
Gps: "{\"Latitude\":\"-48.876667\",\"Longitude\":\"-123.393333\"}",
|
||||
Device: "{\"Manufacturer\": \"RDDL\",\"Serial\":\"AdnT2uyt\"}",
|
||||
AssetDefinition: "{\"Version\": \"0.1\"}",
|
||||
AdditionalDataCID: "CID",
|
||||
}
|
||||
}
|
||||
|
||||
func Asset() string {
|
||||
cid := "cid0"
|
||||
return cid
|
||||
}
|
||||
|
||||
func ExtendedKeyPair(cfg chaincfg.Params) (string, string) {
|
||||
seed, err := bip39.NewSeedWithErrorChecking(Mnemonic, keyring.DefaultBIP39Passphrase)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
xprivKey, err := hdkeychain.NewMaster(seed, &cfg)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
xpubKey, err := xprivKey.Neuter()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return xprivKey.String(), xpubKey.String()
|
||||
}
|
||||
|
||||
func TrustAnchor(pubkey string) machinetypes.TrustAnchor {
|
||||
return machinetypes.TrustAnchor{
|
||||
Pubkey: pubkey,
|
||||
}
|
||||
}
|
||||
|
||||
func MintRequest(beneficiaryAddr string, amount uint64, txhash string) daotypes.MintRequest {
|
||||
return daotypes.MintRequest{
|
||||
Beneficiary: beneficiaryAddr,
|
||||
Amount: amount,
|
||||
LiquidTxHash: txhash,
|
||||
}
|
||||
}
|
||||
|
@ -8,9 +8,10 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/planetmint/planetmint-go/errormsg"
|
||||
|
||||
cometcfg "github.com/cometbft/cometbft/config"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/planetmint/planetmint-go/config"
|
||||
)
|
||||
|
||||
type Key struct {
|
||||
@ -24,37 +25,52 @@ type KeyFile struct {
|
||||
PrivKey Key `json:"priv-key"`
|
||||
}
|
||||
|
||||
func GetValidatorCometBFTIdentity(ctx sdk.Context) (string, bool) {
|
||||
conf := config.GetConfig()
|
||||
|
||||
func GetValidatorCometBFTIdentity(ctx sdk.Context, rootDir string) (validatorIdentity string, err error) {
|
||||
cfg := cometcfg.DefaultConfig()
|
||||
jsonFilePath := filepath.Join(conf.ConfigRootDir, cfg.PrivValidatorKey)
|
||||
jsonFilePath := filepath.Join(rootDir, cfg.PrivValidatorKey)
|
||||
|
||||
jsonFile, err := os.Open(jsonFilePath)
|
||||
if err != nil {
|
||||
GetAppLogger().Error(ctx, "error while opening config", err.Error())
|
||||
return "", false
|
||||
GetAppLogger().Error(ctx, err, "error while opening config: %v", jsonFilePath)
|
||||
return
|
||||
}
|
||||
jsonBytes, err := io.ReadAll(jsonFile)
|
||||
if err != nil {
|
||||
GetAppLogger().Error(ctx, "error while reading file", err.Error())
|
||||
return "", false
|
||||
GetAppLogger().Error(ctx, err, "error while reading file: %v", jsonFile)
|
||||
return
|
||||
}
|
||||
|
||||
var keyFile KeyFile
|
||||
err = json.Unmarshal(jsonBytes, &keyFile)
|
||||
if err != nil {
|
||||
GetAppLogger().Error(ctx, "error while unmarshaling key file", err.Error())
|
||||
return "", false
|
||||
GetAppLogger().Error(ctx, err, "error while unmarshaling key file")
|
||||
return
|
||||
}
|
||||
return strings.ToLower(keyFile.Address), true
|
||||
validatorIdentity = strings.ToLower(keyFile.Address)
|
||||
return
|
||||
}
|
||||
|
||||
func IsValidatorBlockProposer(ctx sdk.Context, proposerAddress []byte) bool {
|
||||
validatorIdentity, validResult := GetValidatorCometBFTIdentity(ctx)
|
||||
if !validResult {
|
||||
return false
|
||||
func IsValidatorBlockProposer(ctx sdk.Context, rootDir string) (result bool) {
|
||||
validatorIdentity, err := GetValidatorCometBFTIdentity(ctx, rootDir)
|
||||
if err != nil {
|
||||
GetAppLogger().Error(ctx, err, errormsg.CouldNotGetValidatorIdentity)
|
||||
return
|
||||
}
|
||||
hexProposerAddress := hex.EncodeToString(proposerAddress)
|
||||
return hexProposerAddress == validatorIdentity
|
||||
hexProposerAddress := hex.EncodeToString(ctx.BlockHeader().ProposerAddress)
|
||||
result = hexProposerAddress == validatorIdentity
|
||||
return
|
||||
}
|
||||
|
||||
func IsValidAddress(address string) (valid bool, err error) {
|
||||
// Attempt to decode the address
|
||||
_, err = sdk.AccAddressFromBech32(address)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if !strings.Contains(address, "plmnt") {
|
||||
valid = false
|
||||
return
|
||||
}
|
||||
valid = true
|
||||
return
|
||||
}
|
||||
|
@ -1,70 +0,0 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/planetmint/planetmint-go/config"
|
||||
)
|
||||
|
||||
type ReissueResult struct {
|
||||
Txid string `json:"txid"`
|
||||
Vin int `json:"vin"`
|
||||
}
|
||||
|
||||
func ReissueAsset(reissueTx string) (txid string, err error) {
|
||||
conf := config.GetConfig()
|
||||
cmdArgs := strings.Split(reissueTx, " ")
|
||||
cmd := exec.Command("/usr/local/bin/elements-cli", "-rpcpassword="+conf.RPCPassword,
|
||||
"-rpcuser="+conf.RPCUser, "-rpcport="+strconv.Itoa(conf.RPCPort), "-rpcconnect="+conf.RPCHost,
|
||||
cmdArgs[0], cmdArgs[1], cmdArgs[2])
|
||||
|
||||
var stdout, stderr bytes.Buffer
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
err = cmd.Run()
|
||||
errstr := stderr.String()
|
||||
|
||||
if err != nil || len(errstr) > 0 {
|
||||
err = errors.New("reissuance of RDDL failed: " + errstr)
|
||||
} else {
|
||||
var txobj ReissueResult
|
||||
err = json.Unmarshal(stdout.Bytes(), &txobj)
|
||||
if err == nil {
|
||||
txid = txobj.Txid
|
||||
}
|
||||
}
|
||||
return txid, err
|
||||
}
|
||||
|
||||
func DistributeAsset(address string, amount string) (txid string, err error) {
|
||||
conf := config.GetConfig()
|
||||
cmd := exec.Command("/usr/local/bin/elements-cli", "-rpcpassword="+conf.RPCPassword,
|
||||
"-rpcuser="+conf.RPCUser, "-rpcport="+strconv.Itoa(conf.RPCPort), "-rpcconnect="+conf.RPCHost,
|
||||
"sendtoaddress", address, amount, "", "", "false", "true", "null", "\"unset\"", "false",
|
||||
"\""+conf.ReissuanceAsset+"\"")
|
||||
|
||||
var stdout, stderr bytes.Buffer
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
err = cmd.Run()
|
||||
errstr := stderr.String()
|
||||
|
||||
if err != nil || len(errstr) > 0 {
|
||||
errormessage := "distribution of RDDL failed for " + address
|
||||
err = errors.New(errormessage)
|
||||
} else {
|
||||
var txobj ReissueResult
|
||||
err = json.Unmarshal(stdout.Bytes(), &txobj)
|
||||
if err == nil {
|
||||
txid = txobj.Txid
|
||||
}
|
||||
}
|
||||
return txid, err
|
||||
}
|
@ -2,82 +2,113 @@ package util
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
"github.com/planetmint/planetmint-go/config"
|
||||
"github.com/planetmint/planetmint-go/lib"
|
||||
daotypes "github.com/planetmint/planetmint-go/x/dao/types"
|
||||
machinetypes "github.com/planetmint/planetmint-go/x/machine/types"
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
func setRPCConfig(goCtx context.Context) {
|
||||
rpcConf := lib.GetConfig()
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
rpcConf.SetChainID(ctx.ChainID())
|
||||
}
|
||||
func buildSignBroadcastTx(goCtx context.Context, loggingContext string, sendingValidatorAddress string, msg sdk.Msg) {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
GetAppLogger().Info(ctx, loggingContext+": "+msg.String())
|
||||
TerminationWaitGroup.Add(1)
|
||||
go func() {
|
||||
setRPCConfig(goCtx)
|
||||
defer TerminationWaitGroup.Done()
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
addr := sdk.MustAccAddressFromBech32(sendingValidatorAddress)
|
||||
txJSON, err := lib.BuildUnsignedTx(addr, msg)
|
||||
if err != nil {
|
||||
GetAppLogger().Error(ctx, loggingContext+" build unsigned tx failed: "+err.Error())
|
||||
GetAppLogger().Error(ctx, err, loggingContext+" build unsigned tx failed for: %v, %v", addr, msg)
|
||||
return
|
||||
}
|
||||
GetAppLogger().Info(ctx, loggingContext+" unsigned tx: "+txJSON)
|
||||
_, err = lib.BroadcastTxWithFileLock(addr, msg)
|
||||
GetAppLogger().Debug(ctx, loggingContext+" unsigned tx: "+txJSON)
|
||||
out, err := lib.BroadcastTxWithFileLock(addr, msg)
|
||||
if err != nil {
|
||||
GetAppLogger().Error(ctx, loggingContext+" broadcast tx failed: "+err.Error())
|
||||
GetAppLogger().Error(ctx, err, loggingContext+" broadcast tx failed: %v, %v", addr, msg)
|
||||
return
|
||||
}
|
||||
GetAppLogger().Info(ctx, loggingContext+" broadcast tx succeeded")
|
||||
txResponse, err := lib.GetTxResponseFromOut(out)
|
||||
if err != nil {
|
||||
GetAppLogger().Error(ctx, err, loggingContext+" getting tx response from out failed: %v", out)
|
||||
return
|
||||
}
|
||||
if txResponse.Code == 0 {
|
||||
GetAppLogger().Info(ctx, loggingContext+" broadcast tx succeeded")
|
||||
return
|
||||
}
|
||||
txResponseJSON, err := yaml.YAMLToJSON([]byte(txResponse.String()))
|
||||
if err != nil {
|
||||
GetAppLogger().Error(ctx, err, loggingContext+" converting tx response from yaml to json failed: %v", txResponse)
|
||||
return
|
||||
}
|
||||
GetAppLogger().Info(ctx, loggingContext+" broadcast tx failed: "+string(txResponseJSON))
|
||||
}()
|
||||
}
|
||||
|
||||
func InitRDDLReissuanceProcess(goCtx context.Context, proposerAddress string, txUnsigned string, blockHeight int64) {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
// get_last_PoPBlockHeight() // TODO: to be read form the upcoming PoP-store
|
||||
sendingValidatorAddress := config.GetConfig().ValidatorAddress
|
||||
GetAppLogger().Info(ctx, "create re-issuance proposal")
|
||||
msg := daotypes.NewMsgReissueRDDLProposal(sendingValidatorAddress, proposerAddress, txUnsigned, blockHeight)
|
||||
buildSignBroadcastTx(goCtx, "initializing RDDL re-issuance", sendingValidatorAddress, msg)
|
||||
func SendInitReissuance(goCtx context.Context, proposerAddress string, txUnsigned string, blockHeight int64,
|
||||
firstIncludedPop int64, lastIncludedPop int64) {
|
||||
sendingValidatorAddress := config.GetConfig().GetNodeAddress()
|
||||
msg := daotypes.NewMsgReissueRDDLProposal(sendingValidatorAddress, proposerAddress, txUnsigned, blockHeight,
|
||||
firstIncludedPop, lastIncludedPop)
|
||||
loggingContext := "reissuance proposal"
|
||||
buildSignBroadcastTx(goCtx, loggingContext, sendingValidatorAddress, msg)
|
||||
}
|
||||
|
||||
func SendRDDLReissuanceResult(goCtx context.Context, proposerAddress string, txID string, blockHeight int64) {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
sendingValidatorAddress := config.GetConfig().ValidatorAddress
|
||||
GetAppLogger().Info(ctx, "create re-issuance result")
|
||||
func SendReissuanceResult(goCtx context.Context, proposerAddress string, txID string, blockHeight int64) {
|
||||
sendingValidatorAddress := config.GetConfig().GetNodeAddress()
|
||||
msg := daotypes.NewMsgReissueRDDLResult(sendingValidatorAddress, proposerAddress, txID, blockHeight)
|
||||
buildSignBroadcastTx(goCtx, "sending the re-issuance result", sendingValidatorAddress, msg)
|
||||
loggingContext := "reissuance result"
|
||||
buildSignBroadcastTx(goCtx, loggingContext, sendingValidatorAddress, msg)
|
||||
}
|
||||
|
||||
func SendRDDLDistributionRequest(goCtx context.Context, distribution daotypes.DistributionOrder) {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
sendingValidatorAddress := config.GetConfig().ValidatorAddress
|
||||
GetAppLogger().Info(ctx, "create Distribution Request")
|
||||
func SendDistributionRequest(goCtx context.Context, distribution daotypes.DistributionOrder) {
|
||||
sendingValidatorAddress := config.GetConfig().GetNodeAddress()
|
||||
msg := daotypes.NewMsgDistributionRequest(sendingValidatorAddress, &distribution)
|
||||
buildSignBroadcastTx(goCtx, "sending the distribution request", sendingValidatorAddress, msg)
|
||||
loggingContext := "distribution request"
|
||||
buildSignBroadcastTx(goCtx, loggingContext, sendingValidatorAddress, msg)
|
||||
}
|
||||
|
||||
func SendRDDLDistributionResult(goCtx context.Context, lastPoP string, daoTxID string, invTxID string, popTxID string) {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
sendingValidatorAddress := config.GetConfig().ValidatorAddress
|
||||
GetAppLogger().Info(ctx, "create Distribution Result")
|
||||
iLastPoP, err := strconv.ParseInt(lastPoP, 10, 64)
|
||||
if err != nil {
|
||||
ctx.Logger().Error("Distribution Result: preparation failed ", err.Error())
|
||||
return
|
||||
}
|
||||
msg := daotypes.NewMsgDistributionResult(sendingValidatorAddress, iLastPoP, daoTxID, invTxID, popTxID)
|
||||
buildSignBroadcastTx(goCtx, "send distribution result", sendingValidatorAddress, msg)
|
||||
func SendDistributionResult(goCtx context.Context, lastPoP int64, daoTxID string, invTxID string,
|
||||
popTxID string, earlyInvestorTxID string, strategicTxID string) {
|
||||
sendingValidatorAddress := config.GetConfig().GetNodeAddress()
|
||||
msg := daotypes.NewMsgDistributionResult(sendingValidatorAddress, lastPoP, daoTxID, invTxID, popTxID, earlyInvestorTxID, strategicTxID)
|
||||
loggingContext := "distribution result"
|
||||
buildSignBroadcastTx(goCtx, loggingContext, sendingValidatorAddress, msg)
|
||||
}
|
||||
|
||||
func SendLiquidAssetRegistration(goCtx context.Context, notarizedAsset machinetypes.LiquidAsset) {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
sendingValidatorAddress := config.GetConfig().ValidatorAddress
|
||||
GetAppLogger().Info(ctx, "create Liquid Asset Registration")
|
||||
sendingValidatorAddress := config.GetConfig().GetNodeAddress()
|
||||
msg := machinetypes.NewMsgNotarizeLiquidAsset(sendingValidatorAddress, ¬arizedAsset)
|
||||
buildSignBroadcastTx(goCtx, "Liquid Asset Registration:", sendingValidatorAddress, msg)
|
||||
loggingContext := "notarize liquid asset"
|
||||
buildSignBroadcastTx(goCtx, loggingContext, sendingValidatorAddress, msg)
|
||||
}
|
||||
|
||||
func SendInitPoP(goCtx context.Context, challenger string, challengee string, blockHeight int64) {
|
||||
sendingValidatorAddress := config.GetConfig().GetNodeAddress()
|
||||
msg := daotypes.NewMsgInitPop(sendingValidatorAddress, sendingValidatorAddress, challenger, challengee, blockHeight)
|
||||
loggingContext := "PoP"
|
||||
buildSignBroadcastTx(goCtx, loggingContext, sendingValidatorAddress, msg)
|
||||
}
|
||||
|
||||
func SendUpdateRedeemClaim(goCtx context.Context, beneficiary string, id uint64, txID string) {
|
||||
sendingValidatorAddress := config.GetConfig().GetNodeAddress()
|
||||
msg := daotypes.NewMsgUpdateRedeemClaim(sendingValidatorAddress, beneficiary, txID, id)
|
||||
loggingContext := "redeem claim"
|
||||
buildSignBroadcastTx(goCtx, loggingContext, sendingValidatorAddress, msg)
|
||||
}
|
||||
|
||||
func SendTokens(goCtx context.Context, beneficiary sdk.AccAddress, amount uint64, denominator string) {
|
||||
sendingValidatorAddress := config.GetConfig().GetNodeAddress()
|
||||
|
||||
coin := sdk.NewCoin(denominator, sdk.NewIntFromUint64(amount))
|
||||
coins := sdk.NewCoins(coin)
|
||||
orgAddr := sdk.MustAccAddressFromBech32(sendingValidatorAddress)
|
||||
msg := banktypes.NewMsgSend(orgAddr, beneficiary, coins)
|
||||
|
||||
loggingContext := "sending " + denominator + " tokens"
|
||||
buildSignBroadcastTx(goCtx, loggingContext, sendingValidatorAddress, msg)
|
||||
}
|
||||
|
42
util/kv_serialize.go
Normal file
42
util/kv_serialize.go
Normal file
@ -0,0 +1,42 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
)
|
||||
|
||||
func SerializeInt64(value int64) []byte {
|
||||
// Adding 1 because 0 will be interpreted as nil, which is an invalid key
|
||||
buf := make([]byte, 8)
|
||||
// Use binary.BigEndian to write the int64 into the byte slice
|
||||
binary.BigEndian.PutUint64(buf, uint64(value+1))
|
||||
return buf
|
||||
}
|
||||
|
||||
func DeserializeInt64(value []byte) int64 {
|
||||
integer := binary.BigEndian.Uint64(value)
|
||||
// Subtract 1 because addition in serialization
|
||||
return int64(integer - 1)
|
||||
}
|
||||
|
||||
func SerializeUint64(value uint64) []byte {
|
||||
buf := make([]byte, 8)
|
||||
// Adding 1 because 0 will be interpreted as nil, which is an invalid key
|
||||
binary.BigEndian.PutUint64(buf, value+1)
|
||||
return buf
|
||||
}
|
||||
|
||||
func DeserializeUint64(value []byte) uint64 {
|
||||
integer := binary.BigEndian.Uint64(value)
|
||||
// Subtract 1 because addition in serialization
|
||||
return integer - 1
|
||||
}
|
||||
|
||||
func SerializeString(value string) []byte {
|
||||
byteArray := []byte(value)
|
||||
return byteArray
|
||||
}
|
||||
|
||||
func SerializeHexString(value string) ([]byte, error) {
|
||||
return hex.DecodeString(value)
|
||||
}
|
@ -1,11 +1,23 @@
|
||||
package util
|
||||
|
||||
import sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
type AppLogger struct {
|
||||
testingLogger *testing.T
|
||||
}
|
||||
|
||||
var globalApplicationLoggerTag string
|
||||
var (
|
||||
globalApplicationLoggerTag string
|
||||
appLogger *AppLogger
|
||||
initAppLogger sync.Once
|
||||
syncTestingLog sync.RWMutex
|
||||
)
|
||||
|
||||
func init() {
|
||||
// Initialize the package-level variable
|
||||
@ -13,17 +25,52 @@ func init() {
|
||||
}
|
||||
|
||||
func GetAppLogger() *AppLogger {
|
||||
return &AppLogger{}
|
||||
initAppLogger.Do(func() {
|
||||
appLogger = &AppLogger{
|
||||
testingLogger: nil,
|
||||
}
|
||||
})
|
||||
return appLogger
|
||||
}
|
||||
|
||||
func (logger *AppLogger) SetTestingLogger(testingLogger *testing.T) *AppLogger {
|
||||
syncTestingLog.Lock()
|
||||
logger.testingLogger = testingLogger
|
||||
syncTestingLog.Unlock()
|
||||
return logger
|
||||
}
|
||||
|
||||
func format(msg string, keyvals ...interface{}) string {
|
||||
if len(keyvals) == 0 {
|
||||
return msg
|
||||
}
|
||||
return fmt.Sprintf(msg, keyvals...)
|
||||
}
|
||||
|
||||
func (logger *AppLogger) testingLog(msg string, keyvals ...interface{}) {
|
||||
syncTestingLog.RLock()
|
||||
defer syncTestingLog.RUnlock()
|
||||
if logger.testingLogger == nil {
|
||||
return
|
||||
}
|
||||
msg = format(msg, keyvals...)
|
||||
logger.testingLogger.Log(msg)
|
||||
}
|
||||
|
||||
func (logger *AppLogger) Info(ctx sdk.Context, msg string, keyvals ...interface{}) {
|
||||
ctx.Logger().Info(globalApplicationLoggerTag+msg, keyvals...)
|
||||
msg = format(msg, keyvals...)
|
||||
logger.testingLog(globalApplicationLoggerTag + msg)
|
||||
ctx.Logger().Info(globalApplicationLoggerTag + msg)
|
||||
}
|
||||
|
||||
func (logger *AppLogger) Debug(ctx sdk.Context, msg string, keyvals ...interface{}) {
|
||||
ctx.Logger().Debug(globalApplicationLoggerTag+msg, keyvals...)
|
||||
msg = format(msg, keyvals...)
|
||||
logger.testingLog(globalApplicationLoggerTag + msg)
|
||||
ctx.Logger().Debug(globalApplicationLoggerTag + msg)
|
||||
}
|
||||
|
||||
func (logger *AppLogger) Error(ctx sdk.Context, msg string, keyvals ...interface{}) {
|
||||
ctx.Logger().Error(globalApplicationLoggerTag+msg, keyvals...)
|
||||
func (logger *AppLogger) Error(ctx sdk.Context, err error, msg string, keyvals ...interface{}) {
|
||||
msg = format(msg, keyvals...)
|
||||
logger.testingLog(globalApplicationLoggerTag + msg + ": " + err.Error())
|
||||
ctx.Logger().Error(globalApplicationLoggerTag + msg + ": " + err.Error())
|
||||
}
|
||||
|
104
util/machine_nft.go
Normal file
104
util/machine_nft.go
Normal file
@ -0,0 +1,104 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/planetmint/planetmint-go/clients/shamir/coordinator"
|
||||
"github.com/planetmint/planetmint-go/x/machine/types"
|
||||
)
|
||||
|
||||
type HTTPClient interface {
|
||||
Do(req *http.Request) (*http.Response, error)
|
||||
}
|
||||
|
||||
var (
|
||||
RegisterAssetServiceHTTPClient HTTPClient
|
||||
)
|
||||
|
||||
func init() {
|
||||
RegisterAssetServiceHTTPClient = &http.Client{}
|
||||
}
|
||||
|
||||
func IssueMachineNFT(goCtx context.Context, machine *types.Machine, scheme string, domain string, path string) error {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
// asset registration is in order to have the contact published
|
||||
var notarizedAsset types.LiquidAsset
|
||||
notarizedAsset.Registered = true
|
||||
assetID, contract, hex, err := coordinator.IssueNFTAsset(goCtx, machine.Name, machine.Address, domain)
|
||||
if err != nil {
|
||||
GetAppLogger().Error(ctx, err, "")
|
||||
return err
|
||||
}
|
||||
assetRegistryEndpoint := fmt.Sprintf("%s://%s/%s", scheme, domain, path)
|
||||
|
||||
GetAppLogger().Info(ctx, "Liquid Token Issuance assetID: "+assetID+" contract: "+contract+" tx: "+hex)
|
||||
err = RegisterAsset(goCtx, assetID, contract, assetRegistryEndpoint)
|
||||
if err != nil {
|
||||
GetAppLogger().Error(ctx, err, "")
|
||||
notarizedAsset.Registered = false
|
||||
}
|
||||
// issue message with:
|
||||
notarizedAsset.AssetID = assetID
|
||||
notarizedAsset.MachineID = machine.GetMachineId()
|
||||
notarizedAsset.MachineAddress = machine.Address
|
||||
|
||||
SendLiquidAssetRegistration(goCtx, notarizedAsset)
|
||||
return err
|
||||
}
|
||||
|
||||
func RegisterAsset(goCtx context.Context, assetID string, contract string, assetRegistryEndpoint string) error {
|
||||
var contractMap map[string]interface{}
|
||||
err := json.Unmarshal([]byte(contract), &contractMap)
|
||||
if err != nil {
|
||||
return errorsmod.Wrap(types.ErrAssetRegistryReqFailure, "Unmarshal "+err.Error())
|
||||
}
|
||||
// Create your request payload
|
||||
data := map[string]interface{}{
|
||||
"asset_id": assetID,
|
||||
"contract": contractMap,
|
||||
}
|
||||
|
||||
jsonData, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return errorsmod.Wrap(types.ErrAssetRegistryReqFailure, "Marshall "+err.Error())
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(goCtx, http.MethodPost, assetRegistryEndpoint, bytes.NewBuffer(jsonData))
|
||||
if err != nil {
|
||||
return errorsmod.Wrap(types.ErrAssetRegistryReqFailure, "Request creation: "+err.Error())
|
||||
}
|
||||
|
||||
// Set headers
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("accept", "application/json")
|
||||
|
||||
// Send request
|
||||
resp, err := RegisterAssetServiceHTTPClient.Do(req)
|
||||
if err != nil {
|
||||
return errorsmod.Wrap(types.ErrAssetRegistryReqSending, err.Error())
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// Read response
|
||||
if resp.StatusCode > 299 {
|
||||
return errorsmod.Wrap(types.ErrAssetRegistryRepsonse, "Error reading response body:"+strconv.Itoa(resp.StatusCode))
|
||||
}
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return errorsmod.Wrap(types.ErrAssetRegistryRepsonse, "Error reading response body:"+err.Error())
|
||||
}
|
||||
resultObj := string(body)
|
||||
if strings.Contains(resultObj, assetID) {
|
||||
return nil
|
||||
}
|
||||
return errorsmod.Wrap(types.ErrAssetRegistryRepsonse, "does not confirm asset registration")
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user