From 7a8cdac4bd958a1027364189315ce5b3681c3c35 Mon Sep 17 00:00:00 2001 From: hard-nett Date: Mon, 8 Apr 2024 12:01:32 -0400 Subject: [PATCH] add custom msg registry, makefiles, scripts --- .github/workflows/interchaintest-E2E.yml | 2 +- .goreleaser.yaml | 228 ++++++++++++++ Makefile | 280 ++++++------------ app/app.go | 16 - app/keepers/keepers.go | 25 +- app/keepers/querier.go | 22 ++ interchaintest/helpers/cosmwasm.go | 20 +- interchaintest/module_clock_test.go | 2 +- interchaintest/module_feeshare_test.go | 2 +- interchaintest/module_ibchooks_test.go | 2 +- interchaintest/module_tokenfactory_test.go | 2 +- internal/wasm/distribution.go | 47 +++ internal/wasm/encoder.go | 51 ++++ internal/wasm/registry.go | 22 ++ scripts/makefiles/build.mk | 144 +++++++++ scripts/makefiles/deps.mk | 45 +++ scripts/makefiles/e2e.mk | 66 +++++ scripts/makefiles/lint.mk | 38 +++ scripts/makefiles/proto.mk | 111 +++++++ scripts/makefiles/release.mk | 52 ++++ scripts/makefiles/tests.mk | 29 ++ .../create_all_binaries_json.sh | 16 + .../create_binaries_json.py | 118 ++++++++ .../create_binaries_json/requirements.txt | 0 .../create_upgrade_guide/UPGRADE_TEMPLATE.md | 116 ++++++++ .../create_upgrade_guide.py | 82 +++++ scripts/replace_import_paths.sh | 61 ++++ 27 files changed, 1371 insertions(+), 228 deletions(-) create mode 100644 .goreleaser.yaml create mode 100644 app/keepers/querier.go create mode 100644 internal/wasm/distribution.go create mode 100644 internal/wasm/encoder.go create mode 100644 internal/wasm/registry.go create mode 100644 scripts/makefiles/build.mk create mode 100644 scripts/makefiles/deps.mk create mode 100644 scripts/makefiles/e2e.mk create mode 100644 scripts/makefiles/lint.mk create mode 100644 scripts/makefiles/proto.mk create mode 100644 scripts/makefiles/release.mk create mode 100644 scripts/makefiles/tests.mk create mode 100644 scripts/release/create_binaries_json/create_all_binaries_json.sh create mode 100644 scripts/release/create_binaries_json/create_binaries_json.py create mode 100644 scripts/release/create_binaries_json/requirements.txt create mode 100644 scripts/release/create_upgrade_guide/UPGRADE_TEMPLATE.md create mode 100644 scripts/release/create_upgrade_guide/create_upgrade_guide.py create mode 100644 scripts/replace_import_paths.sh diff --git a/.github/workflows/interchaintest-E2E.yml b/.github/workflows/interchaintest-E2E.yml index 0a2f9b1c..f3dac25b 100644 --- a/.github/workflows/interchaintest-E2E.yml +++ b/.github/workflows/interchaintest-E2E.yml @@ -69,7 +69,7 @@ jobs: # - "ictest-pob" # - "ictest-drip" # - "ictest-cwhooks" - # - "ictest-clock" + - "ictest-clock" fail-fast: false steps: diff --git a/.goreleaser.yaml b/.goreleaser.yaml new file mode 100644 index 00000000..80326870 --- /dev/null +++ b/.goreleaser.yaml @@ -0,0 +1,228 @@ +project_name: terpd + +env: + - CGO_ENABLED=1 + +builds: + - id: terpd-darwin-amd64 + main: ./cmd/terpd/main.go + binary: terpd + hooks: + pre: + - wget https://github.com/CosmWasm/wasmvm/releases/download/{{ .Env.COSMWASM_VERSION }}/libwasmvmstatic_darwin.a -O /lib/libwasmvmstatic_darwin.a + env: + - CC=o64-clang + - CGO_LDFLAGS=-L/lib + goos: + - darwin + goarch: + - amd64 + flags: + - -mod=readonly + - -trimpath + ldflags: + - -X github.com/cosmos/cosmos-sdk/version.Name=terpnetwork + - -X github.com/cosmos/cosmos-sdk/version.AppName=terpd + - -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=netgo,ledger,static_wasm + - -w -s + - -linkmode=external + tags: + - netgo + - ledger + - static_wasm + + - id: terpd-darwin-arm64 + main: ./cmd/terpd/main.go + binary: terpd + hooks: + pre: + - wget https://github.com/CosmWasm/wasmvm/releases/download/{{ .Env.COSMWASM_VERSION }}/libwasmvmstatic_darwin.a -O /lib/libwasmvmstatic_darwin.a + env: + - CC=oa64-clang + - CGO_LDFLAGS=-L/lib + goos: + - darwin + goarch: + - arm64 + flags: + - -mod=readonly + - -trimpath + ldflags: + - -X github.com/cosmos/cosmos-sdk/version.Name=terpnetwork + - -X github.com/cosmos/cosmos-sdk/version.AppName=terpd + - -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=netgo,ledger,static_wasm + - -w -s + - -linkmode=external + tags: + - netgo + - ledger + - static_wasm + + - id: terpd-linux-amd64 + main: ./cmd/terpd + binary: terpd + hooks: + pre: + - wget https://github.com/CosmWasm/wasmvm/releases/download/{{ .Env.COSMWASM_VERSION }}/libwasmvm_muslc.x86_64.a -O /usr/lib/x86_64-linux-gnu/libwasmvm_muslc.a + goos: + - linux + goarch: + - amd64 + env: + - CC=x86_64-linux-gnu-gcc + flags: + - -mod=readonly + - -trimpath + ldflags: + - -X github.com/cosmos/cosmos-sdk/version.Name=terpnetwork + - -X github.com/cosmos/cosmos-sdk/version.AppName=terpd + - -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=netgo,ledger,muslc,osusergo + - -w -s + - -linkmode=external + - -extldflags '-Wl,-z,muldefs -static -lm' + tags: + - netgo + - ledger + - muslc + - osusergo + + - id: terpd-linux-arm64 + main: ./cmd/terpd + binary: terpd + hooks: + pre: + - wget https://github.com/CosmWasm/wasmvm/releases/download/{{ .Env.COSMWASM_VERSION }}/libwasmvm_muslc.aarch64.a -O /usr/lib/aarch64-linux-gnu/libwasmvm_muslc.a + goos: + - linux + goarch: + - arm64 + env: + - CC=aarch64-linux-gnu-gcc + flags: + - -mod=readonly + - -trimpath + ldflags: + - -X github.com/cosmos/cosmos-sdk/version.Name=terpnetwork + - -X github.com/cosmos/cosmos-sdk/version.AppName=terpd + - -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=netgo,ledger,muslc,osusergo + - -w -s + - -linkmode=external + - -extldflags '-Wl,-z,muldefs -static -lm' + tags: + - netgo + - ledger + - muslc + - osusergo + +universal_binaries: + - id: terpd-darwin-universal + ids: + - terpd-darwin-amd64 + - terpd-darwin-arm64 + replace: false + +archives: + - id: zipped + builds: + # - terpd-darwin-universal + - terpd-linux-amd64 + - terpd-linux-arm64 + # - terpd-darwin-amd64 + # - terpd-darwin-arm64 + name_template: "{{.ProjectName}}-{{ .Version }}-{{ .Os }}-{{ .Arch }}" + format: tar.gz + files: + - none* + - id: binaries + builds: + # - terpd-darwin-universal + - terpd-linux-amd64 + - terpd-linux-arm64 + # - terpd-darwin-amd64 + # - terpd-darwin-arm64 + name_template: "{{.ProjectName}}-{{ .Version }}-{{ .Os }}-{{ .Arch }}" + format: binary + files: + - none* + +checksum: + name_template: "sha256sum.txt" + algorithm: sha256 + +# Docs: https://goreleaser.com/customization/changelog/ +changelog: + skip: true + +# Docs: https://goreleaser.com/customization/release/ +release: + github: + owner: terpnetwork + name: terp-core + replace_existing_draft: true + header: | + < DESCRIPTION OF RELEASE > + + ## Changelog + + See the full changelog [here](https://github.com/terpnetwork/terp-core/blob/v{{ .Version }}/CHANGELOG.md) + + ## ⚡️ Binaries + + Binaries for Linux (amd64 and arm64) are available below. + + #### 🔨 Build from source + + If you prefer to build from source, you can use the following commands: + + ````bash + git clone https://github.com/terpnetwork/terp-core + cd osmosis && git checkout v{{ .Version }} + make install + ```` + + ## 🐳 Run with Docker + + As an alternative to installing and running terpd on your system, you may run terpd in a Docker container. + The following Docker images are available in our registry: + + | Image Name | Base | Description | + |----------------------------------------------|--------------------------------------|-----------------------------------| + | `terpnetwork/terp-core:{{ .Version }}` | `distroless/static-debian11` | Default image based on Distroless | + | `terpnetwork/terp-core:{{ .Version }}-distroless` | `distroless/static-debian11` | Distroless image (same as above) | + | `terpnetwork/terp-core:{{ .Version }}-nonroot` | `distroless/static-debian11:nonroot` | Distroless non-root image | + | `terpnetwork/terp-core:{{ .Version }}-alpine` | `alpine` | Alpine image | + + Example run: + + ```bash + docker run terpnetwork/terp-core:{{ .Version }} version + # v{{ .Version }} + ```` + + All the images support `arm64` and `amd64` architectures. + + name_template: "Terp-Core v{{.Version}} " + mode: replace + draft: true + +# Docs: https://goreleaser.com/customization/announce/ +# We could automatically announce the release in +# - discord +# - slack +# - twitter +# - webhooks +# - telegram +# - reddit +# +# announce: + # discord: + # enabled: true + # message_template: 'New {{.Tag}} is out!' diff --git a/Makefile b/Makefile index 40226cd7..38a635a4 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,67 @@ #!/usr/bin/make -f +include scripts/makefiles/proto.mk +include scripts/makefiles/release.mk +include scripts/makefiles/lint.mk +include scripts/makefiles/tests.mk +include scripts/makefiles/e2e.mk +include scripts/makefiles/heighliner.mk +include scripts/makefiles/build.mk +include scripts/makefiles/deps.mk + + +.DEFAULT_GOAL := help +help: + @echo "Available top-level commands:" + @echo "" + @echo "Usage:" + @echo " make [command]" + @echo "" + @echo " make build Build terpd binary" + @echo " make build-help Show available build commands" + @echo " make deps Show available deps commands" + @echo " make heighliner Show available docker commands" + @echo " make e2e Show available e2e commands" + @echo " make install Install terpd binary" + @echo " make lint Show available lint commands" + @echo " make proto Show available proto commands" + @echo " make release Show available release commands" + @echo " make release-help Show available release commands" + @echo " make test Show available test commands" + @echo "" + @echo "Run 'make [subcommand]' to see the available commands for each subcommand." + +# git info BRANCH := $(shell git rev-parse --abbrev-ref HEAD) -COMMIT := $(shell git log -1 --format='%H') VERSION := $(shell echo $(shell git describe --tags) | sed 's/^v//') -BINDIR ?= $(GOPATH)/bin -APP = ./app +COMMIT := $(shell git log -1 --format='%H') + +LEDGER_ENABLED ?= true +SDK_PACK := $(shell go list -m github.com/cosmos/cosmos-sdk | sed 's/ /\@/g') +BUILDDIR ?= $(CURDIR)/build +DOCKER := $(shell which docker) +E2E_UPGRADE_VERSION := "v4" + + + +DOCKER_BUF := $(DOCKER) run --rm -v $(CURDIR):/workspace --workdir /workspace $(BUF_IMAGE) +PACKAGES_SIMTEST=$(shell go list ./... | grep '/simulation') +BUF_IMAGE=bufbuild/buf@sha256:3cb1f8a4b48bd5ad8f09168f10f607ddc318af202f5c057d52a45216793d85e5 #v1.4.0 +SDK_PACK := $(shell go list -m github.com/cosmos/cosmos-sdk | sed 's/ /\@/g') +HTTPS_GIT := https://github.com/terpnetwork/terp-core.git + + +GO_MODULE := $(shell cat go.mod | grep "module " | cut -d ' ' -f 2) +GO_VERSION := $(shell cat go.mod | grep -E 'go [0-9].[0-9]+' | cut -d ' ' -f 2) +GO_MAJOR_VERSION = $(shell go version | cut -c 14- | cut -d' ' -f1 | cut -d'.' -f1) +GO_MINOR_VERSION = $(shell go version | cut -c 14- | cut -d' ' -f1 | cut -d'.' -f2) +GO_MINIMUM_MAJOR_VERSION = $(shell cat go.mod | grep -E 'go [0-9].[0-9]+' | cut -d ' ' -f2 | cut -d'.' -f1) +GO_MINIMUM_MINOR_VERSION = $(shell cat go.mod | grep -E 'go [0-9].[0-9]+' | cut -d ' ' -f2 | cut -d'.' -f2) +# message to be printed if Go does not meet the minimum required version +GO_VERSION_ERR_MSG = "ERROR: Go version $(GO_MINIMUM_MAJOR_VERSION).$(GO_MINIMUM_MINOR_VERSION)+ is required" + + +export GO111MODULE = on # don't override user values ifeq (,$(VERSION)) @@ -15,10 +72,6 @@ ifeq (,$(VERSION)) endif endif -PACKAGES_SIMTEST=$(shell go list ./... | grep '/simulation') -LEDGER_ENABLED ?= true -SDK_PACK := $(shell go list -m github.com/cosmos/cosmos-sdk | sed 's/ /\@/g') - # don't override user values ifeq (,$(VERSION)) VERSION := $(shell git describe --tags) @@ -28,12 +81,6 @@ ifeq (,$(VERSION)) endif endif -# for dockerized protobuf tools -DOCKER := $(shell which docker) -BUF_IMAGE=bufbuild/buf@sha256:3cb1f8a4b48bd5ad8f09168f10f607ddc318af202f5c057d52a45216793d85e5 #v1.4.0 -DOCKER_BUF := $(DOCKER) run --rm -v $(CURDIR):/workspace --workdir /workspace $(BUF_IMAGE) -HTTPS_GIT := https://github.com/terpnetwork/terp-core.git - export GO111MODULE = on # process build tags @@ -69,9 +116,9 @@ build_tags += $(BUILD_TAGS) build_tags := $(strip $(build_tags)) whitespace := -empty = $(whitespace) $(whitespace) +whitespace := $(whitespace) $(whitespace) comma := , -build_tags_comma_sep := $(subst $(empty),$(comma),$(build_tags)) +build_tags_comma_sep := $(subst $(whitespace),$(comma),$(build_tags)) # process linker flags @@ -93,187 +140,36 @@ ldflags := $(strip $(ldflags)) BUILD_FLAGS := -tags "$(build_tags_comma_sep)" -ldflags '$(ldflags)' -trimpath -# The below include contains the tools and runsim targets. -include contrib/devtools/Makefile - -all: install - @echo "--> project root: go mod tidy" - @go mod tidy - @echo "--> project root: linting --fix" - @GOGC=1 golangci-lint run --fix --timeout=8m - -install: go.sum - go install -mod=readonly $(BUILD_FLAGS) ./cmd/terpd - -build: go.sum -ifeq ($(OS),Windows_NT) - $(error terpd server not supported. Use "make build-windows-client" for client) - exit 1 -else - go build -mod=readonly $(BUILD_FLAGS) -o build/terpd ./cmd/terpd -endif - -build-windows-client: go.sum - GOOS=windows GOARCH=amd64 go build -mod=readonly $(BUILD_FLAGS) -o build/terpd.exe ./cmd/terpd - -build-contract-tests-hooks: -ifeq ($(OS),Windows_NT) - go build -mod=readonly $(BUILD_FLAGS) -o build/contract_tests.exe ./cmd/contract_tests -else - go build -mod=readonly $(BUILD_FLAGS) -o build/contract_tests ./cmd/contract_tests -endif - -test-node: - CHAIN_ID="local-1" HOME_DIR="~/.terp1" TIMEOUT_COMMIT="500ms" CLEAN=true sh scripts/test_node.sh - -############################################################################### -### Testing ### -############################################################################### - -test: test-unit -test-all: check test-race test-cover - -test-unit: - @VERSION=$(VERSION) go test -mod=readonly -tags='ledger test_ledger_mock' ./... - -benchmark: - @go test -mod=readonly -bench=. ./... - -test-sim-multi-seed-short: runsim - @echo "Running short multi-seed application simulation. This may take awhile!" - @$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(APP) -ExitOnFail 50 5 TestFullAppSimulation - -test-sim-deterministic: runsim - @echo "Running short multi-seed application simulation. This may take awhile!" - @$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(APP) -ExitOnFail 1 1 TestAppStateDeterminism - -############################################################################### -### Tools & dependencies ### -############################################################################### - -go-mod-cache: go.sum - @echo "--> Download go modules to local cache" - @go mod download - -go.sum: go.mod - @echo "--> Ensure dependencies have not been modified" - @go mod verify - -draw-deps: - @# requires brew install graphviz or apt-get install graphviz - go install github.com/RobotsAndPencils/goviz@latest - @goviz -i ./cmd/terpd -d 2 | dot -Tpng -o dependency-graph.png - -clean: - rm -rf snapcraft-local.yaml build/ - -distclean: clean - rm -rf vendor/ - -############################################################################### -### Linting ### -############################################################################### - -format-tools: - go install mvdan.cc/gofumpt@v0.4.0 - go install github.com/client9/misspell/cmd/misspell@v0.3.4 - go install golang.org/x/tools/cmd/goimports@latest - -lint: format-tools - golangci-lint run --tests=false - find . -name '*.go' -type f -not -path "./vendor*" -not -path "*.git*" -not -path "*_test.go" | xargs gofumpt -d -format: format-tools - find . -name '*.go' -type f -not -path "./vendor*" -not -path "*.git*" -not -path "./client/lcd/statik/statik.go" | xargs gofumpt -w -s - find . -name '*.go' -type f -not -path "./vendor*" -not -path "*.git*" -not -path "./client/lcd/statik/statik.go" | xargs gofumpt -w - find . -name '*.go' -type f -not -path "./vendor*" -not -path "*.git*" -not -path "./client/lcd/statik/statik.go" | xargs goimports -w -local github.com/terpnetwork/terp-core - -############################################################################### -### e2e interchain test ### -############################################################################### - - # Executes basic chain tests via interchaintest -ictest-basic: rm-testcache - cd interchaintest && go test -race -v -run TestBasicTerpStart . - -ictest-statesync: rm-testcache - cd interchaintest && go test -race -v -run TestTerpStateSync . - -ictest-ibchooks: rm-testcache - cd interchaintest && go test -race -v -run TestTerpIBCHooks . - -ictest-pfm: rm-testcache - cd interchaintest && go test -race -v -run TestPacketForwardMiddlewareRouter . - -ictest-tokenfactory: rm-testcache - cd interchaintest && go test -race -v -run TestTerpTokenFactory . - -# ictest-clock: rm-testcache -# cd interchaintest && go test -race -v -run TestTerpClock . - -ictest-feeshare: rm-testcache - cd interchaintest && go test -race -v -run TestTerpFeeShare . - -# Executes a basic chain upgrade test via interchaintest -ictest-upgrade: rm-testcache - cd interchaintest && go test -race -v -run TestBasicTerpUpgrade . - -# Executes a basic chain upgrade locally via interchaintest after compiling a local image as terpnetwork:local -ictest-upgrade-local: local-image ictest-upgrade - -# Executes IBC tests via interchaintest -ictest-ibc: rm-testcache - cd interchaintest && go test -race -v -run TestTerpGaiaIBCTransfer . - -rm-testcache: - go clean -testcache - -.PHONY: test-mutation ictest-basic ictest-upgrade ictest-ibc - ############################################################################### -### heighliner ### +### Build & Install ### ############################################################################### -get-heighliner: - git clone https://github.com/strangelove-ventures/heighliner.git - cd heighliner && go install +build: build-check-version go.sum + mkdir -p $(BUILDDIR)/ + GOWORK=off go build -mod=readonly $(BUILD_FLAGS) -o $(BUILDDIR)/ $(GO_MODULE)/cmd/terpd -local-image: -ifeq (,$(shell which heighliner)) - echo 'heighliner' binary not found. Consider running `make get-heighliner` -else - heighliner build -c terpnetwork --local -f ./chains.yaml -endif +install: build-check-version go.sum + GOWORK=off go install -mod=readonly $(BUILD_FLAGS) $(GO_MODULE)/cmd/terpd -.PHONY: get-heighliner local-image ############################################################################### -### Protobuf ### +### Release ### ############################################################################### -protoVer=0.13.1 -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 format - -proto-gen: - @echo "Generating Protobuf files" - @$(protoImage) sh ./scripts/protocgen.sh - -proto-swagger-gen: - @echo "Generating Protobuf Swagger" - @$(protoImage) sh ./scripts/protoc_swagger_openapi_gen.sh - $(MAKE) update-swagger-docs - -proto-format: - @echo "Formatting Protobuf files" - @$(protoImage) find ./ -name "*.proto" -exec clang-format -i {} \; - -proto-lint: - @$(DOCKER_BUF) lint --error-format=json - -proto-check-breaking: - @$(DOCKER_BUF) breaking --against $(HTTPS_GIT)#branch=main - -.PHONY: all install install-debug \ - go-mod-cache draw-deps clean build format \ - test test-all test-build test-cover test-unit test-race \ - test-sim-import-export build-windows-client \ +GORELEASER_IMAGE := ghcr.io/goreleaser/goreleaser-cross:v$(GO_VERSION) +COSMWASM_VERSION := $(shell go list -m github.com/CosmWasm/wasmvm | sed 's/.* //') + +ifdef GITHUB_TOKEN +release: + docker run \ + --rm \ + -e GITHUB_TOKEN=$(GITHUB_TOKEN) \ + -e COSMWASM_VERSION=$(COSMWASM_VERSION) \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -v `pwd`:/go/src/terpd \ + -w /go/src/terpd \ + $(GORELEASER_IMAGE) \ + release \ + --clean +else +release: + @echo "Error: GITHUB_TOKEN is not defined. Please define it before running 'make release'." +endif \ No newline at end of file diff --git a/app/app.go b/app/app.go index dfbcad80..958f14af 100644 --- a/app/app.go +++ b/app/app.go @@ -597,19 +597,3 @@ func (app *TerpApp) GetChainBondDenom() string { } return d } - -// QuerierWrapper is a local wrapper around BaseApp that exports only the Queryable interface. -// This is used to pass the baseApp to Async ICQ without exposing all methods -type QuerierWrapper struct { - querier sdk.Queryable -} - -var _ sdk.Queryable = QuerierWrapper{} - -func NewQuerierWrapper(querier sdk.Queryable) QuerierWrapper { - return QuerierWrapper{querier: querier} -} - -func (q QuerierWrapper) Query(req abci.RequestQuery) abci.ResponseQuery { - return q.querier.Query(req) -} diff --git a/app/keepers/keepers.go b/app/keepers/keepers.go index 98d83897..81072bed 100644 --- a/app/keepers/keepers.go +++ b/app/keepers/keepers.go @@ -108,6 +108,8 @@ import ( "github.com/terpnetwork/terp-core/v4/x/tokenfactory/bindings" tokenfactorykeeper "github.com/terpnetwork/terp-core/v4/x/tokenfactory/keeper" tokenfactorytypes "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types" + + terpwasm "github.com/terpnetwork/terp-core/v4/internal/wasm" ) var ( @@ -118,6 +120,8 @@ var ( tokenfactorytypes.EnableForceTransfer, tokenfactorytypes.EnableSetMetadata, } + + EmptyWasmOpts []wasm.Option ) // module account permissions @@ -501,8 +505,9 @@ func NewAppKeepers( panic(fmt.Sprintf("error while reading wasm config: %s", err)) } - tfOpts := bindings.RegisterCustomPlugins(&appKeepers.BankKeeper, &appKeepers.TokenFactoryKeeper) - wasmOpts = append(wasmOpts, tfOpts...) + // custom messages for cosmwasm go here + registry := terpwasm.NewEncoderRegistry() + registry.RegisterEncoder(terpwasm.DistributionRoute, terpwasm.CustomDistributionEncoder) // Stargate Queries accepted := wasmkeeper.AcceptedStargateQueries{ @@ -530,11 +535,17 @@ func NewAppKeepers( "/osmosis.tokenfactory.v1beta1.Query/DenomAuthorityMetadata": &tokenfactorytypes.QueryDenomAuthorityMetadataResponse{}, "/osmosis.tokenfactory.v1beta1.Query/DenomsFromCreator": &tokenfactorytypes.QueryDenomsFromCreatorResponse{}, } - querierOpts := wasmkeeper.WithQueryPlugins( - &wasmkeeper.QueryPlugins{ - Stargate: wasmkeeper.AcceptListStargateQuerier(accepted, bApp.GRPCQueryRouter(), appCodec), - }) - wasmOpts = append(wasmOpts, querierOpts) + + wasmOpts = append(wasmOpts, + wasmkeeper.WithMessageEncoders(terpwasm.MessageEncoders(registry)), + wasmkeeper.WithQueryPlugins( + &wasmkeeper.QueryPlugins{ + Stargate: wasmkeeper.AcceptListStargateQuerier(accepted, bApp.GRPCQueryRouter(), appCodec), + }), + ) + + tfOpts := bindings.RegisterCustomPlugins(&appKeepers.BankKeeper, &appKeepers.TokenFactoryKeeper) + wasmOpts = append(wasmOpts, tfOpts...) appKeepers.WasmKeeper = wasmkeeper.NewKeeper( appCodec, diff --git a/app/keepers/querier.go b/app/keepers/querier.go new file mode 100644 index 00000000..993eff30 --- /dev/null +++ b/app/keepers/querier.go @@ -0,0 +1,22 @@ +package keepers + +import ( + abci "github.com/cometbft/cometbft/abci/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// QuerierWrapper is a local wrapper around BaseApp that exports only the Queryable interface. +// This is used to pass the baseApp to Async ICQ without exposing all methods +type QuerierWrapper struct { + querier sdk.Queryable +} + +var _ sdk.Queryable = QuerierWrapper{} + +func NewQuerierWrapper(querier sdk.Queryable) QuerierWrapper { + return QuerierWrapper{querier: querier} +} + +func (q QuerierWrapper) Query(req abci.RequestQuery) abci.ResponseQuery { + return q.querier.Query(req) +} diff --git a/interchaintest/helpers/cosmwasm.go b/interchaintest/helpers/cosmwasm.go index 206bdf34..61ea6094 100644 --- a/interchaintest/helpers/cosmwasm.go +++ b/interchaintest/helpers/cosmwasm.go @@ -11,21 +11,23 @@ import ( "github.com/stretchr/testify/require" ) -func SetupContract(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, keyname string, fileLoc string, message string) (codeId, contract string) { +func SetupContract(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, keyname string, fileLoc string, storeOnly bool, message string) (codeId, contract string) { codeId, err := chain.StoreContract(ctx, keyname, fileLoc) if err != nil { t.Fatal(err) } - contractAddr, err := chain.InstantiateContract(ctx, keyname, codeId, message, true) - if err != nil { - t.Fatal(err) + if !storeOnly { + contractAddr, err := chain.InstantiateContract(ctx, keyname, codeId, message, true) + if err != nil { + t.Fatal(err) + } + return codeId, contractAddr } - - return codeId, contractAddr + return codeId, "" } -func ExecuteMsgWithAmount(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, user ibc.Wallet, contractAddr, amount, message string) { +func ExecuteMsgWithAmount(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, user ibc.Wallet, contractAddr, amount, message string) string { // amount is #utoken // There has to be a way to do this in ictest? @@ -49,9 +51,10 @@ func ExecuteMsgWithAmount(t *testing.T, ctx context.Context, chain *cosmos.Cosmo if err := testutil.WaitForBlocks(ctx, 2, chain); err != nil { t.Fatal(err) } + return string(stdout) } -func ExecuteMsgWithFee(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, user ibc.Wallet, contractAddr, amount, feeCoin, message string) { +func ExecuteMsgWithFee(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, user ibc.Wallet, contractAddr, amount, feeCoin, message string) string { // amount is #utoken // There has to be a way to do this in ictest? @@ -80,4 +83,5 @@ func ExecuteMsgWithFee(t *testing.T, ctx context.Context, chain *cosmos.CosmosCh if err := testutil.WaitForBlocks(ctx, 2, chain); err != nil { t.Fatal(err) } + return string(stdout) } diff --git a/interchaintest/module_clock_test.go b/interchaintest/module_clock_test.go index fc4b00d0..bddd01f9 100644 --- a/interchaintest/module_clock_test.go +++ b/interchaintest/module_clock_test.go @@ -34,7 +34,7 @@ func TestTerpClock(t *testing.T) { user := users[0] // Upload & init contract payment to another address - _, contractAddr := helpers.SetupContract(t, ctx, terp, user.KeyName(), "contracts/clock_example.wasm", `{}`) + _, contractAddr := helpers.SetupContract(t, ctx, terp, user.KeyName(), "contracts/clock_example.wasm", false, `{}`) // Ensure config is 0 res := helpers.GetClockContractValue(t, ctx, terp, contractAddr) diff --git a/interchaintest/module_feeshare_test.go b/interchaintest/module_feeshare_test.go index 4b19851d..10165032 100644 --- a/interchaintest/module_feeshare_test.go +++ b/interchaintest/module_feeshare_test.go @@ -29,7 +29,7 @@ func TestTerpFeeShare(t *testing.T) { feeRcvAddr := "terp1v75wlkccpv7le3560zw32v2zjes5n0e7fgfzdc" // Upload & init contract payment to another address - _, contractAddr := helpers.SetupContract(t, ctx, terp, user.KeyName(), "contracts/cw_template.wasm", `{"count":0}`) + _, contractAddr := helpers.SetupContract(t, ctx, terp, user.KeyName(), "contracts/cw_template.wasm", false, `{"count":0}`) // register contract to a random address (since we are the creator, though not the admin) helpers.RegisterFeeShare(t, ctx, terp, user, contractAddr, feeRcvAddr) diff --git a/interchaintest/module_ibchooks_test.go b/interchaintest/module_ibchooks_test.go index 52ff372a..613bbad6 100644 --- a/interchaintest/module_ibchooks_test.go +++ b/interchaintest/module_ibchooks_test.go @@ -128,7 +128,7 @@ func TestTerpIBCHooks(t *testing.T) { }, ) - _, contractAddr := helpers.SetupContract(t, ctx, terp2, terp2User.KeyName(), "contracts/ibchooks_counter.wasm", `{"count":0}`) + _, contractAddr := helpers.SetupContract(t, ctx, terp2, terp2User.KeyName(), "contracts/ibchooks_counter.wasm", false, `{"count":0}`) // do an ibc transfer through the memo to the other chain. transfer := ibc.WalletAmount{ diff --git a/interchaintest/module_tokenfactory_test.go b/interchaintest/module_tokenfactory_test.go index c8850285..1f84e5c3 100644 --- a/interchaintest/module_tokenfactory_test.go +++ b/interchaintest/module_tokenfactory_test.go @@ -52,7 +52,7 @@ func TestTerpTokenFactory(t *testing.T) { // This allows the uaddr here to mint tokens on behalf of the contract. Typically you only allow a contract here, but this is testing. coreInitMsg := fmt.Sprintf(`{"allowed_mint_addresses":["%s"],"denoms":["%s"]}`, uaddr, tfDenom) - _, coreTFContract := helpers.SetupContract(t, ctx, terp, user.KeyName(), "contracts/tokenfactory_core.wasm", coreInitMsg) + _, coreTFContract := helpers.SetupContract(t, ctx, terp, user.KeyName(), "contracts/tokenfactory_core.wasm", false, coreInitMsg) t.Log("coreContract", coreTFContract) // change admin to the contract diff --git a/internal/wasm/distribution.go b/internal/wasm/distribution.go new file mode 100644 index 00000000..47d3d479 --- /dev/null +++ b/internal/wasm/distribution.go @@ -0,0 +1,47 @@ +package wasm + +import ( + "encoding/json" + "fmt" + + wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" + wasmvmtypes "github.com/CosmWasm/wasmvm/types" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types" +) + +const ( + DistributionRoute = "distribution" +) + +var _ Encoder = CustomDistributionEncoder + +type FundCommunityPool struct { + Amount wasmvmtypes.Coins `json:"amount"` +} + +func (fcp FundCommunityPool) Encode(contract sdk.AccAddress) ([]sdk.Msg, error) { + amount, err := wasmkeeper.ConvertWasmCoinsToSdkCoins(fcp.Amount) + if err != nil { + return nil, err + } + msg := distributiontypes.NewMsgFundCommunityPool(amount, contract) + return []sdk.Msg{msg}, nil +} + +type DistributionMsg struct { + FundCommunityPool *FundCommunityPool `json:"fund_community_pool,omitempty"` +} + +func CustomDistributionEncoder(contract sdk.AccAddress, data json.RawMessage, _ string) ([]sdk.Msg, error) { + msg := &DistributionMsg{} + err := json.Unmarshal(data, msg) + if err != nil { + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) + } + if msg.FundCommunityPool != nil { + return msg.FundCommunityPool.Encode(contract) + } + return nil, fmt.Errorf("wasm: invalid custom distribution message") +} diff --git a/internal/wasm/encoder.go b/internal/wasm/encoder.go new file mode 100644 index 00000000..9a258df2 --- /dev/null +++ b/internal/wasm/encoder.go @@ -0,0 +1,51 @@ +package wasm + +import ( + "encoding/json" + + "github.com/CosmWasm/wasmd/x/wasm" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +// Encoder describes behavior for Stargaze smart contract message encoding. +// The contract address must ALWAYS be set as the Msg signer. +type Encoder func(contract sdk.AccAddress, data json.RawMessage, version string) ([]sdk.Msg, error) + +// MessageEncoders provides stargaze custom encoder for contracts +func MessageEncoders(registry *EncoderRegistry) *wasm.MessageEncoders { + return &wasm.MessageEncoders{ + Custom: customEncoders(registry), + } +} + +type MessageEncodeRequest struct { + Route string `json:"route"` + MsgData json.RawMessage `json:"msg_data"` + Version string `json:"version"` +} + +func customEncoders(registry *EncoderRegistry) wasm.CustomEncoder { + return func(sender sdk.AccAddress, m json.RawMessage) ([]sdk.Msg, error) { + encodeRequest := &MessageEncodeRequest{} + err := json.Unmarshal(m, encodeRequest) + if err != nil { + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) + } + encode, exists := registry.encoders[encodeRequest.Route] + if !exists { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "encoder not found for route: %s", encodeRequest.Route) + } + + msgs, err := encode(sender, encodeRequest.MsgData, encodeRequest.Version) + if err != nil { + return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error()) + } + for _, msg := range msgs { + if err := msg.ValidateBasic(); err != nil { + return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error()) + } + } + return msgs, nil + } +} diff --git a/internal/wasm/registry.go b/internal/wasm/registry.go new file mode 100644 index 00000000..013cd092 --- /dev/null +++ b/internal/wasm/registry.go @@ -0,0 +1,22 @@ +package wasm + +import "fmt" + +type EncoderRegistry struct { + encoders map[string]Encoder +} + +// NewEncoderRegistry creates a new registry for message encoders. +func NewEncoderRegistry() *EncoderRegistry { + return &EncoderRegistry{ + encoders: make(map[string]Encoder), + } +} + +// RegisterEncoder adds a message encoder for the given route. +func (qr *EncoderRegistry) RegisterEncoder(route string, encoder Encoder) { + if _, exists := qr.encoders[route]; exists { + panic(fmt.Sprintf("wasm: encoder already registered for route: %s", route)) + } + qr.encoders[route] = encoder +} diff --git a/scripts/makefiles/build.mk b/scripts/makefiles/build.mk new file mode 100644 index 00000000..f5007aab --- /dev/null +++ b/scripts/makefiles/build.mk @@ -0,0 +1,144 @@ +############################################################################### +### Build & Install ### +############################################################################### + +build-help: + @echo "build subcommands" + @echo "" + @echo "Usage:" + @echo " make build-[command]" + @echo "" + @echo "Available Commands:" + @echo " all Build all targets" + @echo " check-version Check Go version" + @echo " dev-build Build development version" + @echo " dev-install Install development build" + @echo " linux Build for Linux" + @echo " windows Build for Windows" + @echo " reproducible Build reproducible binaries" + @echo " reproducible-amd64 Build reproducible amd64 binary" + @echo " reproducible-arm64 Build reproducible arm64 binary" + +build-check-version: + @echo "Go version: $(GO_MAJOR_VERSION).$(GO_MINOR_VERSION)" + @if [ $(GO_MAJOR_VERSION) -gt $(GO_MINIMUM_MAJOR_VERSION) ]; then \ + echo "Go version is sufficient"; \ + exit 0; \ + elif [ $(GO_MAJOR_VERSION) -lt $(GO_MINIMUM_MAJOR_VERSION) ]; then \ + echo '$(GO_VERSION_ERR_MSG)'; \ + exit 1; \ + elif [ $(GO_MINOR_VERSION) -lt $(GO_MINIMUM_MINOR_VERSION) ]; then \ + echo '$(GO_VERSION_ERR_MSG)'; \ + exit 1; \ + fi + +all: install + @echo "--> project root: go mod tidy" + @go mod tidy + @echo "--> project root: linting --fix" + @GOGC=1 golangci-lint run --fix --timeout=8m + +install: go.sum + go install -mod=readonly $(BUILD_FLAGS) ./cmd/terpd + +build: go.sum +ifeq ($(OS),Windows_NT) + $(error terpd server not supported. Use "make build-windows" for client) + exit 1 +else + go build -mod=readonly $(BUILD_FLAGS) -o build/terpd ./cmd/terpd +endif + +build-windows: go.sum + GOOS=windows GOARCH=amd64 go build -mod=readonly $(BUILD_FLAGS) -o build/terpd.exe ./cmd/terpd + +build-dev-install: go.sum + GOWORK=off go install $(DEBUG_BUILD_FLAGS) $(GC_FLAGS) $(GO_MODULE)/cmd/terpd + +build-dev-build: + mkdir -p $(BUILDDIR)/ + GOWORK=off go build $(GC_FLAGS) -mod=readonly -ldflags '$(DEBUG_LDFLAGS)' -gcflags "all=-N -l" -trimpath -o $(BUILDDIR) ./...; + +# Cross-building for arm64 from amd64 (or vice-versa) takes +# a lot of time due to QEMU virtualization but it's the only way (afaik) +# to get a statically linked binary with CosmWasm + +build-reproducible: build-reproducible-amd64 build-reproducible-arm64 + +build-reproducible-amd64: go.sum + mkdir -p $(BUILDDIR) + $(DOCKER) buildx create --name terpbuilder || true + $(DOCKER) buildx use terpbuilder + $(DOCKER) buildx build \ + --build-arg GO_VERSION=$(GO_VERSION) \ + --build-arg GIT_VERSION=$(VERSION) \ + --build-arg GIT_COMMIT=$(COMMIT) \ + --build-arg RUNNER_IMAGE=alpine:3.17 \ + --platform linux/amd64 \ + -t terp-core:local-amd64 \ + --load \ + -f Dockerfile . + $(DOCKER) rm -f terpbinary || true + $(DOCKER) create -ti --name terpbinary terpn-core:local-amd64 + $(DOCKER) cp terpbinary:/bin/terpd $(BUILDDIR)/terpd-linux-amd64 + $(DOCKER) rm -f terpbinary + +build-reproducible-arm64: go.sum + mkdir -p $(BUILDDIR) + $(DOCKER) buildx create --name terpbuilder || true + $(DOCKER) buildx use terpbuilder + $(DOCKER) buildx build \ + --build-arg GO_VERSION=$(GO_VERSION) \ + --build-arg GIT_VERSION=$(VERSION) \ + --build-arg GIT_COMMIT=$(COMMIT) \ + --build-arg RUNNER_IMAGE=alpine:3.17 \ + --platform linux/arm64 \ + -t terp-core:local-arm64 \ + --load \ + -f Dockerfile . + $(DOCKER) rm -f terpbinary || true + $(DOCKER) create -ti --name terpbinary terp-core:local-arm64 + $(DOCKER) cp osmobinary:/bin/terpd $(BUILDDIR)/terpd-linux-arm64 + $(DOCKER) rm -f terpbinary + +build-linux: go.sum + LEDGER_ENABLED=false GOOS=linux GOARCH=amd64 $(MAKE) build + + +# build-install-with-autocomplete: build-check-version go.sum +# GOWORK=off go install -mod=readonly $(BUILD_FLAGS) $(GO_MODULE)/cmd/terpd +# @PARENT_SHELL=$$(ps -o ppid= -p $$PPID | xargs ps -o comm= -p); \ +# if echo "$$PARENT_SHELL" | grep -q "zsh"; then \ +# if ! grep -q ". <(terpd enable-cli-autocomplete zsh)" ~/.zshrc; then \ +# echo ". <(terpd enable-cli-autocomplete zsh)" >> ~/.zshrc; \ +# echo; \ +# echo "Autocomplete enabled. Run 'source ~/.zshrc' to complete installation."; \ +# else \ +# echo; \ +# echo "Autocomplete already enabled in ~/.zshrc"; \ +# fi \ +# elif echo "$$PARENT_SHELL" | grep -q "bash" && [ "$$(uname)" = "Darwin" ]; then \ +# if ! grep -q -e "\. <(terpd enable-cli-autocomplete bash)" -e '\[\[ -r "/opt/homebrew/etc/profile.d/bash_completion.sh" \]\] && \. "/opt/homebrew/etc/profile.d/bash_completion.sh"' ~/.bash_profile; then \ +# brew install bash-completion; \ +# echo '[ -r "/opt/homebrew/etc/profile.d/bash_completion.sh" ] && . "/opt/homebrew/etc/profile.d/bash_completion.sh"' >> ~/.bash_profile; \ +# echo ". <(terpd enable-cli-autocomplete bash)" >> ~/.bash_profile; \ +# echo; \ +# echo; \ +# echo "Autocomplete enabled. Run 'source ~/.bash_profile' to complete installation."; \ +# else \ +# echo "Autocomplete already enabled in ~/.bash_profile"; \ +# fi \ +# elif echo "$$PARENT_SHELL" | grep -q "bash" && [ "$$(uname)" = "Linux" ]; then \ +# if ! grep -q ". <(terpd enable-cli-autocomplete bash)" ~/.bash_profile; then \ +# sudo apt-get install -y bash-completion; \ +# echo '[ -r "/etc/bash_completion" ] && . "/etc/bash_completion"' >> ~/.bash_profile; \ +# echo ". <(terpd enable-cli-autocomplete bash)" >> ~/.bash_profile; \ +# echo; \ +# echo "Autocomplete enabled. Run 'source ~/.bash_profile' to complete installation."; \ +# else \ +# echo; \ +# echo "Autocomplete already enabled in ~/.bash_profile"; \ +# fi \ +# else \ +# echo "Shell or OS not recognized. Skipping autocomplete setup."; \ +# fi \ No newline at end of file diff --git a/scripts/makefiles/deps.mk b/scripts/makefiles/deps.mk new file mode 100644 index 00000000..af1b7bc4 --- /dev/null +++ b/scripts/makefiles/deps.mk @@ -0,0 +1,45 @@ +############################################################################### +### Dependency Updates ### +############################################################################### +deps-help: + @echo "Dependency Update subcommands" + @echo "" + @echo "Usage:" + @echo " make deps-[command]" + @echo "" + @echo "Available Commands:" + @echo " clean Remove artifacts" + @echo " distclean Remove vendor directory" + @echo " draw Create a dependency graph" + @echo " go-mod-cache Download go modules to local cache" + @echo " go.sum Ensure dependencies have not been modified" + @echo " tidy-workspace Tidy workspace" + @echo " update-sdk-version Update SDK version" + + +go-mod-cache: go.sum + @echo "--> Download go modules to local cache" + @go mod download + +go.sum: go.mod + @echo "--> Ensure dependencies have not been modified" + @go mod verify + +draw-deps: + @# requires brew install graphviz or apt-get install graphviz + go install github.com/RobotsAndPencils/goviz@latest + @goviz -i ./cmd/terpd -d 2 | dot -Tpng -o dependency-graph.png + +deps-clean: + rm -rf $(CURDIR)/artifacts/ + +deps-distclean: clean + rm -rf vendor/ + +MODFILES := ./go.mod ./interchaintest/go.mod +# run with VERSION argument specified +# e.g) make update-sdk-version VERSION=v0.45.1-0.20230523200430-193959b898ec +# This will change sdk dependencyu version for go.mod in root directory + all sub-modules in this rep + +deps-tidy-workspace: + @./scripts/tidy_workspace.sh \ No newline at end of file diff --git a/scripts/makefiles/e2e.mk b/scripts/makefiles/e2e.mk new file mode 100644 index 00000000..dc8c38f4 --- /dev/null +++ b/scripts/makefiles/e2e.mk @@ -0,0 +1,66 @@ +############################################################################### +### e2e interchain test ### +############################################################################### + +e2e-help: + @echo "e2e subcommands" + @echo "" + @echo "Usage:" + @echo " make e2e-[command]" + @echo "" + @echo "Available Commands:" + @echo " build-script Build e2e script" + @echo " check-image-sha Check e2e image SHA" + @echo " docker-build-debug Build e2e debug Docker image" + @echo " docker-build-e2e-init-chain Build e2e init chain Docker image" + @echo " docker-build-e2e-init-node Build e2e init node Docker image" + @echo " remove-resources Remove e2e resources" + @echo " setup Set up e2e environment" + @echo " basic Run basic test" + @echo " upgrade Run basic planned upgrade test" + @echo " upgrade-local Run basic upgrade locally after compiling a local image as terpnetwork:local" + @echo " statesync Run basic test on node statesync capabilities" + @echo " ibc Run basic ibc test" + @echo " pfm Run basic packet-forward-middleware test" + @echo " ibchooks Run basic ibc-hooks test" + @echo " tokenfactory Run basic x/tokenfactory test" + @echo " feeshare Run basic x/feeshare test" + +e2e: e2e-help + + + # Executes basic chain tests via interchaintest +e2e-basic: rm-testcache + cd interchaintest && go test -race -v -run TestBasicTerpStart . + +e2e-statesync: rm-testcache + cd interchaintest && go test -race -v -run TestTerpStateSync . + +e2e-ibchooks: rm-testcache + cd interchaintest && go test -race -v -run TestTerpIBCHooks . + +e2e-pfm: rm-testcache + cd interchaintest && go test -race -v -run TestPacketForwardMiddlewareRouter . + +e2e-tokenfactory: rm-testcache + cd interchaintest && go test -race -v -run TestTerpTokenFactory . + +e2e-clock: rm-testcache + cd interchaintest && go test -race -v -run TestTerpClock . + +e2e-feeshare: rm-testcache + cd interchaintest && go test -race -v -run TestTerpFeeShare . + +e2e-upgrade: rm-testcache + cd interchaintest && go test -race -v -run TestBasicTerpUpgrade . + +e2e-upgrade-local: local-image ictest-upgrade + +# Executes IBC tests via interchaintest +e2e-ibc: rm-testcache + cd interchaintest && go test -race -v -run TestTerpGaiaIBCTransfer . + +rm-testcache: + go clean -testcache + +.PHONY: test-mutation ictest-basic ictest-upgrade ictest-ibc \ No newline at end of file diff --git a/scripts/makefiles/lint.mk b/scripts/makefiles/lint.mk new file mode 100644 index 00000000..85d200fa --- /dev/null +++ b/scripts/makefiles/lint.mk @@ -0,0 +1,38 @@ +############################################################################### +### Linting ### +############################################################################### + +lint-help: + @echo "" + @echo "" + @echo "lint subcommands" + @echo "" + @echo "Usage:" + @echo " make lint-[command]" + @echo "" + @echo "Available Commands:" + @echo " format-tools Run linters with auto-fix" + @echo " markdown Run markdown linter with auto-fix" + @echo " mdlint Run markdown linter" + @echo "" +# lint: lint-help + +lint-format-tools: + go install mvdan.cc/gofumpt@v0.4.0 + go install github.com/client9/misspell/cmd/misspell@v0.3.4 + go install golang.org/x/tools/cmd/goimports@latest + +lint: lint-format-tools + golangci-lint run --tests=false + find . -name '*.go' -type f -not -path "./vendor*" -not -path "*.git*" -not -path "*_test.go" | xargs gofumpt -d +format: format-tools + find . -name '*.go' -type f -not -path "./vendor*" -not -path "*.git*" -not -path "./client/lcd/statik/statik.go" | xargs gofumpt -w -s + find . -name '*.go' -type f -not -path "./vendor*" -not -path "*.git*" -not -path "./client/lcd/statik/statik.go" | xargs gofumpt -w + find . -name '*.go' -type f -not -path "./vendor*" -not -path "*.git*" -not -path "./client/lcd/statik/statik.go" | xargs goimports -w -local github.com/terpnetwork/terp-core + +lint-mdlint: + @echo "--> Running markdown linter" + @docker run -v $(PWD):/workdir ghcr.io/igorshubovych/markdownlint-cli:latest "**/*.md" + +lint-markdown: + @docker run -v $(PWD):/workdir ghcr.io/igorshubovych/markdownlint-cli:latest "**/*.md" --fix \ No newline at end of file diff --git a/scripts/makefiles/proto.mk b/scripts/makefiles/proto.mk new file mode 100644 index 00000000..4ea7a1f5 --- /dev/null +++ b/scripts/makefiles/proto.mk @@ -0,0 +1,111 @@ +############################################################################### +### Proto ### +############################################################################### + +proto-help: + @echo "proto subcommands" + @echo "" + @echo "Usage:" + @echo " make proto-[command]" + @echo "" + @echo "Available Commands:" + @echo " all Run proto-format and proto-gen" + @echo " format Format Protobuf files" + @echo " gen Generate Protobuf files" + @echo " image-build Build the protobuf Docker image" + @echo " image-push Push the protobuf Docker image" + +proto: proto-help +proto-all: proto-format proto-gen + +PROTO_BUILDER_IMAGE=ghcr.io/cosmos/proto-builder:0.14.0 +protoImage=$(DOCKER) run --rm -v $(CURDIR):/workspace --workdir /workspace $(PROTO_BUILDER_IMAGE) + +proto-all: proto-format proto-gen + +proto-gen: + @echo "Generating Protobuf files" + @$(protoImage) sh ./scripts/protocgen.sh +# generate the stubs for the proto files from the proto directory + spawn stub-gen + +proto-swagger-gen: + @$(protoImage) sh ./scripts/protoc_swagger_openapi_gen.sh + +proto-lint: + @$(protoImage) buf lint --error-format=json + +proto-format: + @echo "Formatting Protobuf files" + @$(DOCKER) run --rm -v $(CURDIR):/workspace --workdir /workspace tendermintdev/docker-build-proto \ + find ./proto -name "*.proto" -exec clang-format -i {} \; + +proto-check-breaking: + @$(CURDIR) $(protoImage) buf breaking --against $(HTTPS_GIT)#branch=main + +SWAGGER_DIR=./swagger-proto +THIRD_PARTY_DIR=$(SWAGGER_DIR)/third_party + +proto-download-deps: + mkdir -p "$(THIRD_PARTY_DIR)/cosmos_tmp" && \ + cd "$(THIRD_PARTY_DIR)/cosmos_tmp" && \ + git init && \ + git remote add origin "https://github.com/cosmos/cosmos-sdk.git" && \ + git config core.sparseCheckout true && \ + printf "proto\nthird_party\n" > .git/info/sparse-checkout && \ + git pull origin main && \ + rm -f ./proto/buf.* && \ + mv ./proto/* .. + rm -rf "$(THIRD_PARTY_DIR)/cosmos_tmp" + + mkdir -p "$(THIRD_PARTY_DIR)/ibc_tmp" && \ + cd "$(THIRD_PARTY_DIR)/ibc_tmp" && \ + git init && \ + git remote add origin "https://github.com/cosmos/ibc-go.git" && \ + git config core.sparseCheckout true && \ + printf "proto\n" > .git/info/sparse-checkout && \ + git pull origin main && \ + rm -f ./proto/buf.* && \ + mv ./proto/* .. + rm -rf "$(THIRD_PARTY_DIR)/ibc_tmp" + + mkdir -p "$(THIRD_PARTY_DIR)/cosmos_proto_tmp" && \ + cd "$(THIRD_PARTY_DIR)/cosmos_proto_tmp" && \ + git init && \ + git remote add origin "https://github.com/cosmos/cosmos-proto.git" && \ + git config core.sparseCheckout true && \ + printf "proto\n" > .git/info/sparse-checkout && \ + git pull origin main && \ + rm -f ./proto/buf.* && \ + mv ./proto/* .. + rm -rf "$(THIRD_PARTY_DIR)/cosmos_proto_tmp" + + mkdir -p "$(THIRD_PARTY_DIR)/gogoproto" && \ + curl -SSL https://raw.githubusercontent.com/cosmos/gogoproto/main/gogoproto/gogo.proto > "$(THIRD_PARTY_DIR)/gogoproto/gogo.proto" + + mkdir -p "$(THIRD_PARTY_DIR)/google/api" && \ + curl -sSL https://raw.githubusercontent.com/googleapis/googleapis/master/google/api/annotations.proto > "$(THIRD_PARTY_DIR)/google/api/annotations.proto" + curl -sSL https://raw.githubusercontent.com/googleapis/googleapis/master/google/api/http.proto > "$(THIRD_PARTY_DIR)/google/api/http.proto" + + mkdir -p "$(THIRD_PARTY_DIR)/cosmos/ics23/v1" && \ + curl -sSL https://raw.githubusercontent.com/cosmos/ics23/master/proto/cosmos/ics23/v1/proofs.proto > "$(THIRD_PARTY_DIR)/cosmos/ics23/v1/proofs.proto" + + +docs: + @echo + @echo "=========== Generate Message ============" + @echo + @make proto-download-deps + ./scripts/generate-docs.sh + + statik -src=client/docs/static -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 + @echo + @echo "=========== Generate Complete ============" + @echo +.PHONY: docs \ No newline at end of file diff --git a/scripts/makefiles/release.mk b/scripts/makefiles/release.mk new file mode 100644 index 00000000..d041c423 --- /dev/null +++ b/scripts/makefiles/release.mk @@ -0,0 +1,52 @@ +############################################################################### +### Release ### +############################################################################### + +GORELEASER_IMAGE := ghcr.io/goreleaser/goreleaser-cross:v$(GO_VERSION) +COSMWASM_VERSION := $(shell go list -m github.com/CosmWasm/wasmvm | sed 's/.* //') + +ifdef GITHUB_TOKEN +release: + docker run \ + --rm \ + -e GITHUB_TOKEN=$(GITHUB_TOKEN) \ + -e COSMWASM_VERSION=$(COSMWASM_VERSION) \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -v `pwd`:/go/src/terpd \ + -w /go/src/terpd \ + $(GORELEASER_IMAGE) \ + release \ + --clean +else +release: + @echo "Error: GITHUB_TOKEN is not defined. Please define it before running 'make release'." +endif + +release-dry-run: + docker run \ + --rm \ + -e COSMWASM_VERSION=$(COSMWASM_VERSION) \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -v `pwd`:/go/src/terpd \ + -w /go/src/terpd \ + $(GORELEASER_IMAGE) \ + release \ + --clean \ + --skip-publish + +release-snapshot: + docker run \ + --rm \ + -e COSMWASM_VERSION=$(COSMWASM_VERSION) \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -v `pwd`:/go/src/terpd \ + -w /go/src/terpd \ + $(GORELEASER_IMAGE) \ + release \ + --clean \ + --snapshot \ + --skip-validate \ + --skip-publish + +create-binaries: + \ No newline at end of file diff --git a/scripts/makefiles/tests.mk b/scripts/makefiles/tests.mk new file mode 100644 index 00000000..55b9afe9 --- /dev/null +++ b/scripts/makefiles/tests.mk @@ -0,0 +1,29 @@ +############################################################################### +### Testing ### +############################################################################### + +APP = ./app +BINDIR ?= $(GOPATH)/bin + +# The below include contains the tools and runsim targets. +include contrib/devtools/Makefile + +test: test-unit +test-all: check test-race test-cover + +test-node: + CHAIN_ID="local-1" HOME_DIR="~/.terp1" TIMEOUT_COMMIT="500ms" CLEAN=true sh scripts/test_node.sh + +test-unit: + @VERSION=$(VERSION) go test -mod=readonly -tags='ledger test_ledger_mock' ./... + +benchmark: + @go test -mod=readonly -bench=. ./... + +test-sim-multi-seed-short: runsim + @echo "Running short multi-seed application simulation. This may take awhile!" + @$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(APP) -ExitOnFail 50 5 TestFullAppSimulation + +test-sim-deterministic: runsim + @echo "Running short multi-seed application simulation. This may take awhile!" + @$(BINDIR)/runsim -Jobs=4 -SimAppPkg=$(APP) -ExitOnFail 1 1 TestAppStateDeterminism \ No newline at end of file diff --git a/scripts/release/create_binaries_json/create_all_binaries_json.sh b/scripts/release/create_binaries_json/create_all_binaries_json.sh new file mode 100644 index 00000000..dfdd1da9 --- /dev/null +++ b/scripts/release/create_binaries_json/create_all_binaries_json.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +tags=( + "v4.2.0" +) + +echo "## Upgrade binaries" + +for tag in ${tags[@]}; do + echo + echo "### ${tag}" + echo + echo '```json' + python create_binaries_json.py --tag $tag + echo '```' +done \ No newline at end of file diff --git a/scripts/release/create_binaries_json/create_binaries_json.py b/scripts/release/create_binaries_json/create_binaries_json.py new file mode 100644 index 00000000..84d9d5f7 --- /dev/null +++ b/scripts/release/create_binaries_json/create_binaries_json.py @@ -0,0 +1,118 @@ +""" +Usage: +This script generates a JSON object containing binary download URLs and their corresponding checksums +for a given release tag of terpnetwork/terp-core or from a provided checksum URL. +The binary JSON is compatible with cosmovisor and with the chain registry. + +You can run this script with the following commands: + +❯ python create_binaries_json.py --checksums_url https://github.com/terpnetwork/terp-core/releases/download/v4.2.0/sha256sum.txt + +Output: +{ + "binaries": { + "linux/arm64": "https://github.com/terpnetwork/terp-core/releases/download/16.1.1/terpd-4.2.0-linux-arm64?checksum=", + "darwin/arm64": "https://github.com/terpnetwork/terp-core/releases/download/16.1.1/terpd-4.2.0-darwin-arm64?checksum=", + "darwin/amd64": "https://github.com/terpnetwork/terp-core/releases/download/16.1.1/terpd-4.2.0-darwin-amd64?checksum=, + "linux/amd64": "https://github.com/terpnetwork/terp-core/releases/download/16.1.1/terpd-4.2.0-linux-amd64?checksum=>" + } +} + +Expects a checksum in the form: + + terpd---[.tar.gz] + terpd---[.tar.gz] +... + +Example: + +f838618633c1d42f593dc33d26b25842f5900961e987fc08570bb81a062e311d terpd-4.2.0-linux-amd64 +fa6699a763487fe6699c8720a2a9be4e26a4f45aafaec87aa0c3aced4cbdd155 terpd-4.2.0-linux-amd64.tar.gz + +(From: https://github.com/terpnetwork/terp-core/releases/download/v16.1.1/sha256sum.txt) + +❯ python create_binaries_json.py --tag v16.1.1 + +Output: +{ + "binaries": { + "linux/arm64": "https://github.com/terpnetwork/terp-core/releases/download/16.1.1/terpd-4.2.0-linux-arm64?checksum=", + "darwin/arm64": "https://github.com/terpnetwork/terp-core/releases/download/16.1.1/terpd-4.2.0-darwin-arm64?checksum=", + "darwin/amd64": "https://github.com/terpnetwork/terp-core/releases/download/16.1.1/terpd-4.2.0-darwin-amd64?checksum=", + "linux/amd64": "https://github.com/terpnetwork/terp-core/releases/download/16.1.1/terpd-4.2.0-linux-amd64?checksum=>" + } +} + +Expect a checksum to be present at: +https://github.com/terpnetwork/terp-core/releases/download//sha256sum.txt +""" + +import requests +import json +import argparse +import re +import sys + +def validate_tag(tag): + pattern = '^v[0-9]+.[0-9]+.[0-9]+$' + return bool(re.match(pattern, tag)) + +def download_checksums(checksums_url): + + response = requests.get(checksums_url) + if response.status_code != 200: + raise ValueError(f"Failed to fetch sha256sum.txt. Status code: {response.status_code}") + return response.text + +def checksums_to_binaries_json(checksums): + + binaries = {} + + # Parse the content and create the binaries dictionary + for line in checksums.splitlines(): + checksum, filename = line.split(' ') + + # exclude tar.gz files + if not filename.endswith('.tar.gz') and filename.startswith('terpd'): + try: + _, tag, platform, arch = filename.split('-') + except ValueError: + print(f"Error: Expected binary name in the form: terpd-X.Y.Z-platform-architecture, but got {filename}") + sys.exit(1) + _, tag, platform, arch, = filename.split('-') + # exclude universal binaries and windows binaries + if arch == 'all' or platform == 'windows': + continue + binaries[f"{platform}/{arch}"] = f"https://github.com/terpnetwork/terp-core/releases/download/v{tag}/{filename}?checksum=sha256:{checksum}" + + binaries_json = { + "binaries": binaries + } + + return json.dumps(binaries_json, indent=2) + +def main(): + + parser = argparse.ArgumentParser(description="Create binaries json") + parser.add_argument('--tag', metavar='tag', type=str, help='the tag to use (e.g v16.1.1)') + parser.add_argument('--checksums_url', metavar='checksums_url', type=str, help='URL to the checksum') + + args = parser.parse_args() + + # Validate the tag format + if args.tag and not validate_tag(args.tag): + print("Error: The provided tag does not follow the 'vX.Y.Z' format.") + sys.exit(1) + + # Ensure that only one of --tag or --checksums_url is specified + if not bool(args.tag) ^ bool(args.checksums_url): + parser.error("Only one of tag or --checksums_url must be specified") + sys.exit(1) + + checksums_url = args.checksums_url if args.checksums_url else f"https://github.com/terpnetwork/terp-core/releases/download/{args.tag}/sha256sum.txt" + checksums = download_checksums(checksums_url) + binaries_json = checksums_to_binaries_json(checksums) + print(binaries_json) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/scripts/release/create_binaries_json/requirements.txt b/scripts/release/create_binaries_json/requirements.txt new file mode 100644 index 00000000..e69de29b diff --git a/scripts/release/create_upgrade_guide/UPGRADE_TEMPLATE.md b/scripts/release/create_upgrade_guide/UPGRADE_TEMPLATE.md new file mode 100644 index 00000000..a84f4c8c --- /dev/null +++ b/scripts/release/create_upgrade_guide/UPGRADE_TEMPLATE.md @@ -0,0 +1,116 @@ +# Mainnet Upgrade Guide: From Version $CURRENT_VERSION to $UPGRADE_VERSION + +## Overview + +- **$UPGRADE_VERSION Proposal**: [Proposal Page](https://www.ping.pub/terp/gov/$PROPOSAL_ID) +- **$UPGRADE_VERSION Upgrade Block Height**: $UPGRADE_BLOCK +- **$UPGRADE_VERSION Upgrade Countdown**: [Block Countdown](https://testnet.itrocket.net/terp/block/$UPGRADE_BLOCK) + +## Hardware Requirements + +### Memory Specifications + +Although this upgrade is not expected to be resource-intensive, a minimum of 64GB of RAM is advised. If you cannot meet this requirement, setting up a swap space is recommended. + +#### Configuring Swap Space + +*Execute these commands to set up a 32GB swap space*: + +```sh +sudo swapoff -a +sudo fallocate -l 32G /swapfile +sudo chmod 600 /swapfile +sudo mkswap /swapfile +sudo swapon /swapfile +``` + +*To ensure the swap space persists after reboot*: + +```sh +sudo cp /etc/fstab /etc/fstab.bak +echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab +``` + +For an in-depth guide on swap configuration, please refer to [this tutorial](https://www.digitalocean.com/community/tutorials/how-to-add-swap-space-on-ubuntu-20-04). + +--- + +## Cosmovisor Configuration + +### Initial Setup (For First-Time Users) + +If you have not previously configured Cosmovisor, follow this section; otherwise, proceed to the next section. + +Cosmovisor is strongly recommended for validators to minimize downtime during upgrades. It automates the binary replacement process according to on-chain `SoftwareUpgrade` proposals. + +Documentation for Cosmovisor can be found [here](https://docs.cosmos.network/main/tooling/cosmovisor). + +#### Installation Steps + +*Run these commands to install and configure Cosmovisor*: + +```sh +go install github.com/cosmos/cosmos-sdk/cosmovisor/cmd/cosmovisor@v1.0.0 +mkdir -p ~/.terp +mkdir -p ~/.terp/cosmovisor +mkdir -p ~/.terp/cosmovisor/genesis +mkdir -p ~/.terp/cosmovisor/genesis/bin +mkdir -p ~/.terp/cosmovisor/upgrades +cp $GOPATH/bin/terpd ~/.terp/cosmovisor/genesis/bin +mkdir -p ~/.terp/cosmovisor/upgrades/$CURRENT_VERSION/bin +cp $GOPATH/bin/terpd ~/.terp/cosmovisor/upgrades/$CURRENT_VERSION/bin +``` + +*Add these lines to your profile to set up environment variables*: + +```sh +echo "# Cosmovisor Setup" >> ~/.profile +echo "export DAEMON_NAME=terpd" >> ~/.profile +echo "export DAEMON_HOME=$HOME/.terp" >> ~/.profile +echo "export DAEMON_ALLOW_DOWNLOAD_BINARIES=false" >> ~/.profile +echo "export DAEMON_LOG_BUFFER_SIZE=512" >> ~/.profile +echo "export DAEMON_RESTART_AFTER_UPGRADE=true" >> ~/.profile +echo "export UNSAFE_SKIP_BACKUP=true" >> ~/.profile +source ~/.profile +``` + +### Upgrading to $UPGRADE_VERSION + +*To prepare for the upgrade, execute these commands*: + +```sh +mkdir -p ~/.terp/cosmovisor/upgrades/$UPGRADE_VERSION/bin +cd $HOME/terp-core +git pull +git checkout $UPGRADE_TAG +make build +cp build/terpd ~/.terp/cosmovisor/upgrades/$UPGRADE_VERSION/bin +``` + +At the designated block height, Cosmovisor will automatically upgrade to version $UPGRADE_VERSION. + +--- + +## Manual Upgrade Procedure + +Follow these steps if you opt for a manual upgrade: + +1. Monitor Terp Network until it reaches the specified upgrade block height: $UPGRADE_BLOCK. +2. Observe for a panic message followed by continuous peer logs, then halt the daemon. +3. Perform these steps: + +```sh +cd $HOME/terp-core +git pull +git checkout $UPGRADE_TAG +make install +``` + +4. Restart the Terp-Core daemon and observe the upgrade. + +--- + +## Additional Resources + +- Terp Network Documentation: [Website](https://docs.terp.network) +- Community Support: [Discord](https://discord.gg/pAxjcFnAFH) diff --git a/scripts/release/create_upgrade_guide/create_upgrade_guide.py b/scripts/release/create_upgrade_guide/create_upgrade_guide.py new file mode 100644 index 00000000..8f6e5b86 --- /dev/null +++ b/scripts/release/create_upgrade_guide/create_upgrade_guide.py @@ -0,0 +1,82 @@ +import argparse +from string import Template +import argparse +import re +import sys + +# USAGE: +# +# This script generates a Mainnet Upgrade Guide using a template. It replaces variables like current_version, upgrade_version, +# proposal_id, and upgrade_block based on the arguments provided. +# +# Example: +# Run the script using the following command: +# python create_upgrade_guide.py --current_version=v18 --upgrade_version=v19 --proposal_id=606 --upgrade_block=11317300 --upgrade_tag=v19.0.0 +# +# Arguments: +# --current_version : The current version before upgrade (e.g., v18) +# --upgrade_version : The version to upgrade to (e.g., v19) +# --proposal_id : The proposal ID related to the upgrade +# --upgrade_block : The block height at which the upgrade will occur +# --upgrade_tag : The specific version tag for the upgrade (e.g., v19.0.0) +# +# This will read a template file and replace the variables in it to generate a complete Mainnet Upgrade Guide. + + +def validate_tag(tag): + pattern = '^v[0-9]+.[0-9]+.[0-9]+$' + return bool(re.match(pattern, tag)) + + +def validate_version(version): + # Regex to match 'v' followed by a number + pattern = '^v\d+$' + return bool(re.match(pattern, version)) + + +def main(): + + parser = argparse.ArgumentParser(description="Create upgrade guide from template") + parser.add_argument('--current_version', '-c', metavar='current_version', type=str, required=True, help='Current version (e.g v1)') + parser.add_argument('--upgrade_version', '-u', metavar='upgrade_version', type=str, required=True, help='Upgrade version (e.g v2)') + parser.add_argument('--upgrade_tag', '-t', metavar='upgrade_tag', type=str, required=True, help='Upgrade tag (e.g v2.0.0)') + parser.add_argument('--proposal_id', '-p', metavar='proposal_id', type=str, required=True, help='Proposal ID') + parser.add_argument('--upgrade_block', '-b', metavar='upgrade_block', type=str, required=True, help='Upgrade block height') + + args = parser.parse_args() + + if not validate_version(args.current_version): + print("Error: The provided current_version does not follow the 'vX' format.") + sys.exit(1) + + if not validate_version(args.upgrade_version): + print("Error: The provided upgrade_version does not follow the 'vX' format.") + sys.exit(1) + + if not validate_tag(args.upgrade_tag): + print("Error: The provided tag does not follow the 'vX.Y.Z' format.") + sys.exit(1) + + # Read the template from an external file + with open('UPGRADE_TEMPLATE.md', 'r') as f: + markdown_template = f.read() + + # Initialize the template + t = Template(markdown_template) + + # Substitute the variables + # Use Template.safe_substitute() over Template.substitute() + # This method won't throw an error for missing placeholders, making it suitable for partial replacements. + filled_markdown = t.safe_substitute( + CURRENT_VERSION=args.current_version, + UPGRADE_VERSION=args.upgrade_version, + UPGRADE_TAG=args.upgrade_tag, + PROPOSAL_ID=args.proposal_id, + UPGRADE_BLOCK=args.upgrade_block + ) + + print(filled_markdown) + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/scripts/replace_import_paths.sh b/scripts/replace_import_paths.sh new file mode 100644 index 00000000..6b850767 --- /dev/null +++ b/scripts/replace_import_paths.sh @@ -0,0 +1,61 @@ +#!/bin/bash + +set -euo pipefail + +NEXT_MAJOR_VERSION=$1 +import_path_to_replace=$(go list -m) + +version_to_replace=$(echo $import_path_to_replace | sed -n 's/.*v\([0-9]*\).*/\1/p') + +echo $version_to_replace +echo Current import paths are $version_to_replace, replacing with $NEXT_MAJOR_VERSION + +# list all folders containing Go modules. +modules=$(go list -tags e2e ./... | sed "s/g.*v${version_to_replace}\///") + +while IFS= read -r line; do + modules_to_upgrade_manually+=("$line") +done < <(find . -name go.mod -exec grep -l "github.com/terpnetwork/terp-core/v4" {} \; | grep -v "^./go.mod$" | sed 's|/go.mod||' | sed 's|^./||') + +replace_paths() { + file="${1}" + sed -i "s/github.com\/terpnetwork\/terp-core/v4\/v${version_to_replace}/github.com\/terpnetwork\/terp-core/v4\/v${NEXT_MAJOR_VERSION}/g" ${file} +} + +echo "Replacing import paths in all files" + +while IFS= read -r line; do + files+=("$line") +done < <(find ./ -type f -not \( -path "./vendor*" -or -path "./.git*" -or -name "*.md" \)) + +echo "Updating all files" + +for file in "${files[@]}"; do + if test -f "$file"; then + # skip files that need manual upgrading + for excluded_file in "${modules_to_upgrade_manually[@]}"; do + if [[ "$file" == *"$excluded_file"* ]]; then + continue 2 + fi + done + replace_paths $file + fi +done + +exit 0 + +echo "Updating go.mod and vendoring" +# go.mod +replace_paths "go.mod" +go mod vendor >/dev/null + +# ensure that generated files are updated. +# N.B.: This must be run after go mod vendor. +echo "running make proto-gen" +make proto-gen >/dev/null + +echo "Run go mod vendor after proto-gen to avoid vendoring issues" +go mod vendor >/dev/null + +echo "running make run-querygen" +make run-querygen >/dev/null \ No newline at end of file