diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 5876e9f8d17..543364c78ba 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -8,6 +8,10 @@ updates: interval: "daily" labels: - "github_actions" + groups: + actions: + patterns: + - "*" # Maintain dependencies for top level Go modules - package-ecosystem: gomod diff --git a/.github/golangci.yml b/.github/golangci.yml index 6f2d808932f..8b38691ec75 100644 --- a/.github/golangci.yml +++ b/.github/golangci.yml @@ -60,17 +60,6 @@ linters-settings: - opinionated - performance - style - gomodguard: - blocked: - modules: - - log/slog: - recommendations: - - golang.org/x/exp - reason: "the minimum go version for the monorepo is 1.20" - versions: - - go.uber.org/zap/exp: - version: "> 0.1.0" - reason: "this version of zap/exp is a requirement until we upgrade to go 1.21 (https://github.com/uber-go/zap/blob/master/exp/CHANGELOG.md)" issues: whole-files: true @@ -86,4 +75,4 @@ issues: - goconst # Disabled linting of common mnemonics and test case strings - path: _\.gno linters: - - errorlint # Disabled linting of error comparisons, because of lacking std lib support \ No newline at end of file + - errorlint # Disabled linting of error comparisons, because of lacking std lib support diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 63490c0bfa1..17e1456e24a 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -19,7 +19,7 @@ jobs: fetch-depth: 1 - uses: actions/setup-go@v4 with: - go-version: "1.21.x" + go-version: "1.22.x" - name: "gobenchdata publish: ${{ inputs.publish }}" run: go run go.bobheadxi.dev/gobenchdata@v1 action env: diff --git a/.github/workflows/codegen.yml b/.github/workflows/codegen.yml index f941dd69855..d516b67cc10 100644 --- a/.github/workflows/codegen.yml +++ b/.github/workflows/codegen.yml @@ -20,7 +20,7 @@ jobs: - name: Install Go uses: actions/setup-go@v4 with: - go-version: 1.21.x + go-version: 1.22.x - name: Checkout code uses: actions/checkout@v4 diff --git a/.github/workflows/contribs.yml b/.github/workflows/contribs.yml index e3bada1e195..f86680e667e 100644 --- a/.github/workflows/contribs.yml +++ b/.github/workflows/contribs.yml @@ -21,7 +21,7 @@ jobs: fail-fast: false matrix: goversion: # two latest versions - - "1.21.x" + - "1.22.x" program: - "gnomd" - "gnodev" diff --git a/.github/workflows/db-tests.yml b/.github/workflows/db-tests.yml index b259a0bcf74..3f2544378fd 100644 --- a/.github/workflows/db-tests.yml +++ b/.github/workflows/db-tests.yml @@ -21,8 +21,8 @@ jobs: fail-fast: false matrix: goversion: - - "1.20.x" - "1.21.x" + - "1.22.x" tags: - cleveldb - memdb diff --git a/.github/workflows/dependabot-tidy.yml b/.github/workflows/dependabot-tidy.yml index 8234de91924..489fb950ba6 100644 --- a/.github/workflows/dependabot-tidy.yml +++ b/.github/workflows/dependabot-tidy.yml @@ -20,7 +20,7 @@ jobs: - name: Install Go uses: actions/setup-go@v4 with: - go-version: 1.21.x + go-version: 1.22.x - name: Tidy all Go mods env: diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 35917d38e99..29dad80b3c6 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -22,8 +22,8 @@ jobs: fail-fast: false matrix: goversion: - - "1.20.x" - "1.21.x" + - "1.22.x" runs-on: ubuntu-latest timeout-minutes: 30 steps: @@ -38,8 +38,8 @@ jobs: fail-fast: false matrix: goversion: - - "1.20.x" - "1.21.x" + - "1.22.x" # unittests: TODO: matrix with contracts runs-on: ubuntu-latest timeout-minutes: 30 @@ -63,8 +63,8 @@ jobs: fail-fast: false matrix: goversion: - - "1.20.x" - "1.21.x" + - "1.22.x" # unittests: TODO: matrix with contracts runs-on: ubuntu-latest timeout-minutes: 10 @@ -84,7 +84,7 @@ jobs: strategy: fail-fast: false matrix: - go-version: [ "1.21.x" ] + go-version: [ "1.22.x" ] # unittests: TODO: matrix with contracts runs-on: ubuntu-latest timeout-minutes: 10 diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml index dea849fbb4d..3964f3d5e7b 100644 --- a/.github/workflows/gh-pages.yml +++ b/.github/workflows/gh-pages.yml @@ -23,7 +23,7 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-go@v4 with: - go-version: "1.21.x" + go-version: "1.22.x" - run: "cd misc/gendocs && make install gen" - uses: actions/configure-pages@v4 id: pages diff --git a/.github/workflows/gnoland.yml b/.github/workflows/gnoland.yml index 25b14c0db04..58ec7b480d1 100644 --- a/.github/workflows/gnoland.yml +++ b/.github/workflows/gnoland.yml @@ -28,8 +28,8 @@ jobs: fail-fast: false matrix: goversion: - - "1.20.x" - "1.21.x" + - "1.22.x" goarch: [ "amd64" ] goos: [ "linux" ] program: @@ -37,7 +37,6 @@ jobs: - gnokey - gnoweb - gnofaucet - - gnotxsync runs-on: ubuntu-latest timeout-minutes: 5 steps: @@ -54,8 +53,8 @@ jobs: fail-fast: false matrix: goversion: - - "1.20.x" - "1.21.x" + - "1.22.x" args: - _test.gnoland - _test.gnokey @@ -83,7 +82,7 @@ jobs: export GOTEST_FLAGS="-v -p 1 -timeout=30m -coverprofile=coverage.out -covermode=atomic" make ${{ matrix.args }} - uses: actions/upload-artifact@v3 - if: ${{ runner.os == 'Linux' && matrix.goversion == '1.21.x' }} + if: ${{ runner.os == 'Linux' && matrix.goversion == '1.22.x' }} with: name: ${{runner.os}}-coverage-gnoland-${{ matrix.args}}-${{matrix.goversion}} path: ./gno.land/coverage.out @@ -116,6 +115,9 @@ jobs: timeout-minutes: 10 steps: - uses: actions/checkout@v4 + - uses: actions/setup-go@v4 + with: + go-version: 1.22.x # TODO: setup docker caching - run: make test.docker - run: docker logs int_gnoland || true diff --git a/.github/workflows/gnovm.yml b/.github/workflows/gnovm.yml index 15e0f886e1b..4f9d32e99f9 100644 --- a/.github/workflows/gnovm.yml +++ b/.github/workflows/gnovm.yml @@ -30,8 +30,8 @@ jobs: fail-fast: false matrix: goversion: # two latest versions - - "1.20.x" - "1.21.x" + - "1.22.x" goenv: # TODO: replace with pairs, so it's easier to read in the GH interface. - "GOARCH=amd64 GOOS=linux" - "GOARCH=wasm GOOS=js" @@ -53,8 +53,8 @@ jobs: fail-fast: false matrix: goversion: - - "1.20.x" - "1.21.x" + - "1.22.x" args: - _test.cmd - _test.pkg @@ -96,7 +96,7 @@ jobs: # Run target test make ${{ matrix.args }} - uses: actions/upload-artifact@v3 - if: ${{ runner.os == 'Linux' && matrix.goversion == '1.21.x' }} + if: ${{ runner.os == 'Linux' && matrix.goversion == '1.22.x' }} with: name: ${{runner.os}}-coverage-gnovm-${{ matrix.args}}-${{matrix.goversion}} path: ${{ env.COVERAGE_DIR }} @@ -122,7 +122,7 @@ jobs: path: ${{ env.COVERAGE_DATA }} - uses: actions/setup-go@v4 with: - go-version: "1.21.x" + go-version: "1.22.x" - name: Merge coverages working-directory: ${{ env.COVERAGE_DATA }} run: | diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index b417e904e7c..bcfc779c7cf 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -19,7 +19,7 @@ jobs: - name: Install Go uses: actions/setup-go@v4 with: - go-version: 1.21.x + go-version: 1.22.x - name: Lint uses: golangci/golangci-lint-action@v3 @@ -37,7 +37,7 @@ jobs: - name: Install Go uses: actions/setup-go@v4 with: - go-version: 1.21.x + go-version: 1.22.x - name: Install make run: sudo apt-get install -y make @@ -68,7 +68,7 @@ jobs: - name: Install Go uses: actions/setup-go@v4 with: - go-version: 1.21.x + go-version: 1.22.x - name: Install make run: sudo apt-get install -y make diff --git a/.github/workflows/misc.yml b/.github/workflows/misc.yml index 52329e9c7d6..7b7d520e82d 100644 --- a/.github/workflows/misc.yml +++ b/.github/workflows/misc.yml @@ -27,7 +27,7 @@ jobs: fail-fast: false matrix: goversion: - - "1.21.x" + - "1.22.x" program: - "genstd" runs-on: ubuntu-latest @@ -49,7 +49,7 @@ jobs: fail-fast: false matrix: goversion: - - "1.21.x" + - "1.22.x" args: - _test.genstd runs-on: ubuntu-latest diff --git a/.github/workflows/tm2.yml b/.github/workflows/tm2.yml index bbe379bb069..a3b02671eb7 100644 --- a/.github/workflows/tm2.yml +++ b/.github/workflows/tm2.yml @@ -26,8 +26,8 @@ jobs: fail-fast: false matrix: goversion: - - "1.20.x" - "1.21.x" + - "1.22.x" goarch: [ "amd64" ] goos: [ "linux" ] program: [ "./pkg/amino/cmd/aminoscan", "./pkg/amino/cmd/goscan", "./pkg/autofile/cmd", "./pkg/iavl/cmd/iaviewer" ] @@ -48,8 +48,8 @@ jobs: fail-fast: false matrix: goversion: - - "1.20.x" - "1.21.x" + - "1.22.x" args: - _test.flappy - _test.pkg.amino @@ -78,7 +78,7 @@ jobs: make ${{ matrix.args }} touch coverage.out - uses: actions/upload-artifact@v3 - if: ${{ runner.os == 'Linux' && matrix.goversion == '1.21.x' }} + if: ${{ runner.os == 'Linux' && matrix.goversion == '1.22.x' }} with: name: ${{runner.os}}-coverage-tm2-${{ matrix.args}}-${{matrix.goversion}} path: ./tm2/coverage.out diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a3f34b8a85e..369c3a7d6e7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -52,18 +52,18 @@ Likewise, if you have an idea on how to improve this guide, go for it as well. ### Environment -The gno repository is primarily based on Golang (Go) and Gnolang (Gno). +The gno repository is primarily based on Go (Golang) and Gno. The primary tech stack for working on the repository: -- Go (version 1.20+) +- Go (version 1.21+) - make (for using Makefile configurations) It is recommended to work on a Unix environment, as most of the tooling is built around ready-made tools in Unix (WSL2 for Windows / Linux / macOS). For Gno, there is no specific tooling that needs to be installed, that’s not already provided with the repo itself. -You can utilize the `gno` command to facilitate Gnolang support when writing Smart Contracts in Gno, by installing it +You can utilize the `gno` command to facilitate Gno support when writing Smart Contracts in Gno, by installing it with `make install_gno`. If you are working on Go source code on this repository, `pkg.go.dev` will not @@ -149,16 +149,16 @@ if (executable('gnols')) else echomsg 'gnols binary not found: LSP disabled for Gno files' endif - + function! s:on_lsp_buffer_enabled() abort " Autocompletion setlocal omnifunc=lsp#complete " Format on save autocmd BufWritePre LspDocumentFormatSync " Some optional mappings - nmap i (lsp-hover) + nmap i (lsp-hover) " Following mappings are not supported yet by gnols - " nmap gd (lsp-definition) + " nmap gd (lsp-definition) " nmap rr (lsp-rename) endfunction augroup lsp_install diff --git a/Dockerfile b/Dockerfile index 9e7fc48dcb0..d55771e904d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # build -FROM golang:1.21 AS build +FROM golang:1.22 AS build RUN mkdir -p /opt/gno/src /opt/build WORKDIR /opt/build ADD go.mod go.sum ./ @@ -10,7 +10,6 @@ RUN go build -o ./build/gnokey ./gno.land/cmd/gnokey RUN go build -o ./build/gnofaucet ./gno.land/cmd/gnofaucet RUN go build -o ./build/gnoweb ./gno.land/cmd/gnoweb RUN go build -o ./build/gno ./gnovm/cmd/gno -RUN go build -o ./build/gnotxsync ./gno.land/cmd/gnotxsync RUN ls -la ./build ADD . /opt/gno/src/ RUN rm -rf /opt/gno/src/.git @@ -43,10 +42,6 @@ COPY --from=build /opt/build/build/gnofaucet /opt/gno/bin/ ENTRYPOINT ["gnofaucet"] EXPOSE 5050 -FROM runtime-tls AS gnotxsync-slim -COPY --from=build /opt/build/build/gnotxsync /opt/gno/bin/ -ENTRYPOINT ["gnotxsync"] - FROM runtime-tls AS gnoweb-slim COPY --from=build /opt/build/build/gnoweb /opt/gno/bin/ COPY --from=build /opt/gno/src/gno.land/cmd/gnoweb /opt/gno/src/gnoweb diff --git a/Makefile b/Makefile index dc3f8e47089..15fef433b75 100644 --- a/Makefile +++ b/Makefile @@ -1,20 +1,37 @@ .PHONY: help help: @echo "Available make commands:" - @cat Makefile | grep '^[a-z][^:]*:' | cut -d: -f1 | sort | sed 's/^/ /' + @cat Makefile | grep '^[a-z][^:]*:' | grep -v 'install_' | cut -d: -f1 | sort | sed 's/^/ /' rundep=go run -modfile misc/devdeps/go.mod .PHONY: install -install: install_gnokey install_gno +install: install.gnokey install.gno + @if ! command -v gnodev > /dev/null; then \ + echo ------------------------------; \ + echo "For local realm development, gnodev is recommended: https://docs.gno.land/gno-tooling/cli/gno-tooling-gnodev"; \ + echo "You can install it by calling 'make install.gnodev'"; \ + fi # shortcuts to frequently used commands from sub-components. -install_gnokey: +.PHONY: install.gnokey +install.gnokey: $(MAKE) --no-print-directory -C ./gno.land install.gnokey @echo "[+] 'gnokey' is installed. more info in ./gno.land/." -install_gno: +.PHONY: install.gno +install.gno: $(MAKE) --no-print-directory -C ./gnovm install @echo "[+] 'gno' is installed. more info in ./gnovm/." +.PHONY: install.gnodev +install.gnodev: + $(MAKE) --no-print-directory -C ./contribs install.gnodev + @echo "[+] 'gnodev' is installed." + +# old aliases +.PHONY: install_gnokey +install_gnokey: install.gnokey +.PHONY: install_gno +install_gno: install.gno .PHONY: test test: test.components test.docker diff --git a/README.md b/README.md index cc5931de8ef..987a24f5b66 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,6 @@ repository offers more resources to dig into. We are eager to see your first PR! Developer commands: * [gno](./gnovm/cmd/gno) - handy tool for developing gno packages & realms - * [gnotxsync](./gno.land/cmd/gnotxsync) - importing/exporting transactions from local blockchain node storage * [goscan](./misc/goscan) - dumps imports from specified file’s AST * [genproto](./misc/genproto) - helper for generating .proto implementations * [gnofaucet](./gno.land/cmd/gnofaucet) - serves GNOT faucet diff --git a/contribs/gnodev/go.mod b/contribs/gnodev/go.mod index 71838979ec4..30069312ae4 100644 --- a/contribs/gnodev/go.mod +++ b/contribs/gnodev/go.mod @@ -1,14 +1,13 @@ module github.com/gnolang/gno/contribs/gnodev -go 1.20 +go 1.21 replace github.com/gnolang/gno => ../.. require ( github.com/fsnotify/fsnotify v1.7.0 github.com/gnolang/gno v0.0.0-00010101000000-000000000000 - go.uber.org/zap v1.24.0 - golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 + go.uber.org/zap v1.26.0 golang.org/x/term v0.16.0 ) @@ -56,9 +55,8 @@ require ( github.com/zondax/ledger-go v0.14.3 // indirect go.etcd.io/bbolt v1.3.8 // indirect go.opencensus.io v0.22.5 // indirect - go.uber.org/atomic v1.10.0 // indirect go.uber.org/multierr v1.10.0 // indirect - go.uber.org/zap/exp v0.1.0 // indirect + go.uber.org/zap/exp v0.2.0 // indirect golang.org/x/crypto v0.18.0 // indirect golang.org/x/mod v0.14.0 // indirect golang.org/x/net v0.20.0 // indirect diff --git a/contribs/gnodev/go.sum b/contribs/gnodev/go.sum index ca5774fa7ad..7f27a8e0e22 100644 --- a/contribs/gnodev/go.sum +++ b/contribs/gnodev/go.sum @@ -6,7 +6,6 @@ github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= 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 h1:V2/ZgjfDFIygAX3ZapeigkVBoVUtOJKSwrhZdlpSvaA= @@ -22,6 +21,7 @@ github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9E github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 h1:KdUfX2zKommPRa+PD0sWZUyXe9w277ABlgELO7H04IM= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/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= @@ -51,6 +51,7 @@ 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/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= @@ -64,9 +65,13 @@ github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUn github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c h1:8ISkoahWXwZR41ois5lSJBSVw4D0OV19Ht/JSTzvSv0= +github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= +github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk= +github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= 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.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= @@ -105,7 +110,9 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 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/gorilla/csrf v1.7.0/go.mod h1:+a/4tCmqhG6/w4oafeAZ9pEa3/NZOWYVbD9fV0FwIQA= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= @@ -139,7 +146,9 @@ github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfn github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/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/linxGnu/grocksdb v1.8.11 h1:BGol9e5gB1BrsTvOxloC88pe70TCqgrfLNwkyWW0kD8= @@ -149,6 +158,7 @@ github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= +github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= @@ -204,15 +214,14 @@ go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA= go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= go.opencensus.io v0.22.5 h1:dntmOdLpSpHlVqbW5Eay97DelsZHe+55D+xC6i0dDS0= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= -go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= +go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= +go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= -go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= -go.uber.org/zap/exp v0.1.0 h1:Ol9zQNvAEAgFHSBiR5LlwS9Xq8u5QF+7HBwNHUB8rcI= -go.uber.org/zap/exp v0.1.0/go.mod h1:z/0T3As39ttolxZGOsvk1OEvQfwwfTZpmV9YTp+VAkc= +go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +go.uber.org/zap/exp v0.2.0 h1:FtGenNNeCATRB3CmB/yEUnjEFeJWpB/pMcy7e2bKPYs= +go.uber.org/zap/exp v0.2.0/go.mod h1:t0gqAIdh1MfKv9EwN/dLwfZnJxe9ITAZN78HEWPFWDQ= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -221,8 +230,6 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 h1:hNQpMuAJe5CtcUqCXaWga3FHu+kQvCqcsoVaQgSV60o= -golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -311,6 +318,7 @@ google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= @@ -319,6 +327,7 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/contribs/gnodev/pkg/dev/node.go b/contribs/gnodev/pkg/dev/node.go index c1eddc7c91d..0b271c14636 100644 --- a/contribs/gnodev/pkg/dev/node.go +++ b/contribs/gnodev/pkg/dev/node.go @@ -3,6 +3,7 @@ package dev import ( "context" "fmt" + "log/slog" "github.com/gnolang/gno/gno.land/pkg/gnoland" "github.com/gnolang/gno/gno.land/pkg/integration" @@ -16,7 +17,6 @@ import ( bft "github.com/gnolang/gno/tm2/pkg/bft/types" "github.com/gnolang/gno/tm2/pkg/crypto" "github.com/gnolang/gno/tm2/pkg/std" - "golang.org/x/exp/slog" // backup "github.com/gnolang/tx-archive/backup/client" // restore "github.com/gnolang/tx-archive/restore/client" ) diff --git a/contribs/gnokeykc/go.mod b/contribs/gnokeykc/go.mod index 732bececda4..b3b3f9d7c36 100644 --- a/contribs/gnokeykc/go.mod +++ b/contribs/gnokeykc/go.mod @@ -1,6 +1,6 @@ module github.com/gnolang/gno/contribs/gnokeykc -go 1.20 +go 1.21 replace github.com/gnolang/gno => ../.. @@ -50,7 +50,6 @@ require ( go.etcd.io/bbolt v1.3.8 // indirect go.opencensus.io v0.22.5 // indirect golang.org/x/crypto v0.18.0 // indirect - golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 // indirect golang.org/x/mod v0.14.0 // indirect golang.org/x/net v0.20.0 // indirect golang.org/x/sys v0.16.0 // indirect diff --git a/contribs/gnokeykc/go.sum b/contribs/gnokeykc/go.sum index 4a2778e7919..f452a99a5ad 100644 --- a/contribs/gnokeykc/go.sum +++ b/contribs/gnokeykc/go.sum @@ -23,6 +23,7 @@ github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9E github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 h1:KdUfX2zKommPRa+PD0sWZUyXe9w277ABlgELO7H04IM= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/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= @@ -52,6 +53,7 @@ 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/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= @@ -65,9 +67,13 @@ github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUn github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c h1:8ISkoahWXwZR41ois5lSJBSVw4D0OV19Ht/JSTzvSv0= +github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= +github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk= +github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= @@ -107,7 +113,9 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 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/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= @@ -128,8 +136,8 @@ github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8 github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 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/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/linxGnu/grocksdb v1.8.11 h1:BGol9e5gB1BrsTvOxloC88pe70TCqgrfLNwkyWW0kD8= @@ -139,6 +147,7 @@ github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= +github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= @@ -172,6 +181,7 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -203,8 +213,6 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 h1:hNQpMuAJe5CtcUqCXaWga3FHu+kQvCqcsoVaQgSV60o= -golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -291,6 +299,7 @@ google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= @@ -299,6 +308,7 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/contribs/gnomd/go.mod b/contribs/gnomd/go.mod index b631040ce94..1c22a07da31 100644 --- a/contribs/gnomd/go.mod +++ b/contribs/gnomd/go.mod @@ -1,6 +1,6 @@ module github.com/gnolang/gno/contribs/gnomd -go 1.20 +go 1.21 require github.com/MichaelMure/go-term-markdown v0.1.4 diff --git a/docs/concepts/effective-gno.md b/docs/concepts/effective-gno.md new file mode 100644 index 00000000000..ca593edf212 --- /dev/null +++ b/docs/concepts/effective-gno.md @@ -0,0 +1,684 @@ +--- +id: effective-gno +--- + +# Effective Gno + +Welcome to the guide for writing effective Gno code. This document is designed +to help you understand the nuances of Gno and how to use it effectively. + +Before we dive in, it's important to note that Gno shares several similarities +with Go. Therefore, if you haven't already, we highly recommend reading +["Effective Go"](https://go.dev/doc/effective_go) as a primer. + +## Disclaimer + +Gno is a young language. The practices we've identified are based on its current +state. As Gno evolves, new practices will emerge and some current ones may +become obsolete. We welcome your contributions and feedback. Stay updated and +help shape Gno's future! + +## Counter-intuitive good practices + +This section highlights some Gno good practices that might seem +counter-intuitive, especially if you're coming from a Go background. + +### Embrace global variables in realms + +In Gno, using global variables is not only acceptable, but also encouraged, +specifically when working with realms. This is due to the unique persistence +feature of realms. + +In Go, you would typically write your logic and maintain some state in memory. +However, to persist the state and ensure it survives a restart, you would need +to use a store (like a plain file, custom file structure, a database, a +key-value store, an API, etc.). + +In contrast, Gno simplifies this process. When you declare global variables in +Gno realms, the GnoVM automatically persists and restores them as needed between +each run. This means that the state of these variables is maintained across +different executions of the realm, providing a simple and efficient way to +manage state persistence. + +However, it's important to note that this practice is not a blanket +recommendation for all Gno code. It's specifically beneficial in the context of +realms due to their persistent characteristics. In other Gno code, such as +packages, the use of global variables is actually discouraged and may even be +completely disabled in the future. Instead, packages should use global +constants, which provide a safe and reliable way to define values that don't +change. + +Also, be mindful not to export your global variables. Doing so would make them +accessible for everyone to read and write, potentially leading to unintended +side effects. Instead, consider using getters and setters to control access to +these variables, as shown in the following pattern: + +```go +// private global variable. +var counter int + +// public getter endpoint. +func GetCounter() int { + return counter +} + +// public setter endpoint. +func IncCounter() { + counter++ +} +``` + +In this example, `GetCounter` and `IncCounter` are used to read and increment +the `counter` variable, respectively. This allows you to control how the +`counter` variable is accessed and modified, ensuring that it's used correctly +and securely. + +### Embrace `panic` + +In Gno, we have a slightly different approach to handling errors compared to Go. +While the famous [quote by Rob +Pike](https://github.com/golang/go/wiki/CodeReviewComments#dont-panic) advises +Go developers "Don't panic.", in Gno, we actually embrace `panic`. + +Panic in Gno is not just for critical errors or programming mistakes as it is in +Go. Instead, it's used as a control flow mechanism to stop the execution of a +[realm](realms.md) when something goes wrong. This could be due to an invalid input, a +failed precondition, or any other situation where it's not possible or desirable +to continue executing the contract. + +So, while in Go, you should avoid `panic` and handle `error`s gracefully, in Gno, +don't be afraid to use `panic` to enforce contract rules and protect the integrity +of your contract's state. Remember, a well-placed panic can save your contract +from a lot of trouble. + +When you return an `error` in Gno, it's like giving back any other piece of data. +It tells you something went wrong, but it doesn't stop your code or undo any +changes you made. + +But, when you use `panic` in Gno, it stops your code right away, says it failed, +and doesn't save any changes you made. This is safer when you want to stop +everything and not save wrong changes. + +In Gno, the use of `panic()` and `error` should be context-dependent to ensure +clarity and proper error handling: +- Use `panic()` to immediately halt execution and roll back the transaction when + encountering critical issues or invalid inputs that cannot be recovered from. +- Return an `error` when the situation allows for the possibility of recovery or + when the caller should decide how to handle the error. + +Consequently, reusable packages should avoid `panic()` except in assert-like +functions, such as `Must*` or `Assert*`, which are explicit about their +behavior. Packages should be designed to be flexible and not impose restrictions +that could lead to user frustration or the need to fork the code. + +```go +import "std" + +func Foobar() { + caller := std.PrevRealm().Addr() + if caller != "g1xxxxx" { + panic("permission denied") + } + // ... +} +``` + +- TODO: suggest MustXXX and AssertXXX flows in p/. + +### Understand the importance of `init()` + +In Gno, the `init()` function isn't just a function, it's a cornerstone. It's +automatically triggered when a new realm is added onchain, making it a one-time +setup tool for the lifetime of a realm. In essence, `init()` acts as a +constructor for your realm. + +Unlike Go, where `init()` is used for tasks like setting up database +connections, configuring logging, or initializing global variables every time +you start a program, in Gno, `init()` is executed once in a realm's lifetime. + +In Gno, `init()` primarily serves two purposes: +1. It establishes the initial state, specifically, setting up global variables. + - Note: global variables can often be set up just by assigning their initial value when you're declaring them. See below for an example! \ + Deciding when to initialise the variable directly, and when to set it up in `init` can be non-straightforward. As a rule of thumb, though, `init` visually marks the code as executing only when the realm is started, while assigning the variables can be less straightforward. +2. It communicates with another realm, for example, to register itself in a registry. + +```go +import "gno.land/r/some/registry" + +func init() { + registry.Register("myID", myCallback) +} + +func myCallback(a, b string) { /* ... */ } +``` + +A common use case could be to set the "admin" as the caller uploading the +package. + +```go +import ( + "std" + "time" +) + +var ( + created time.Time + admin std.Address + list = []string{"foo", "bar", time.Now().Format("15:04:05")} +) + +func init() { + created = time.Now() + // std.GetOrigCaller in the context of realm initialisation is, + // of course, the publisher of the realm :) + // This can be better than hardcoding an admin address as a constant. + admin = std.GetOrigCaller() + // list is already initialized, so it will already contain "foo", "bar" and + // the current time as existing items. + list = append(list, admin.String()) +} +``` + +In essence, `init()` in Gno is your go-to function for setting up and +registering realms. It's a powerful tool that helps keep your realms organized +and properly configured from the get-go. Acting as a constructor, it sets the +stage for the rest of your realm's lifetime. + +### A little dependency is better than a little copying + +In Go, there's a well-known saying by Rob Pike: ["A little copying is better +than a little dependency"](https://www.youtube.com/watch?v=PAAkCSZUG1c&t=568s). +This philosophy encourages developers to minimize their dependencies and instead +copy small amounts of code where necessary. While this approach often makes +sense in Go, it's not always the best strategy in Gno. + +In Gno, especially for `p/` packages, another philosophy prevails, one that is +more akin to the Node/NPM ecosystem. This philosophy encourages creating small +modules and leveraging multiple dependencies. The main reason for this shift is +code readability and trust. + +A Gno contract is not just its lines of code, but also the imports it uses. More +importantly, Gno contracts are not just for developers. For the first time, it +makes sense for users to see what functionality they are executing too. Code simplicity, transparency, +explicitness, and trustability are paramount. + +Another good reason for creating simple, focused libraries is the composability +of Go and Gno. Essentially, you can think of each `p/` package as a Lego brick +in an ever-growing collection, giving more power to users. `p/` in Gno is +basically a way to extend the standard libraries in a community-driven manner. + +Unlike other compiled languages where dependencies are not always well-known and +clear metrics are lacking, Gno allows for a reputation system not only for the +called contracts, but also for the dependencies. + +For example, you might choose to use well-crafted `p/` packages that have been +reviewed, audited, and have billions of transactions under their belt, boasting +super high stability. This approach can make your code footprint smaller and more +reliable. + +In other platforms, an audit usually involves auditing everything, including the +dependencies. However, in Gno, we can expect that over time, contracts will +become smaller, more powerful, and partially audited by default, thanks to this +enforced open-source system. + +One key difference between the Go and Gno ecosystem is the trust assumption when +adding a new dependency. Dependency code always needs to be vetted, [regardless +of what programming language or ecosystem you're using][sc-attack]. However, in +Gno, you can have the certainty that the author of a package cannot overwrite an +existing, published contract; as that is simply disallowed by the blockchain. In +other words, using existing and widely-used packages reinforces your security +rather than harming it. +[sc-attack]: https://en.wikipedia.org/wiki/Supply_chain_attack + +So, while you can still adhere to the original philosophy of minimizing +dependencies, ultimately, try to use and write super stable, simple, tested, +and focused `p/` small libraries. This approach can lead to more reliable, +efficient, and trustworthy Gno contracts. + +```go +import ( + "gno.land/p/finance/tokens" + "gno.land/p/finance/exchange" + "gno.land/p/finance/wallet" + "gno.land/p/utils/permissions" +) + +var ( + myWallet wallet.Wallet + myToken tokens.Token + myExchange exchange.Exchange +) + +func init() { + myWallet = wallet.NewWallet() + myToken = tokens.NewToken("MyToken", "MTK") + myExchange = exchange.NewExchange(myToken) +} + +func BuyTokens(amount int) { + caller := permissions.GetCaller() + permissions.CheckPermission(caller, "buy") + myWallet.Debit(caller, amount) + myExchange.Buy(caller, amount) +} + +func SellTokens(amount int) { + caller := permissions.GetCaller() + permissions.CheckPermission(caller, "sell") + myWallet.Credit(caller, amount) + myExchange.Sell(caller, amount) +} +``` + +## When Gno takes Go practices to the next level + +### Documentation is for users + +One of the well-known proverbs in Go is: ["Documentation is for +users"](https://www.youtube.com/watch?v=PAAkCSZUG1c&t=1147s), as stated by Rob +Pike. In Go, documentation is for users, but users are often developers. In Gno, +documentation is for users, and users can be other developers but also the end users. + +In Go, we usually have well-written documentation for other developers to +maintain and use our code as a library. Then, we often have another layer of +documentation on our API, sometimes with OpenAPI Specs, Protobuf, or even user +documentation. + +In Gno, the focus shifts towards writing documentation for the end user. You can +even consider that the main reader is an end user, who is not so interested in +technical details, but mostly interested in how and why they should use a +particular endpoint. Comments will be used to aid code source reading, but also to +generate documentation and even for smart wallets that need to understand what +to do. + +Inline comments have the same goal: to guide users (developers or end users) +through the code. While comments are still important for maintainability, their +main purpose in Gno is for discoverability. This shift towards user-centric +documentation reflects the broader shift in Gno towards making code more +accessible and understandable for all users, not just developers. + +TODO: `func ExampleXXX`. + +### Reflection is never clear + +In Go, there's a well-known saying by Rob Pike: ["Reflection is never +clear."](https://www.youtube.com/watch?v=PAAkCSZUG1c&t=15m22s) This statement +emphasizes the complexity and potential pitfalls of using reflection in Go. + +In Gno, reflection does not exist (yet). There are technical reasons for this, +but also a desire to create a Go alternative that is explicitly safer to use +than Go, with a smaller cognitive difficulty to read, discover, and understand. + +The absence of reflection in Gno is not just about simplicity, but also about +safety. Reflection can be powerful, but it can also lead to code that is hard to +understand, hard to debug, and prone to runtime errors. By not supporting +reflection, Gno encourages you to write code that is explicit, clear, and easy +to understand. + +We're currently in the process of considering whether to add reflection support +or not, or perhaps add it in a privileged mode for very few libraries. But for now, +when you're writing Gno code, remember: explicit is better than implicit, and +clear code is better than clever code. + +## Gno good practices + +### Package naming and organization + +Your package name should match the folder name. This helps to prevent having +named imports, which can make your code more difficult to understand and +maintain. By matching the package name with the folder name, you can ensure that +your imports are clear and intuitive. + +Ideally, package names should be short and human-readable. This makes it easier +for other developers to understand what your package does at a glance. Avoid +using abbreviations or acronyms unless they are widely understood. + +Packages and realms can be organized into subdirectories. However, consider that the +best place for your main project will likely be `r/NAMESPACE/DAPP`, similar +to how repositories are organized on GitHub. + +If you have multiple sublevels of realms, remember that they are actually +independent realms and won't share data. A good usage could be to have an +ecosystem of realms, where one realm is about storing the state, another one +about configuration, etc. But in general, a single realm makes sense. + +You can also create small realms to create your ecosystem. For example, you +could centralize all the authentication for your whole company/organization in +`r/NAMESPACE/auth`, and then import it in all your contracts. + +The `p/` prefix is different. In general, you should use top-level `p/` like +`p/NAMESPACE/DAPP` only for things you expect people to use. If your goal is +just to have internal libraries that you created to centralize your helpers and +don't expect that other people will use your helpers, then you should probably +use subdirectories like `p/NAMESPACE/DAPP/foo/bar/baz`. + +### Define types and interfaces in pure packages (p/) + +In Gno, it's common to create `p/NAMESPACE/DAPP` for defining types and +interfaces, and `r/NAMESPACE/DAPP` for the runtime, especially when the goal +for the realm is to become a standard that could be imported by `p/`. + +The reason for this is that `p/` can only import `p/`, while `r/` can import +anything. This separation allows you to define standards in `p/` that can be +used across multiple realms and packages. + +In general, you can just write your `r/` to be an app. But if for some reason +you introduce a concept that can be reused, it makes sense to have a +dedicated `p/` so that people can re-use your logic without depending on +your realm's data. + +For instance, if you want to create a token type in a realm, you can use it, and +other realms can import the realm and compose it. But if you want to create a +`p/` helper that will create a pattern, then you need to have your interface and +types defined in `p/` so anything can import it. + +By separating your types and interfaces into `p/` and your runtime into `r/`, +you can create more modular, reusable, and standardized code in Gno. This +approach allows you to leverage the composability of Gno to build more powerful +and flexible applications. + +### Design your realm as a public API + +In Go, all your packages, including your dependencies, are typically treated as +part of your safe zone, similar to a secure perimeter. The boundary is drawn +between your program and the rest of the world, which means you secure the API +itself, potentially with authentication middlewares. + +However, in Gno, your realm is the public API. It's exposed to the outside +world and can be accessed by other realms. Therefore, it's crucial to design +your realm with the same level of care and security considerations as you would +a public API. + +One approach is to simulate a secure perimeter within your realm by having +private functions for the logic and then writing your API layer by adding some +front-facing API with authentication. This way, you can control access to your +realm's functionality and ensure that only authorized callers can execute +certain operations. + +```go +import "std" + +func PublicMethod(nb int) { + caller := std.PrevRealm().Addr() + privateMethod(caller, nb) +} + +func privateMethod(caller std.Address, nb int) { /* ... */ } +``` + +In this example, `PublicMethod` is a public function that can be called by other +realms. It retrieves the caller's address using `std.PrevRealm().Addr()`, and +then passes it to `privateMethod`, which is a private function that performs the +actual logic. This way, `privateMethod` can only be called from within the +realm, and it can use the caller's address for authentication or authorization +checks. + +### Contract-level access control + +In Gno, it's a good practice to design your contract as an application with its +own access control. This means that different endpoints of your contract should +be accessible to different types of users, such as the public, admins, or +moderators. + +The goal is usually to store the admin address or a list of addresses +(`std.Address`) in a variable, and then create helper functions to update the +owners. These helper functions should check if the caller of a function is +whitelisted or not. + +Let's deep dive into the different access control mechanisms we can use: + +One strategy is to look at the caller with `std.PrevRealm()`, which could be the +EOA (Externally Owned Account), or the preceding realm in the call stack. + +Another approach is to look specifically at the EOA. For this, you should call +`std.GetOrigCaller()`, which returns the public address of the account that +signed the transaction. + +TODO: explain when to use `std.GetOrigCaller`. + +Internally, this call will look at the frame stack, which is basically the stack +of callers including all the functions, anonymous functions, other realms, and +take the initial caller. This allows you to identify the original caller and +implement access control based on their address. + +Here's an example: + +```go +import "std" + +var admin std.Address = "g1xxxxx" + +func AdminOnlyFunction() { + caller := std.PrevRealm().Addr() + if caller != admin { + panic("permission denied") + } + // ... +} + +// func UpdateAdminAddress(newAddr std.Address) { /* ... */ } +``` + +In this example, `AdminOnlyFunction` is a function that can only be called by +the admin. It retrieves the caller's address using `std.PrevRealm().Addr()`, +this can be either another realm contract, or the calling user if there is no +other intermediary realm. and then checks if the caller is the admin. If not, it +panics and stops the execution. + +The goal of this approach is to allow a contract to own assets (like grc20 or +native tokens), so that you can create contracts that can be called by another +contract, reducing the risk of stealing money from the original caller. This is +the behavior of the default grc20 implementation. + +Here's an example: + +```go +import "std" + +func TransferTokens(to std.Address, amount int64) { + caller := std.PrevRealm().Addr() + if caller != admin { + panic("permission denied") + } + // ... +} +``` + +In this example, `TransferTokens` is a function that can only be called by the +admin. It retrieves the caller's address using `std.PrevRealm().Addr()`, and +then checks if the caller is the admin. If not, the function panics and execution is stopped. + +By using these access control mechanisms, you can ensure that your contract's +functionality is accessible only to the intended users, providing a secure and +reliable way to manage access to your contract. + +### Using avl.Tree for efficient data retrieval + +In Gno, the `avl.Tree` data structure is a powerful tool for optimizing data +retrieval. It works by lazily resolving information, which means it only loads +the data you need when you need it. This allows you to scale your application +and pay less gas for data retrieval. + +[AVL is short for Adelson-Velsky and Landis:][avl-wiki] under the hood, it is an +implementation of a self-balancing binary tree. +[avl-wiki]: https://en.wikipedia.org/wiki/AVL_tree + +The `avl.Tree` can be used like a map, where you can store key-value pairs and +retrieve an entry with a simple key. However, unlike a traditional map, the +`avl.Tree` doesn't load unnecessary data. This makes it particularly efficient +for large data sets where you only need to access a small subset of the data at +a time. + +Here's an example of how you can use `avl.Tree`: + +```go +import "avl" + +var tree avl.Tree + +func GetPost(id string) *Post { + return tree.Get(id).(*Post) +} + +func AddPost(id string, post *Post) { + tree.Set(id, post) +} +``` + +In this example, `GetPost` is a function that retrieves a post from the +`avl.Tree` using an ID. It only loads the post with the specified ID, without +loading any other posts. + +In the future, we plan to add built-in "map" support that will match the +efficienty of an `avl.Tree` while offering a more intuitive API. Until then, if +you're dealing with a compact dataset, it's probably best to use slices. +For larger datasets where you need to quickly retrieve elements by keys, +`avl.Tree` is the way to go. + +You can also create SQL-like indexes by having multiple `avl.Tree` instances for +different fields. For example, you can have an `avl.Tree` for ID to *post, then +an `avl.Tree` for Tags, etc. Then, you can create reader methods that will just +retrieve what you need, similar to SQL indexes. + +By using `avl.Tree` and other efficient data structures, you can optimize your +Gno code for performance and cost-effectiveness, making your applications more +scalable and efficient. + +TODO: multi-indices example + +### Construct "safe" objects + +A safe object in Gno is an object that is designed to be tamper-proof and +secure. It's created with the intent of preventing unauthorized access and +modifications. This follows the same principle of making a package an API, but +for a Gno object that can be directly referenced by other realms. + +The goal is to create an object which, once instantiated, can be linked and its +pointer can be "stored" by other realms without issue, because it protects its +usage completely. + +```go +type MySafeStruct { + counter nb + admin std.Address +} + +func NewSafeStruct() *MySafeStruct { + caller := std.PrevRealm().Addr() + return &MySafeStruct{ + counter: 0, + admin: caller, + } +} + +func (s *MySafeStruct) Counter() int { return s.counter } +func (s *MySafeStruct) Inc() { + caller := std.PrevRealm().Addr() + if caller != s.admin { + panic("permission denied") + } + s.counter++ +} +``` + +Then, you can register this object in another or several other realms so other +realms can access the object, but still following your own rules. + +```go +import "gno.land/r/otherrealm" + +func init() { + mySafeObj := NewSafeStruct() + otherrealm.Register(mySafeObject) +} + +// then, other realm can call the public functions but won't be the "owner" of +// the object. +``` + +### Choosing between native tokens and GRC20 tokens + +In Gno, you've got two main choices for tokens: Native or GRC20. Each has its +own pros and cons, and the best fit depends on your needs. + +#### Native tokens + +Native tokens are managed by the banker module, separate from GnoVM. They're +simple, strict, and secure. You can create, transfer, and check balances with an +RPC call, no GnoVM needed. + +For example, if you're creating a coin for cross-chain transfers, native tokens +are your best bet. They're IBC-ready and their strict rules offer top-notch +security. + +Read about how to use the Banker module [here](../concepts/standard-library/banker). + +#### GRC20 tokens + +GRC20 tokens, on the other hand, are like Ethereum's ERC20 or CosmWasm's CW20. +They're flexible, composable, and perfect for DeFi protocols and DAOs. They +offer more features like token-gating, vaults, and wrapping. + +For instance, if you're creating a voting system for a DAO, GRC20 tokens are +ideal. They're programmable, can be embedded in safe Gno objects, and offer more +control. + +Remember, GRC20 tokens are more gas-intensive and aren't IBC-ready yet. They +also come with shared ownership, meaning the contract retains some control. + +In the end, your choice depends on your needs: simplicity and security with +Native tokens, or flexibility and control with GRC20 tokens. And if you want the +best of both worlds, you can wrap a native token into a GRC20 compatible +token. + +```go +import "gno.land/p/demo/grc/grc20" + +var fooToken grc20.AdminToken = grc20.NewAdminToken("Foo Token", "FOO", 4) + +func MyBalance() uint64 { + caller := std.PrevRealm().Addr() + balance, _ := fooToken.BalanceOf(caller) + return balance +} +``` + +See also: https://gno.land/r/demo/foo20 + +#### Wrapping native tokens + +Want the best of both worlds? Consider wrapping your Native tokens. This gives +your tokens the flexibility of GRC20 while keeping the security of Native +tokens. It's a bit more complex, but it's a powerful option that offers great +versatility. + +See also: https://github.com/gnolang/gno/tree/master/examples/gno.land/r/demo/wugnot + + diff --git a/docs/concepts/standard-library/banker.md b/docs/concepts/standard-library/banker.md index 66aacb82c07..a4a1104859c 100644 --- a/docs/concepts/standard-library/banker.md +++ b/docs/concepts/standard-library/banker.md @@ -10,7 +10,7 @@ The Banker module can be cast into 4 subtypes of bankers that expose different f ### Banker Types -1. `BankerTypeReadOnly` - read-only access to coin balances +1. `BankerTypeReadonly` - read-only access to coin balances 2. `BankerTypeOrigSend` - full access to coins sent with the transaction that called the banker 3. `BankerTypeRealmSend` - full access to coins that the realm itself owns, including the ones sent with the transaction 4. `BankerTypeRealmIssue` - able to issue new coins diff --git a/docs/gno-tooling/cli/tm2txsync.md b/docs/gno-tooling/cli/tm2txsync.md deleted file mode 100644 index e9d616bcea5..00000000000 --- a/docs/gno-tooling/cli/tm2txsync.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -id: gno-tooling-tm2txsync ---- - -# tm2txsync - -`tm2txsync` is used for backing up a local node's transactions. - -## Import Transaction Data To (or Export It From) a Node - -You may import or export transaction data with the following command. - -```bash -tm2txsync {SUB_COMMAND} -``` - -#### **Subcommands** - -| Name | Description | -| -------- | -------------------------- | -| `export` | Exports txs from the node. | -| `import` | Imports txs to the node. | - -### Import - -#### **Options** - -| Name | Type | Description | -| -------- | ------ | ----------------------------------------------------------------- | -| `remote` | String | The Remote RPC in `addr:port` format (default: `localhost:26657`) | -| `in` | String | The input file path (default: `txexport.log`) | - -### Export - -#### **Options** - -| Name | Type | Description | -| -------- | ------- | ----------------------------------------------------------------- | -| `remote` | String | The Remote RPC in `addr:port` format (default: `localhost:26657`) | -| `start` | Int64 | Starting height (default: `1`) | -| `tail` | Int64 | Start at LAST - N. | -| `end` | Int64 | End height (optional) | -| `out` | String | The output file path (default: `txexport.log`) | -| `quiet` | Boolean | Quiet mode. | -| `follow` | Boolean | Keep attached and follow new events. | diff --git a/docs/reference/standard-library/std/banker.md b/docs/reference/standard-library/std/banker.md index 761f3c7d253..621a447ab84 100644 --- a/docs/reference/standard-library/std/banker.md +++ b/docs/reference/standard-library/std/banker.md @@ -28,7 +28,7 @@ Returns `Banker` of the specified type. #### Parameters - `BankerType` - type of Banker to get: - - `BankerTypeReadOnly` - read-only access to coin balances + - `BankerTypeReadonly` - read-only access to coin balances - `BankerTypeOrigSend` - full access to coins sent with the transaction that calls the banker - `BankerTypeRealmSend` - full access to coins that the realm itself owns, including the ones sent with the transaction - `BankerTypeRealmIssue` - able to issue new coins diff --git a/examples/gno.land/r/gnoland/home/home.gno b/examples/gno.land/r/gnoland/home/home.gno index 14da10dd63a..3dfd3af1269 100644 --- a/examples/gno.land/r/gnoland/home/home.gno +++ b/examples/gno.land/r/gnoland/home/home.gno @@ -58,22 +58,24 @@ func lastBlogposts(limit int) ui.Element { func lastContributions(limit int) ui.Element { return ui.Element{ - ui.H3("Last Contributions"), - ui.Text("TODO: import r/gh"), - ui.Link{Text: "#1134", URL: "https://github.com/gnolang/gno/pull/1134"}, + ui.H3("Latest Contributions"), + // TODO: import r/gh + // ui.Link{Text: "#1134", URL: "https://github.com/gnolang/gno/pull/1134"}, + ui.Text("coming soon"), } } func upcomingEvents(limit int) ui.Element { return ui.Element{ ui.H3("Upcoming Events"), - ui.Text("TODO: import r/gnoland/events"), + // TODO: import r/gnoland/events + ui.Text("coming soon"), } } func introSection() ui.Element { return ui.Element{ - ui.H3("An interpretation of the Golang (Go) programming language for advanced developers and intrepid pioneers to build succinct, composable smart contracts for social coordination."), + ui.H3("An interpretation of the Go (Golang) programming language for advanced developers and intrepid pioneers to build succinct, composable smart contracts for social coordination."), ui.Paragraph("If you’re concerned about information censorship and want to contribute to the #GnoWorldOrder, follow our socials to find out how."), ui.Paragraph("Gno.land is in building mode. If you want to help lay the foundations of a fairer and freer world through innovative ideas and exceptional code, join us today."), } @@ -107,7 +109,8 @@ func worxDAO() ui.Element { ``*/ return ui.Element{ ui.H3("Contributions (WorxDAO & GoR)"), - ui.Text(`TODO: GoR dashboard + WorxDAO topics`), + // TODO: GoR dashboard + WorxDAO topics + ui.Text(`coming soon`), } } @@ -220,12 +223,12 @@ func discoverLinks() ui.Element {
-### Build with Gnolang +### Build with Gno - [Gno dev with CLI (soon)](#) - [Explore the Universe](/ecosystem) - [Test in the browser (soon)](#) -- [About the Gnolang Language](/gnolang) +- [About the Gno Language](/gnolang) - [Docs/ Tutorials](https://github.com/gnolang) - [Gno by example](https://gno-by-example.com/) - [Getting started video (soon)](#) diff --git a/examples/gno.land/r/gnoland/home/home_filetest.gno b/examples/gno.land/r/gnoland/home/home_filetest.gno index e87e5917676..a9fc8f7e629 100644 --- a/examples/gno.land/r/gnoland/home/home_filetest.gno +++ b/examples/gno.land/r/gnoland/home/home_filetest.gno @@ -9,7 +9,7 @@ func main() { // Output: // # Welcome to Gno.land // -// ### An interpretation of the Golang (Go) programming language for advanced developers and intrepid pioneers to build succinct, composable smart contracts for social coordination. +// ### An interpretation of the Go (Golang) programming language for advanced developers and intrepid pioneers to build succinct, composable smart contracts for social coordination. // // // If you’re concerned about information censorship and want to contribute to the #GnoWorldOrder, follow our socials to find out how. @@ -21,7 +21,7 @@ func main() { // // ### Contributions (WorxDAO & GoR) // -// TODO: GoR dashboard + WorxDAO topics +// coming soon //
// // ### Explore New Packages and Realms @@ -94,14 +94,13 @@ func main() { // // ### Upcoming Events // -// TODO: import r/gnoland/events +// coming soon // //
// -// ### Last Contributions +// ### Latest Contributions // -// TODO: import r/gh -// [#1134](https://github.com/gnolang/gno/pull/1134) +// coming soon //
// // @@ -124,12 +123,12 @@ func main() { // //
// -// ### Build with Gnolang +// ### Build with Gno // // - [Gno dev with CLI (soon)](#) // - [Explore the Universe](/ecosystem) // - [Test in the browser (soon)](#) -// - [About the Gnolang Language](/gnolang) +// - [About the Gno Language](/gnolang) // - [Docs/ Tutorials](https://github.com/gnolang) // - [Gno by example](https://gno-by-example.com/) // - [Getting started video (soon)](#) diff --git a/examples/gno.land/r/gnoland/pages/page_about.gno b/examples/gno.land/r/gnoland/pages/page_about.gno index 9aba4e39f76..80c43c1741d 100644 --- a/examples/gno.land/r/gnoland/pages/page_about.gno +++ b/examples/gno.land/r/gnoland/pages/page_about.gno @@ -2,19 +2,19 @@ package gnopages func init() { path := "about" - title := "Gno.land Is A Platform To Write Smart Contracts In Gnolang (Gno)" - // XXX: description := "On Gno.land, developers write smart contracts and other blockchain apps using Gnolang (Gno) without learning a language that’s exclusive to a single ecosystem." + title := "Gno.land Is A Platform To Write Smart Contracts In Gno" + // XXX: description := "On Gno.land, developers write smart contracts and other blockchain apps using Gno without learning a language that’s exclusive to a single ecosystem." body := `# About Gno.land -Gno.land is a platform to write smart contracts in Gnolang (Gno). -Using an interpreted version of the general-purpose programming language Golang (Go), developers can write smart contracts and other blockchain apps without having to learn a language that’s exclusive to a single ecosystem. +Gno.land is a platform to write smart contracts in Gno. +Using an interpreted version of the general-purpose programming language Go (Golang), developers can write smart contracts and other blockchain apps without having to learn a language that’s exclusive to a single ecosystem. Web2 developers can easily contribute to web3 and start building a more transparent, accountable world. The Gno transaction token, GNOT, and the contributor memberships power the platform, which runs on a variation of Proof of Stake. Proof of Contribution rewards contributors from technical and non-technical backgrounds, fairly and for life with GNOT. This consensus mechanism also achieves higher security with fewer validators, optimizing resources for a greener, more sustainable, and enduring blockchain ecosystem. -Any blockchain using Gnolang achieves succinctness, composability, expressivity, and completeness not found in any other smart contract platform. +Any blockchain using Gno achieves succinctness, composability, expressivity, and completeness not found in any other smart contract platform. By observing a minimal structure, the design can endure over time and challenge the regime of information censorship we’re living in today.` _ = b.NewPost("", path, title, body, nil) } diff --git a/examples/gno.land/r/gnoland/pages/page_gnolang.gno b/examples/gno.land/r/gnoland/pages/page_gnolang.gno index f0c2bfe276d..ecbadab9f01 100644 --- a/examples/gno.land/r/gnoland/pages/page_gnolang.gno +++ b/examples/gno.land/r/gnoland/pages/page_gnolang.gno @@ -3,11 +3,11 @@ package gnopages func init() { var ( path = "gnolang" - title = "Gnolang (Gno) Is a Complete Language for Blockchain" + title = "Gno Is a Complete Language for Blockchain" // XXX: description = "Gnolang (Gno) is an interpretation of the popular Golang (Go) language for blockchain created by Tendermint and Cosmos founder Jae Kwon." - body = `# About the Gnolang, the Gno Language + body = `# About the Gno, the Language for Gno.land -[Gnolang](https://github.com/gnolang/gno/blob/master/LICENSE.md) (Gno) is an interpretation of the widely-used Golang (Go) programming language for blockchain created by Cosmos co-founder Jae Kwon in 2022 to mark a new era in smart contracting. Gno is ~99% identical to Go, so Go programmers can start coding in Gno right away, with a minimal learning curve. For example, Gno comes with blockchain-specific standard libraries, but any code that doesn’t use blockchain-specific logic can run in Go with minimal processing. Libraries that don’t make sense in the blockchain context, such as network or operating-system access, are not available in Gno. Otherwise, Gno loads and uses many standard libraries that power Go, so most of the parsing of the source code is the same. +[Gno](https://github.com/gnolang/gno/blob/master/LICENSE.md) is an interpretation of the widely-used Go (Golang) programming language for blockchain created by Cosmos co-founder Jae Kwon in 2022 to mark a new era in smart contracting. Gno is ~99% identical to Go, so Go programmers can start coding in Gno right away, with a minimal learning curve. For example, Gno comes with blockchain-specific standard libraries, but any code that doesn’t use blockchain-specific logic can run in Go with minimal processing. Libraries that don’t make sense in the blockchain context, such as network or operating-system access, are not available in Gno. Otherwise, Gno loads and uses many standard libraries that power Go, so most of the parsing of the source code is the same. Under the hood, the Gno code is parsed into an abstract syntax tree (AST) and the AST itself is used in the interpreter, rather than bytecode as in many virtual machines such as Java, Python, or Wasm. This makes even the GnoVM accessible to any Go programmer. The novel design of the intuitive GnoVM interpreter allows Gno to freeze and resume the program by persisting and loading the entire memory state. Gno is deterministic, auto-persisted, and auto-Merkle-ized, allowing (smart contract) programs to be succinct, as the programmer doesn’t have to serialize and deserialize objects to persist them into a database (unlike programming applications with the Cosmos SDK). diff --git a/examples/gno.land/r/gnoland/pages/pages_test.gno b/examples/gno.land/r/gnoland/pages/pages_test.gno index 5a6fe84ad38..0119ac78985 100644 --- a/examples/gno.land/r/gnoland/pages/pages_test.gno +++ b/examples/gno.land/r/gnoland/pages/pages_test.gno @@ -33,7 +33,7 @@ func TestAbout(t *testing.T) { got := Render("p/about") expectedSubtrings := []string{ "# About Gno.land", - "Gno.land is a platform to write smart contracts in Gnolang (Gno).", + "Gno.land is a platform to write smart contracts in Gno.", } for _, substring := range expectedSubtrings { if !strings.Contains(got, substring) { diff --git a/gno.land/Makefile b/gno.land/Makefile index 8138dfcfe3e..f4f9dd1aae2 100644 --- a/gno.land/Makefile +++ b/gno.land/Makefile @@ -17,26 +17,24 @@ start.gnoland:; go run ./cmd/gnoland start start.gnoweb:; go run ./cmd/gnoweb .PHONY: build -build: build.gnoland build.gnokey build.gnoweb build.gnofaucet build.gnotxsync build.genesis +build: build.gnoland build.gnokey build.gnoweb build.gnofaucet build.genesis build.gnoland:; go build -o build/gnoland ./cmd/gnoland build.gnoweb:; go build -o build/gnoweb ./cmd/gnoweb build.gnofaucet:; go build -o build/gnofaucet ./cmd/gnofaucet build.gnokey:; go build -o build/gnokey ./cmd/gnokey -build.gnotxsync:; go build -o build/gnotxsync ./cmd/gnotxsync build.genesis:; go build -o build/genesis ./cmd/genesis run.gnoland:; go run ./cmd/gnoland start run.gnoweb:; go run ./cmd/gnoweb .PHONY: install -install: install.gnoland install.gnoweb install.gnofaucet install.gnokey install.gnotxsync install.genesis +install: install.gnoland install.gnoweb install.gnofaucet install.gnokey install.genesis install.gnoland:; go install ./cmd/gnoland install.gnoweb:; go install ./cmd/gnoweb install.gnofaucet:; go install ./cmd/gnofaucet install.gnokey:; go install ./cmd/gnokey -install.gnotxsync:; go install ./cmd/gnotxsync install.genesis:; go install ./cmd/genesis .PHONY: fclean diff --git a/gno.land/cmd/gnoland/testdata/float-arg.txtar b/gno.land/cmd/gnoland/testdata/float-arg.txtar new file mode 100644 index 00000000000..ac684fc8fab --- /dev/null +++ b/gno.land/cmd/gnoland/testdata/float-arg.txtar @@ -0,0 +1,24 @@ +# test for float args + +## start a new node +gnoland start + +gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/demo/float_realm -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1 + +gnokey maketx call -pkgpath gno.land/r/demo/float_realm --func AddF32 -args 10.5 --args 20 --gas-fee 1000000ugnot --gas-wanted 2000000 --broadcast -chainid=tendermint_test test1 +stdout '(30.5 float32)' + +gnokey maketx call -pkgpath gno.land/r/demo/float_realm --func AddF64 -args 3.1 --args 2.2 --gas-fee 1000000ugnot --gas-wanted 2000000 --broadcast -chainid=tendermint_test test1 +stdout '(5.3[0-9]* float64)' + +-- float_realm.gno -- +package float_realm + +func AddF32(x, y float32) float32 { + return x + y +} + +func AddF64(x, y float64) float64 { + return x + y +} + diff --git a/gno.land/cmd/gnoland/testdata/issue-gnochess-97.txtar b/gno.land/cmd/gnoland/testdata/issue-gnochess-97.txtar new file mode 100644 index 00000000000..89406d328d4 --- /dev/null +++ b/gno.land/cmd/gnoland/testdata/issue-gnochess-97.txtar @@ -0,0 +1,41 @@ +# test for https://github.com/gnolang/gnochess/issues/97 + +gnoland start + +gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/demo/bug97 -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1 + +gnokey maketx call -pkgpath 'gno.land/r/demo/bug97' -func 'RealmCall1' -gas-fee 1000000ugnot -gas-wanted 2000000 -send '' -broadcast -chainid='tendermint_test' test1 +stdout 'OK!' + +gnokey maketx call -pkgpath 'gno.land/r/demo/bug97' -func 'RealmCall2' -gas-fee 1000000ugnot -gas-wanted 2000000 -send '' -broadcast -chainid='tendermint_test' test1 +stdout 'OK!' + +gnokey maketx call -pkgpath 'gno.land/r/demo/bug97' -func 'RealmCall1' -gas-fee 1000000ugnot -gas-wanted 2000000 -send '' -broadcast -chainid='tendermint_test' test1 +stdout 'OK!' + +-- bug97.gno -- +package bug97 + +var x = [3]int{1, 2, 3} + +func newX() [3]int { return x} + +type S struct { + Arr [3]int +} + +func NewS() S { + return S{Arr: x} +} + +var s S + +func RealmCall1() { + s = NewS() +} + +func RealmCall2() { + arr2 := s.Arr + arr2[0] = 8 + s = S{Arr: arr2} +} diff --git a/gno.land/cmd/gnotxsync/README.md b/gno.land/cmd/gnotxsync/README.md deleted file mode 100644 index 3bd032a5f23..00000000000 --- a/gno.land/cmd/gnotxsync/README.md +++ /dev/null @@ -1,3 +0,0 @@ -This is a simple tool to fetch (valid) transactions using the HTTP rpc. -It is pretty slow, especially from a remote machine. -TODO: make it faster by running on local database instance. diff --git a/gno.land/cmd/gnotxsync/export.go b/gno.land/cmd/gnotxsync/export.go deleted file mode 100644 index f22a4cd22f4..00000000000 --- a/gno.land/cmd/gnotxsync/export.go +++ /dev/null @@ -1,143 +0,0 @@ -package main - -import ( - "context" - "flag" - "fmt" - "io" - "log" - "os" - "strings" - "time" - - "github.com/gnolang/gno/tm2/pkg/amino" - "github.com/gnolang/gno/tm2/pkg/bft/rpc/client" - "github.com/gnolang/gno/tm2/pkg/commands" - "github.com/gnolang/gno/tm2/pkg/std" - - _ "github.com/gnolang/gno/gno.land/pkg/sdk/vm" - _ "github.com/gnolang/gno/tm2/pkg/sdk/auth" // XXX better way? - _ "github.com/gnolang/gno/tm2/pkg/sdk/bank" -) - -type exportCfg struct { - rootCfg *config - - startHeight int64 - tailHeight int64 - endHeight int64 - outFile string - quiet bool - follow bool -} - -func newExportCommand(rootCfg *config) *commands.Command { - cfg := &exportCfg{ - rootCfg: rootCfg, - } - - return commands.NewCommand( - commands.Metadata{ - Name: "export", - ShortUsage: "export [flags] ", - ShortHelp: "Export transactions to file", - }, - cfg, - func(_ context.Context, _ []string) error { - return execExport(cfg) - }, - ) -} - -func (c *exportCfg) RegisterFlags(fs *flag.FlagSet) { - fs.Int64Var(&c.startHeight, "start", 1, "start height") - fs.Int64Var(&c.tailHeight, "tail", 0, "start at LAST - N") - fs.Int64Var(&c.endHeight, "end", 0, "end height (optional)") - fs.StringVar(&c.outFile, "out", defaultFilePath, "output file path") - fs.BoolVar(&c.quiet, "quiet", false, "omit console output during execution") - fs.BoolVar(&c.follow, "follow", false, "keep attached and follow new events") -} - -func execExport(c *exportCfg) error { - node := client.NewHTTP(c.rootCfg.remote, "/websocket") - - status, err := node.Status() - if err != nil { - return fmt.Errorf("unable to fetch node status, %w", err) - } - - var ( - start = c.startHeight - end = c.endHeight - tail = c.tailHeight - ) - - if end == 0 { // take last block height - end = status.SyncInfo.LatestBlockHeight - } - if tail > 0 { - start = end - tail - } - - var out io.Writer - switch c.outFile { - case "-", "STDOUT": - out = os.Stdout - default: - out, err = os.OpenFile(c.outFile, os.O_RDWR|os.O_CREATE, 0o755) - if err != nil { - return err - } - } - - for height := start; ; height++ { - if !c.follow && height >= end { - break - } - - getBlock: - block, err := node.Block(&height) - if err != nil { - if c.follow && strings.Contains(err.Error(), "") { - time.Sleep(time.Second) - - goto getBlock - } - - return fmt.Errorf("encountered error while fetching block, %w", err) - } - - txs := block.Block.Data.Txs - if len(txs) == 0 { - continue - } - - _, err = node.BlockResults(&height) - if err != nil { - if c.follow && strings.Contains(err.Error(), "") { - time.Sleep(time.Second) - - goto getBlock - } - - return fmt.Errorf("encountered error while fetching block results, %w", err) - } - - for i := 0; i < len(txs); i++ { - tx := txs[i] - stdtx := std.Tx{} - - amino.MustUnmarshal(tx, &stdtx) - - bz := amino.MustMarshalJSON(stdtx) - - _, _ = fmt.Fprintln(out, string(bz)) - } - - if !c.quiet { - log.Printf("h=%d/%d (txs=%d)", height, end, len(txs)) - } - } - - return nil -} diff --git a/gno.land/cmd/gnotxsync/import.go b/gno.land/cmd/gnotxsync/import.go deleted file mode 100644 index 3369b5378b5..00000000000 --- a/gno.land/cmd/gnotxsync/import.go +++ /dev/null @@ -1,118 +0,0 @@ -package main - -import ( - "bufio" - "context" - "flag" - "fmt" - "os" - "time" - - "github.com/gnolang/gno/tm2/pkg/amino" - "github.com/gnolang/gno/tm2/pkg/bft/rpc/client" - "github.com/gnolang/gno/tm2/pkg/commands" - "github.com/gnolang/gno/tm2/pkg/errors" - "github.com/gnolang/gno/tm2/pkg/std" - - _ "github.com/gnolang/gno/gno.land/pkg/sdk/vm" - _ "github.com/gnolang/gno/tm2/pkg/sdk/auth" // XXX better way? - _ "github.com/gnolang/gno/tm2/pkg/sdk/bank" -) - -type importCfg struct { - rootCfg *config - - inFile string -} - -func newImportCommand(rootCfg *config) *commands.Command { - cfg := &importCfg{ - rootCfg: rootCfg, - } - - return commands.NewCommand( - commands.Metadata{ - Name: "import", - ShortUsage: "import [flags] ", - ShortHelp: "Import transactions from file", - }, - cfg, - func(ctx context.Context, _ []string) error { - return execImport(ctx, cfg) - }, - ) -} - -func (c *importCfg) RegisterFlags(fs *flag.FlagSet) { - fs.StringVar(&c.inFile, "in", defaultFilePath, "input file path") -} - -func execImport(ctx context.Context, c *importCfg) error { - // Initial validation - if len(c.inFile) == 0 { - return errors.New("input file path not specified") - } - - // Read the input file - file, err := os.Open(c.inFile) - if err != nil { - return fmt.Errorf("unable to open input file, %w", err) - } - - defer file.Close() - - // Start the WS connection to the node - node := client.NewHTTP(c.rootCfg.remote, "/websocket") - - index := 0 - scanner := bufio.NewScanner(file) - for scanner.Scan() { - select { - case <-ctx.Done(): - // Stop signal received while parsing - // the import file - return nil - default: - print(".") - - line := scanner.Text() - if len(line) == 0 { - return fmt.Errorf("empty line encountered at %d", index) - } - - var tx std.Tx - amino.MustUnmarshalJSON([]byte(line), &tx) - txbz := amino.MustMarshal(tx) - - res, err := node.BroadcastTxSync(txbz) - - if err != nil || res.Error != nil { - print("!") - // wait for next block and try again. - // TODO: actually wait 1 block instead of fudging it. - time.Sleep(20 * time.Second) - - res, err := node.BroadcastTxSync(txbz) - if err != nil || res.Error != nil { - if err != nil { - fmt.Println("SECOND ERROR", err) - } else { - fmt.Println("SECOND ERROR!", res.Error) - } - - fmt.Println(line) - - return errors.Wrap(err, "broadcasting tx %d", index) - } - } - - index++ - } - } - - if err := scanner.Err(); err != nil { - return fmt.Errorf("error encountered while reading file, %w", err) - } - - return nil -} diff --git a/gno.land/cmd/gnotxsync/main.go b/gno.land/cmd/gnotxsync/main.go deleted file mode 100644 index 02a613d5dc8..00000000000 --- a/gno.land/cmd/gnotxsync/main.go +++ /dev/null @@ -1,47 +0,0 @@ -package main - -import ( - "context" - "flag" - "os" - - "github.com/gnolang/gno/tm2/pkg/commands" -) - -// config is the shared config for gnotxport, and its subcommands -type config struct { - remote string `default:"localhost:26657"` -} - -const ( - defaultFilePath = "txexport.log" -) - -func main() { - cfg := &config{} - - cmd := commands.NewCommand( - commands.Metadata{ - ShortUsage: " [flags] [...]", - LongHelp: "Exports or imports transactions from the node", - }, - cfg, - commands.HelpExec, - ) - - cmd.AddSubCommands( - newImportCommand(cfg), - newExportCommand(cfg), - ) - - cmd.Execute(context.Background(), os.Args[1:]) -} - -func (c *config) RegisterFlags(fs *flag.FlagSet) { - fs.StringVar( - &c.remote, - "remote", - "localhost:26657", - "remote RPC address ", - ) -} diff --git a/gno.land/cmd/gnotxsync/main_test.go b/gno.land/cmd/gnotxsync/main_test.go deleted file mode 100644 index 06ab7d0f9a3..00000000000 --- a/gno.land/cmd/gnotxsync/main_test.go +++ /dev/null @@ -1 +0,0 @@ -package main diff --git a/gno.land/pkg/gnoclient/client.go b/gno.land/pkg/gnoclient/client.go index 2c43a5fa01d..0a6918999a6 100644 --- a/gno.land/pkg/gnoclient/client.go +++ b/gno.land/pkg/gnoclient/client.go @@ -2,7 +2,6 @@ package gnoclient import ( rpcclient "github.com/gnolang/gno/tm2/pkg/bft/rpc/client" - "github.com/gnolang/gno/tm2/pkg/errors" ) // Client provides an interface for interacting with the blockchain. @@ -14,7 +13,7 @@ type Client struct { // validateSigner checks that the signer is correctly configured. func (c Client) validateSigner() error { if c.Signer == nil { - return errors.New("missing Signer") + return ErrMissingSigner } return nil } @@ -22,7 +21,7 @@ func (c Client) validateSigner() error { // validateRPCClient checks that the RPCClient is correctly configured. func (c Client) validateRPCClient() error { if c.RPCClient == nil { - return errors.New("missing RPCClient") + return ErrMissingRPCClient } return nil } diff --git a/gno.land/pkg/gnoclient/client_test.go b/gno.land/pkg/gnoclient/client_test.go index 0fe5f4eefcc..8bcdd903831 100644 --- a/gno.land/pkg/gnoclient/client_test.go +++ b/gno.land/pkg/gnoclient/client_test.go @@ -3,98 +3,549 @@ package gnoclient import ( "testing" - "github.com/gnolang/gno/gno.land/pkg/integration" - "github.com/gnolang/gno/gnovm/pkg/gnoenv" - rpcclient "github.com/gnolang/gno/tm2/pkg/bft/rpc/client" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" + ctypes "github.com/gnolang/gno/tm2/pkg/bft/rpc/core/types" + "github.com/gnolang/gno/tm2/pkg/bft/types" + "github.com/gnolang/gno/tm2/pkg/crypto" "github.com/gnolang/gno/tm2/pkg/crypto/keys" - "github.com/gnolang/gno/tm2/pkg/log" "github.com/gnolang/gno/tm2/pkg/std" - "github.com/jaekwon/testify/require" ) -func newInMemorySigner(t *testing.T, chainid string) *SignerFromKeybase { - t.Helper() - - mmeonic := integration.DefaultAccount_Seed - name := integration.DefaultAccount_Name +func TestClient_Render(t *testing.T) { + t.Parallel() + testRealmPath := "gno.land/r/demo/deep/very/deep" + expectedRender := []byte("it works!") - kb := keys.NewInMemory() - _, err := kb.CreateAccount(name, mmeonic, "", "", uint32(0), uint32(0)) - require.NoError(t, err) - - return &SignerFromKeybase{ - Keybase: kb, // Stores keys in memory or on disk - Account: name, // Account name or bech32 format - Password: "", // Password for encryption - ChainID: chainid, // Chain ID for transaction signing + client := Client{ + Signer: &mockSigner{ + sign: func(cfg SignCfg) (*std.Tx, error) { + return &std.Tx{}, nil + }, + info: func() keys.Info { + return &mockKeysInfo{ + getAddress: func() crypto.Address { + adr, _ := crypto.AddressFromBech32("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") + return adr + }, + } + }, + }, + RPCClient: &mockRPCClient{ + abciQuery: func(path string, data []byte) (*ctypes.ResultABCIQuery, error) { + res := &ctypes.ResultABCIQuery{ + Response: abci.ResponseQuery{ + ResponseBase: abci.ResponseBase{ + Data: expectedRender, + }, + }, + } + return res, nil + }, + }, } -} -func TestClient_Request(t *testing.T) { - config, _ := integration.TestingNodeConfig(t, gnoenv.RootDir()) - node, remoteAddr := integration.TestingInMemoryNode(t, log.NewNoopLogger(), config) - defer node.Stop() + res, data, err := client.Render(testRealmPath, "") + assert.NoError(t, err) + assert.NotEmpty(t, data.Response.Data) + assert.NotEmpty(t, res) + assert.Equal(t, data.Response.Data, expectedRender) +} - signer := newInMemorySigner(t, config.TMConfig.ChainID()) +func TestClient_CallSingle(t *testing.T) { + t.Parallel() client := Client{ - Signer: signer, - RPCClient: rpcclient.NewHTTP(remoteAddr, "/websocket"), + Signer: &mockSigner{ + sign: func(cfg SignCfg) (*std.Tx, error) { + return &std.Tx{}, nil + }, + info: func() keys.Info { + return &mockKeysInfo{ + getAddress: func() crypto.Address { + adr, _ := crypto.AddressFromBech32("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") + return adr + }, + } + }, + }, + RPCClient: &mockRPCClient{ + broadcastTxCommit: func(tx types.Tx) (*ctypes.ResultBroadcastTxCommit, error) { + res := &ctypes.ResultBroadcastTxCommit{ + DeliverTx: abci.ResponseDeliverTx{ + ResponseBase: abci.ResponseBase{ + Data: []byte("it works!"), + }, + }, + } + return res, nil + }, + }, } - data, res, err := client.Render("gno.land/r/demo/boards", "") - require.NoError(t, err) - require.NotEmpty(t, data) + cfg := BaseTxCfg{ + GasWanted: 100000, + GasFee: "10000ugnot", + AccountNumber: 1, + SequenceNumber: 1, + Memo: "Test memo", + } - require.NotNil(t, res) - require.NotEmpty(t, res.Response.Data) + msg := []MsgCall{ + { + PkgPath: "gno.land/r/demo/deep/very/deep", + FuncName: "Render", + Args: []string{""}, + Send: "100ugnot", + }, + } - // XXX: need more test + res, err := client.Call(cfg, msg...) + assert.NoError(t, err) + require.NotNil(t, res) + assert.Equal(t, string(res.DeliverTx.Data), "it works!") } -func TestClient_Run(t *testing.T) { - config, _ := integration.TestingNodeConfig(t, gnoenv.RootDir()) - node, remoteAddr := integration.TestingInMemoryNode(t, log.NewNoopLogger(), config) - defer node.Stop() - - signer := newInMemorySigner(t, config.TMConfig.ChainID()) +func TestClient_CallMultiple(t *testing.T) { + t.Parallel() client := Client{ - Signer: signer, - RPCClient: rpcclient.NewHTTP(remoteAddr, "/websocket"), + Signer: &mockSigner{ + sign: func(cfg SignCfg) (*std.Tx, error) { + return &std.Tx{}, nil + }, + info: func() keys.Info { + return &mockKeysInfo{ + getAddress: func() crypto.Address { + adr, _ := crypto.AddressFromBech32("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") + return adr + }, + } + }, + }, + RPCClient: &mockRPCClient{ + broadcastTxCommit: func(tx types.Tx) (*ctypes.ResultBroadcastTxCommit, error) { + res := &ctypes.ResultBroadcastTxCommit{ + CheckTx: abci.ResponseCheckTx{ + ResponseBase: abci.ResponseBase{ + Error: nil, + Data: nil, + Events: nil, + Log: "", + Info: "", + }, + }, + } + + return res, nil + }, + }, } - code := `package main + cfg := BaseTxCfg{ + GasWanted: 100000, + GasFee: "10000ugnot", + AccountNumber: 1, + SequenceNumber: 1, + Memo: "Test memo", + } -import ( - "std" + msg := []MsgCall{ + { + PkgPath: "gno.land/r/demo/deep/very/deep", + FuncName: "Render", + Args: []string{""}, + Send: "100ugnot", + }, + { + PkgPath: "gno.land/r/demo/wugnot", + FuncName: "Deposit", + Args: []string{""}, + Send: "1000ugnot", + }, + { + PkgPath: "gno.land/r/demo/tamagotchi", + FuncName: "Feed", + Args: []string{""}, + Send: "", + }, + } - "gno.land/p/demo/ufmt" - "gno.land/r/demo/tests" -) + res, err := client.Call(cfg, msg...) + assert.NoError(t, err) + assert.NotNil(t, res) +} -func main() { - println(ufmt.Sprintf("- before: %d", tests.Counter())) - for i := 0; i < 10; i++ { - tests.IncCounter() +func TestClient_Call_Errors(t *testing.T) { + t.Parallel() + + testCases := []struct { + name string + client Client + cfg BaseTxCfg + msgs []MsgCall + expectedError error + }{ + { + name: "Invalid Signer", + client: Client{ + Signer: nil, + RPCClient: &mockRPCClient{}, + }, + cfg: BaseTxCfg{ + GasWanted: 100000, + GasFee: "10000ugnot", + AccountNumber: 1, + SequenceNumber: 1, + Memo: "Test memo", + }, + msgs: []MsgCall{ + { + PkgPath: "random/path", + FuncName: "RandomName", + Send: "", + Args: []string{}, + }, + }, + expectedError: ErrMissingSigner, + }, + { + name: "Invalid RPCClient", + client: Client{ + &mockSigner{}, + nil, + }, + cfg: BaseTxCfg{ + GasWanted: 100000, + GasFee: "10000ugnot", + AccountNumber: 1, + SequenceNumber: 1, + Memo: "Test memo", + }, + msgs: []MsgCall{ + { + PkgPath: "random/path", + FuncName: "RandomName", + Send: "", + Args: []string{}, + }, + }, + expectedError: ErrMissingRPCClient, + }, + { + name: "Invalid Gas Fee", + client: Client{ + Signer: &mockSigner{}, + RPCClient: &mockRPCClient{}, + }, + cfg: BaseTxCfg{ + GasWanted: 100000, + GasFee: "", + AccountNumber: 1, + SequenceNumber: 1, + Memo: "Test memo", + }, + msgs: []MsgCall{ + { + PkgPath: "random/path", + FuncName: "RandomName", + }, + }, + expectedError: ErrInvalidGasFee, + }, + { + name: "Negative Gas Wanted", + client: Client{ + Signer: &mockSigner{}, + RPCClient: &mockRPCClient{}, + }, + cfg: BaseTxCfg{ + GasWanted: -1, + GasFee: "10000ugnot", + AccountNumber: 1, + SequenceNumber: 1, + Memo: "Test memo", + }, + msgs: []MsgCall{ + { + PkgPath: "random/path", + FuncName: "RandomName", + Send: "", + Args: []string{}, + }, + }, + expectedError: ErrInvalidGasWanted, + }, + { + name: "0 Gas Wanted", + client: Client{ + Signer: &mockSigner{}, + RPCClient: &mockRPCClient{}, + }, + cfg: BaseTxCfg{ + GasWanted: 0, + GasFee: "10000ugnot", + AccountNumber: 1, + SequenceNumber: 1, + Memo: "Test memo", + }, + msgs: []MsgCall{ + { + PkgPath: "random/path", + FuncName: "RandomName", + Send: "", + Args: []string{}, + }, + }, + expectedError: ErrInvalidGasWanted, + }, + { + name: "Invalid PkgPath", + client: Client{ + Signer: &mockSigner{}, + RPCClient: &mockRPCClient{}, + }, + cfg: BaseTxCfg{ + GasWanted: 100000, + GasFee: "10000ugnot", + AccountNumber: 1, + SequenceNumber: 1, + Memo: "Test memo", + }, + msgs: []MsgCall{ + { + PkgPath: "", + FuncName: "RandomName", + Send: "", + Args: []string{}, + }, + }, + expectedError: ErrEmptyPkgPath, + }, + { + name: "Invalid FuncName", + client: Client{ + Signer: &mockSigner{}, + RPCClient: &mockRPCClient{}, + }, + cfg: BaseTxCfg{ + GasWanted: 100000, + GasFee: "10000ugnot", + AccountNumber: 1, + SequenceNumber: 1, + Memo: "Test memo", + }, + msgs: []MsgCall{ + { + PkgPath: "random/path", + FuncName: "", + Send: "", + Args: []string{}, + }, + }, + expectedError: ErrEmptyFuncName, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + res, err := tc.client.Call(tc.cfg, tc.msgs...) + assert.Nil(t, res) + assert.ErrorIs(t, err, tc.expectedError) + }) } - println(ufmt.Sprintf("- after: %d", tests.Counter())) -}` - memPkg := &std.MemPackage{ - Files: []*std.MemFile{ - { - Name: "main.gno", - Body: code, +} + +func TestClient_Send_Errors(t *testing.T) { + t.Parallel() + + toAddress, _ := crypto.AddressFromBech32("g14a0y9a64dugh3l7hneshdxr4w0rfkkww9ls35p") + testCases := []struct { + name string + client Client + cfg BaseTxCfg + msgs []MsgSend + expectedError error + }{ + { + name: "Invalid Signer", + client: Client{ + Signer: nil, + RPCClient: &mockRPCClient{}, + }, + cfg: BaseTxCfg{ + GasWanted: 100000, + GasFee: "10000ugnot", + AccountNumber: 1, + SequenceNumber: 1, + Memo: "Test memo", + }, + msgs: []MsgSend{ + { + ToAddress: toAddress, + Send: "1ugnot", + }, + }, + expectedError: ErrMissingSigner, + }, + { + name: "Invalid RPCClient", + client: Client{ + &mockSigner{}, + nil, + }, + cfg: BaseTxCfg{ + GasWanted: 100000, + GasFee: "10000ugnot", + AccountNumber: 1, + SequenceNumber: 1, + Memo: "Test memo", }, + msgs: []MsgSend{ + { + ToAddress: toAddress, + Send: "1ugnot", + }, + }, + expectedError: ErrMissingRPCClient, + }, + { + name: "Invalid Gas Fee", + client: Client{ + Signer: &mockSigner{}, + RPCClient: &mockRPCClient{}, + }, + cfg: BaseTxCfg{ + GasWanted: 100000, + GasFee: "", + AccountNumber: 1, + SequenceNumber: 1, + Memo: "Test memo", + }, + msgs: []MsgSend{ + { + ToAddress: toAddress, + Send: "1ugnot", + }, + }, + expectedError: ErrInvalidGasFee, + }, + { + name: "Negative Gas Wanted", + client: Client{ + Signer: &mockSigner{}, + RPCClient: &mockRPCClient{}, + }, + cfg: BaseTxCfg{ + GasWanted: -1, + GasFee: "10000ugnot", + AccountNumber: 1, + SequenceNumber: 1, + Memo: "Test memo", + }, + msgs: []MsgSend{ + { + ToAddress: toAddress, + Send: "1ugnot", + }, + }, + expectedError: ErrInvalidGasWanted, + }, + { + name: "0 Gas Wanted", + client: Client{ + Signer: &mockSigner{}, + RPCClient: &mockRPCClient{}, + }, + cfg: BaseTxCfg{ + GasWanted: 0, + GasFee: "10000ugnot", + AccountNumber: 1, + SequenceNumber: 1, + Memo: "Test memo", + }, + msgs: []MsgSend{ + { + ToAddress: toAddress, + Send: "1ugnot", + }, + }, + expectedError: ErrInvalidGasWanted, + }, + { + name: "Invalid To Address", + client: Client{ + Signer: &mockSigner{ + info: func() keys.Info { + return &mockKeysInfo{ + getAddress: func() crypto.Address { + adr, _ := crypto.AddressFromBech32("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") + return adr + }, + } + }, + }, + RPCClient: &mockRPCClient{}, + }, + cfg: BaseTxCfg{ + GasWanted: 100000, + GasFee: "10000ugnot", + AccountNumber: 1, + SequenceNumber: 1, + Memo: "Test memo", + }, + msgs: []MsgSend{ + { + ToAddress: crypto.Address{}, + Send: "1ugnot", + }, + }, + expectedError: ErrInvalidToAddress, + }, + { + name: "Invalid Send Coins", + client: Client{ + Signer: &mockSigner{ + info: func() keys.Info { + return &mockKeysInfo{ + getAddress: func() crypto.Address { + adr, _ := crypto.AddressFromBech32("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") + return adr + }, + } + }, + }, + RPCClient: &mockRPCClient{}, + }, + cfg: BaseTxCfg{ + GasWanted: 100000, + GasFee: "10000ugnot", + AccountNumber: 1, + SequenceNumber: 1, + Memo: "Test memo", + }, + msgs: []MsgSend{ + { + ToAddress: toAddress, + Send: "-1ugnot", + }, + }, + expectedError: ErrInvalidSendAmount, }, } - res, err := client.Run(RunCfg{ - Package: memPkg, - GasFee: "1ugnot", - GasWanted: 100000000, - }) - require.NoError(t, err) - require.NotNil(t, res) - require.NotEmpty(t, res.DeliverTx.Data) - require.Equal(t, string(res.DeliverTx.Data), "- before: 0\n- after: 10\n") + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + res, err := tc.client.Send(tc.cfg, tc.msgs...) + assert.Nil(t, res) + assert.ErrorIs(t, err, tc.expectedError) + }) + } } diff --git a/gno.land/pkg/gnoclient/client_txs.go b/gno.land/pkg/gnoclient/client_txs.go index db22fba93ad..39088bc30d5 100644 --- a/gno.land/pkg/gnoclient/client_txs.go +++ b/gno.land/pkg/gnoclient/client_txs.go @@ -5,21 +5,43 @@ import ( gno "github.com/gnolang/gno/gnovm/pkg/gnolang" "github.com/gnolang/gno/tm2/pkg/amino" ctypes "github.com/gnolang/gno/tm2/pkg/bft/rpc/core/types" + "github.com/gnolang/gno/tm2/pkg/crypto" "github.com/gnolang/gno/tm2/pkg/errors" + "github.com/gnolang/gno/tm2/pkg/sdk/bank" "github.com/gnolang/gno/tm2/pkg/std" ) -// CallCfg contains configuration options for executing a contract call. -type CallCfg struct { - PkgPath string // Package path - FuncName string // Function name - Args []string // Function arguments - GasFee string // Gas fee - GasWanted int64 // Gas wanted - Send string // Send amount - AccountNumber uint64 // Account number - SequenceNumber uint64 // Sequence number - Memo string // Memo +var ( + ErrEmptyPkgPath = errors.New("empty pkg path") + ErrEmptyFuncName = errors.New("empty function name") + ErrInvalidGasWanted = errors.New("invalid gas wanted") + ErrInvalidGasFee = errors.New("invalid gas fee") + ErrMissingSigner = errors.New("missing Signer") + ErrMissingRPCClient = errors.New("missing RPCClient") + ErrInvalidToAddress = errors.New("invalid send to address") + ErrInvalidSendAmount = errors.New("invalid send amount") +) + +type BaseTxCfg struct { + GasFee string // Gas fee + GasWanted int64 // Gas wanted + AccountNumber uint64 // Account number + SequenceNumber uint64 // Sequence number + Memo string // Memo +} + +// MsgCall - syntax sugar for vm.MsgCall +type MsgCall struct { + PkgPath string // Package path + FuncName string // Function name + Args []string // Function arguments + Send string // Send amount +} + +// MsgSend - syntax sugar for bank.MsgSend minus fields in BaseTxCfg +type MsgSend struct { + ToAddress crypto.Address // Send to address + Send string // Send amount } // RunCfg contains configuration options for running a temporary package on the blockchain. @@ -33,63 +55,125 @@ type RunCfg struct { } // Call executes a contract call on the blockchain. -func (c *Client) Call(cfg CallCfg) (*ctypes.ResultBroadcastTxCommit, error) { +func (c *Client) Call(cfg BaseTxCfg, msgs ...MsgCall) (*ctypes.ResultBroadcastTxCommit, error) { // Validate required client fields. if err := c.validateSigner(); err != nil { - return nil, errors.Wrap(err, "validate signer") + return nil, err } if err := c.validateRPCClient(); err != nil { - return nil, errors.Wrap(err, "validate RPC client") + return nil, err } - pkgPath := cfg.PkgPath - funcName := cfg.FuncName - args := cfg.Args - gasWanted := cfg.GasWanted - gasFee := cfg.GasFee - send := cfg.Send - sequenceNumber := cfg.SequenceNumber - accountNumber := cfg.AccountNumber - memo := cfg.Memo + // Validate base transaction config + if err := cfg.validateBaseTxConfig(); err != nil { + return nil, err + } - // Validate config. - if pkgPath == "" { - return nil, errors.New("missing PkgPath") + // Parse MsgCall slice + vmMsgs := make([]vm.MsgCall, 0, len(msgs)) + for _, msg := range msgs { + // Validate MsgCall fields + if err := msg.validateMsgCall(); err != nil { + return nil, err + } + + // Parse send coins + send, err := std.ParseCoins(msg.Send) + if err != nil { + return nil, err + } + + // Unwrap syntax sugar to vm.MsgCall slice + vmMsgs = append(vmMsgs, vm.MsgCall{ + Caller: c.Signer.Info().GetAddress(), + PkgPath: msg.PkgPath, + Func: msg.FuncName, + Args: msg.Args, + Send: send, + }) } - if funcName == "" { - return nil, errors.New("missing FuncName") + + // Cast vm.MsgCall back into std.Msg + stdMsgs := make([]std.Msg, len(vmMsgs)) + for i, msg := range vmMsgs { + stdMsgs[i] = msg } - // Parse send amount. - sendCoins, err := std.ParseCoins(send) + // Parse gas fee + gasFeeCoins, err := std.ParseCoin(cfg.GasFee) if err != nil { - return nil, errors.Wrap(err, "parsing send coins") + return nil, err } - // Parse gas wanted & fee. - gasFeeCoins, err := std.ParseCoin(gasFee) - if err != nil { - return nil, errors.Wrap(err, "parsing gas fee coin") + // Pack transaction + tx := std.Tx{ + Msgs: stdMsgs, + Fee: std.NewFee(cfg.GasWanted, gasFeeCoins), + Signatures: nil, + Memo: cfg.Memo, } - caller := c.Signer.Info().GetAddress() + return c.signAndBroadcastTxCommit(tx, cfg.AccountNumber, cfg.SequenceNumber) +} - // Construct message & transaction and marshal. - msg := vm.MsgCall{ - Caller: caller, - Send: sendCoins, - PkgPath: pkgPath, - Func: funcName, - Args: args, +// Send currency to an account on the blockchain. +func (c *Client) Send(cfg BaseTxCfg, msgs ...MsgSend) (*ctypes.ResultBroadcastTxCommit, error) { + // Validate required client fields. + if err := c.validateSigner(); err != nil { + return nil, err } + if err := c.validateRPCClient(); err != nil { + return nil, err + } + + // Validate base transaction config + if err := cfg.validateBaseTxConfig(); err != nil { + return nil, err + } + + // Parse MsgSend slice + vmMsgs := make([]bank.MsgSend, 0, len(msgs)) + for _, msg := range msgs { + // Validate MsgSend fields + if err := msg.validateMsgSend(); err != nil { + return nil, err + } + + // Parse send coins + send, err := std.ParseCoins(msg.Send) + if err != nil { + return nil, err + } + + // Unwrap syntax sugar to vm.MsgSend slice + vmMsgs = append(vmMsgs, bank.MsgSend{ + FromAddress: c.Signer.Info().GetAddress(), + ToAddress: msg.ToAddress, + Amount: send, + }) + } + + // Cast vm.MsgSend back into std.Msg + stdMsgs := make([]std.Msg, len(vmMsgs)) + for i, msg := range vmMsgs { + stdMsgs[i] = msg + } + + // Parse gas fee + gasFeeCoins, err := std.ParseCoin(cfg.GasFee) + if err != nil { + return nil, err + } + + // Pack transaction tx := std.Tx{ - Msgs: []std.Msg{msg}, - Fee: std.NewFee(gasWanted, gasFeeCoins), + Msgs: stdMsgs, + Fee: std.NewFee(cfg.GasWanted, gasFeeCoins), Signatures: nil, - Memo: memo, + Memo: cfg.Memo, } - return c.signAndBroadcastTxCommit(tx, accountNumber, sequenceNumber) + return c.signAndBroadcastTxCommit(tx, cfg.AccountNumber, cfg.SequenceNumber) } // Temporarily load cfg.Package on the blockchain and run main() which can @@ -130,7 +214,7 @@ func (c *Client) Run(cfg RunCfg) (*ctypes.ResultBroadcastTxCommit, error) { return nil, errors.Wrap(err, "precompile and check") } memPkg.Name = "main" - memPkg.Path = "gno.land/r/" + caller.String() + "/run" + memPkg.Path = "" // Construct message & transaction and marshal. msg := vm.MsgRun{ diff --git a/gno.land/pkg/gnoclient/integration_test.go b/gno.land/pkg/gnoclient/integration_test.go new file mode 100644 index 00000000000..4002e25077b --- /dev/null +++ b/gno.land/pkg/gnoclient/integration_test.go @@ -0,0 +1,232 @@ +package gnoclient + +import ( + "testing" + + "github.com/gnolang/gno/gno.land/pkg/integration" + "github.com/gnolang/gno/gnovm/pkg/gnoenv" + rpcclient "github.com/gnolang/gno/tm2/pkg/bft/rpc/client" + "github.com/gnolang/gno/tm2/pkg/crypto" + "github.com/gnolang/gno/tm2/pkg/crypto/keys" + "github.com/gnolang/gno/tm2/pkg/log" + "github.com/gnolang/gno/tm2/pkg/std" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestClient_Call_Single_Integration(t *testing.T) { + // Set up in-memory node + config, _ := integration.TestingNodeConfig(t, gnoenv.RootDir()) + node, remoteAddr := integration.TestingInMemoryNode(t, log.NewNoopLogger(), config) + defer node.Stop() + + // Init Signer & RPCClient + signer := newInMemorySigner(t, "tendermint_test") + rpcClient := rpcclient.NewHTTP(remoteAddr, "/websocket") + + // Setup Client + client := Client{ + Signer: signer, + RPCClient: rpcClient, + } + + // Make Tx config + baseCfg := BaseTxCfg{ + GasFee: "10000ugnot", + GasWanted: 8000000, + AccountNumber: 0, + SequenceNumber: 0, + Memo: "", + } + + // Make Msg config + msg := MsgCall{ + PkgPath: "gno.land/r/demo/deep/very/deep", + FuncName: "Render", + Args: []string{"test argument"}, + Send: "", + } + + // Execute call + res, err := client.Call(baseCfg, msg) + + expected := "(\"hi test argument\" string)" + got := string(res.DeliverTx.Data) + + assert.Nil(t, err) + assert.Equal(t, expected, got) +} + +func TestClient_Call_Multiple_Integration(t *testing.T) { + // Set up in-memory node + config, _ := integration.TestingNodeConfig(t, gnoenv.RootDir()) + node, remoteAddr := integration.TestingInMemoryNode(t, log.NewNoopLogger(), config) + defer node.Stop() + + // Init Signer & RPCClient + signer := newInMemorySigner(t, "tendermint_test") + rpcClient := rpcclient.NewHTTP(remoteAddr, "/websocket") + + // Setup Client + client := Client{ + Signer: signer, + RPCClient: rpcClient, + } + + // Make Tx config + baseCfg := BaseTxCfg{ + GasFee: "10000ugnot", + GasWanted: 8000000, + AccountNumber: 0, + SequenceNumber: 0, + Memo: "", + } + + // Make Msg configs + msg1 := MsgCall{ + PkgPath: "gno.land/r/demo/deep/very/deep", + FuncName: "Render", + Args: []string{""}, + Send: "", + } + + // Same call, different argument + msg2 := MsgCall{ + PkgPath: "gno.land/r/demo/deep/very/deep", + FuncName: "Render", + Args: []string{"test argument"}, + Send: "", + } + + expected := "(\"it works!\" string)(\"hi test argument\" string)" + + // Execute call + res, err := client.Call(baseCfg, msg1, msg2) + + got := string(res.DeliverTx.Data) + assert.Nil(t, err) + assert.Equal(t, expected, got) +} + +func TestClient_Send_Single_Integration(t *testing.T) { + // Set up in-memory node + config, _ := integration.TestingNodeConfig(t, gnoenv.RootDir()) + node, remoteAddr := integration.TestingInMemoryNode(t, log.NewNoopLogger(), config) + defer node.Stop() + + // Init Signer & RPCClient + signer := newInMemorySigner(t, "tendermint_test") + rpcClient := rpcclient.NewHTTP(remoteAddr, "/websocket") + + // Setup Client + client := Client{ + Signer: signer, + RPCClient: rpcClient, + } + + // Make Tx config + baseCfg := BaseTxCfg{ + GasFee: "10000ugnot", + GasWanted: 8000000, + AccountNumber: 0, + SequenceNumber: 0, + Memo: "", + } + + // Make Send config for a new address on the blockchain + toAddress, _ := crypto.AddressFromBech32("g14a0y9a64dugh3l7hneshdxr4w0rfkkww9ls35p") + amount := 10 + msg := MsgSend{ + ToAddress: toAddress, + Send: std.Coin{"ugnot", int64(amount)}.String(), + } + + // Execute send + res, err := client.Send(baseCfg, msg) + assert.Nil(t, err) + assert.Equal(t, "", string(res.DeliverTx.Data)) + + // Get the new account balance + account, _, err := client.QueryAccount(toAddress) + assert.Nil(t, err) + + expected := std.Coins{{"ugnot", int64(amount)}} + got := account.GetCoins() + + assert.Equal(t, expected, got) +} + +func TestClient_Send_Multiple_Integration(t *testing.T) { + // Set up in-memory node + config, _ := integration.TestingNodeConfig(t, gnoenv.RootDir()) + node, remoteAddr := integration.TestingInMemoryNode(t, log.NewNoopLogger(), config) + defer node.Stop() + + // Init Signer & RPCClient + signer := newInMemorySigner(t, "tendermint_test") + rpcClient := rpcclient.NewHTTP(remoteAddr, "/websocket") + + // Setup Client + client := Client{ + Signer: signer, + RPCClient: rpcClient, + } + + // Make Tx config + baseCfg := BaseTxCfg{ + GasFee: "10000ugnot", + GasWanted: 8000000, + AccountNumber: 0, + SequenceNumber: 0, + Memo: "", + } + + // Make Msg configs + toAddress, _ := crypto.AddressFromBech32("g14a0y9a64dugh3l7hneshdxr4w0rfkkww9ls35p") + amount1 := 10 + msg1 := MsgSend{ + ToAddress: toAddress, + Send: std.Coin{"ugnot", int64(amount1)}.String(), + } + + // Same send, different argument + amount2 := 20 + msg2 := MsgSend{ + ToAddress: toAddress, + Send: std.Coin{"ugnot", int64(amount2)}.String(), + } + + // Execute send + res, err := client.Send(baseCfg, msg1, msg2) + assert.Nil(t, err) + assert.Equal(t, "", string(res.DeliverTx.Data)) + + // Get the new account balance + account, _, err := client.QueryAccount(toAddress) + assert.Nil(t, err) + + expected := std.Coins{{"ugnot", int64(amount1 + amount2)}} + got := account.GetCoins() + + assert.Equal(t, expected, got) +} + +// todo add more integration tests. + +func newInMemorySigner(t *testing.T, chainid string) *SignerFromKeybase { + t.Helper() + + mnemonic := integration.DefaultAccount_Seed + name := integration.DefaultAccount_Name + + kb := keys.NewInMemory() + _, err := kb.CreateAccount(name, mnemonic, "", "", uint32(0), uint32(0)) + require.NoError(t, err) + + return &SignerFromKeybase{ + Keybase: kb, // Stores keys in memory or on disk + Account: name, // Account name or bech32 format + Password: "", // Password for encryption + ChainID: chainid, // Chain ID for transaction signing + } +} diff --git a/gno.land/pkg/gnoclient/mock_test.go b/gno.land/pkg/gnoclient/mock_test.go new file mode 100644 index 00000000000..4a12dfd2d88 --- /dev/null +++ b/gno.land/pkg/gnoclient/mock_test.go @@ -0,0 +1,284 @@ +package gnoclient + +import ( + "github.com/gnolang/gno/tm2/pkg/bft/rpc/client" + ctypes "github.com/gnolang/gno/tm2/pkg/bft/rpc/core/types" + "github.com/gnolang/gno/tm2/pkg/bft/types" + "github.com/gnolang/gno/tm2/pkg/crypto" + "github.com/gnolang/gno/tm2/pkg/crypto/hd" + "github.com/gnolang/gno/tm2/pkg/crypto/keys" + "github.com/gnolang/gno/tm2/pkg/std" +) + +// Signer mock +type ( + mockSign func(cfg SignCfg) (*std.Tx, error) + mockInfo func() keys.Info + mockValidate func() error +) + +type mockSigner struct { + sign mockSign + info mockInfo + validate mockValidate +} + +func (m *mockSigner) Sign(cfg SignCfg) (*std.Tx, error) { + if m.sign != nil { + return m.sign(cfg) + } + return nil, nil +} + +func (m *mockSigner) Info() keys.Info { + if m.info != nil { + return m.info() + } + return nil +} + +func (m *mockSigner) Validate() error { + if m.validate != nil { + return m.validate() + } + return nil +} + +// Keys Info mock +type ( + mockGetAddress func() crypto.Address + mockGetType func() keys.KeyType + mockGetName func() string + mockGetPubKey func() crypto.PubKey + mockGetPath func() (*hd.BIP44Params, error) +) + +type mockKeysInfo struct { + getAddress mockGetAddress + getType mockGetType + getName mockGetName + getPubKey mockGetPubKey + getPath mockGetPath +} + +func (m *mockKeysInfo) GetAddress() crypto.Address { + if m.getAddress != nil { + return m.getAddress() + } + return crypto.Address{} +} + +func (m *mockKeysInfo) GetType() keys.KeyType { + if m.getType != nil { + return m.getType() + } + return 0 +} + +func (m *mockKeysInfo) GetName() string { + if m.getName != nil { + return m.getName() + } + return "" +} + +func (m *mockKeysInfo) GetPubKey() crypto.PubKey { + if m.getPubKey != nil { + return m.getPubKey() + } + return nil +} + +func (m *mockKeysInfo) GetPath() (*hd.BIP44Params, error) { + if m.getPath != nil { + return m.getPath() + } + return nil, nil +} + +// RPC Client mock +type ( + mockBroadcastTxCommit func(tx types.Tx) (*ctypes.ResultBroadcastTxCommit, error) + mockABCIQuery func(path string, data []byte) (*ctypes.ResultABCIQuery, error) + mockABCIInfo func() (*ctypes.ResultABCIInfo, error) + mockABCIQueryWithOptions func(path string, data []byte, opts client.ABCIQueryOptions) (*ctypes.ResultABCIQuery, error) + mockBroadcastTxAsync func(tx types.Tx) (*ctypes.ResultBroadcastTx, error) + mockBroadcastTxSync func(tx types.Tx) (*ctypes.ResultBroadcastTx, error) + mockGenesis func() (*ctypes.ResultGenesis, error) + mockBlockchainInfo func(minHeight, maxHeight int64) (*ctypes.ResultBlockchainInfo, error) + mockNetInfo func() (*ctypes.ResultNetInfo, error) + mockDumpConsensusState func() (*ctypes.ResultDumpConsensusState, error) + mockConsensusState func() (*ctypes.ResultConsensusState, error) + mockConsensusParams func(height *int64) (*ctypes.ResultConsensusParams, error) + mockHealth func() (*ctypes.ResultHealth, error) + mockBlock func(height *int64) (*ctypes.ResultBlock, error) + mockBlockResults func(height *int64) (*ctypes.ResultBlockResults, error) + mockCommit func(height *int64) (*ctypes.ResultCommit, error) + mockValidators func(height *int64) (*ctypes.ResultValidators, error) + mockStatus func() (*ctypes.ResultStatus, error) + mockUnconfirmedTxs func(limit int) (*ctypes.ResultUnconfirmedTxs, error) + mockNumUnconfirmedTxs func() (*ctypes.ResultUnconfirmedTxs, error) +) + +type mockRPCClient struct { + broadcastTxCommit mockBroadcastTxCommit + abciQuery mockABCIQuery + abciInfo mockABCIInfo + abciQueryWithOptions mockABCIQueryWithOptions + broadcastTxAsync mockBroadcastTxAsync + broadcastTxSync mockBroadcastTxSync + genesis mockGenesis + blockchainInfo mockBlockchainInfo + netInfo mockNetInfo + dumpConsensusState mockDumpConsensusState + consensusState mockConsensusState + consensusParams mockConsensusParams + health mockHealth + block mockBlock + blockResults mockBlockResults + commit mockCommit + validators mockValidators + status mockStatus + unconfirmedTxs mockUnconfirmedTxs + numUnconfirmedTxs mockNumUnconfirmedTxs +} + +func (m *mockRPCClient) BroadcastTxCommit(tx types.Tx) (*ctypes.ResultBroadcastTxCommit, error) { + if m.broadcastTxCommit != nil { + return m.broadcastTxCommit(tx) + } + return nil, nil +} + +func (m *mockRPCClient) ABCIQuery(path string, data []byte) (*ctypes.ResultABCIQuery, error) { + if m.abciQuery != nil { + return m.abciQuery(path, data) + } + return nil, nil +} + +func (m *mockRPCClient) ABCIInfo() (*ctypes.ResultABCIInfo, error) { + if m.abciInfo != nil { + return m.ABCIInfo() + } + return nil, nil +} + +func (m *mockRPCClient) ABCIQueryWithOptions(path string, data []byte, opts client.ABCIQueryOptions) (*ctypes.ResultABCIQuery, error) { + if m.abciQueryWithOptions != nil { + return m.abciQueryWithOptions(path, data, opts) + } + return nil, nil +} + +func (m *mockRPCClient) BroadcastTxAsync(tx types.Tx) (*ctypes.ResultBroadcastTx, error) { + if m.broadcastTxAsync != nil { + return m.broadcastTxAsync(tx) + } + return nil, nil +} + +func (m *mockRPCClient) BroadcastTxSync(tx types.Tx) (*ctypes.ResultBroadcastTx, error) { + if m.broadcastTxSync != nil { + return m.broadcastTxSync(tx) + } + return nil, nil +} + +func (m *mockRPCClient) Genesis() (*ctypes.ResultGenesis, error) { + if m.genesis != nil { + return m.genesis() + } + return nil, nil +} + +func (m *mockRPCClient) BlockchainInfo(minHeight, maxHeight int64) (*ctypes.ResultBlockchainInfo, error) { + if m.blockchainInfo != nil { + return m.blockchainInfo(minHeight, maxHeight) + } + return nil, nil +} + +func (m *mockRPCClient) NetInfo() (*ctypes.ResultNetInfo, error) { + if m.netInfo != nil { + return m.netInfo() + } + return nil, nil +} + +func (m *mockRPCClient) DumpConsensusState() (*ctypes.ResultDumpConsensusState, error) { + if m.dumpConsensusState != nil { + return m.dumpConsensusState() + } + return nil, nil +} + +func (m *mockRPCClient) ConsensusState() (*ctypes.ResultConsensusState, error) { + if m.consensusState != nil { + return m.consensusState() + } + return nil, nil +} + +func (m *mockRPCClient) ConsensusParams(height *int64) (*ctypes.ResultConsensusParams, error) { + if m.consensusParams != nil { + return m.consensusParams(height) + } + return nil, nil +} + +func (m *mockRPCClient) Health() (*ctypes.ResultHealth, error) { + if m.health != nil { + return m.health() + } + return nil, nil +} + +func (m *mockRPCClient) Block(height *int64) (*ctypes.ResultBlock, error) { + if m.block != nil { + return m.block(height) + } + return nil, nil +} + +func (m *mockRPCClient) BlockResults(height *int64) (*ctypes.ResultBlockResults, error) { + if m.blockResults != nil { + return m.blockResults(height) + } + return nil, nil +} + +func (m *mockRPCClient) Commit(height *int64) (*ctypes.ResultCommit, error) { + if m.commit != nil { + return m.commit(height) + } + return nil, nil +} + +func (m *mockRPCClient) Validators(height *int64) (*ctypes.ResultValidators, error) { + if m.validators != nil { + return m.validators(height) + } + return nil, nil +} + +func (m *mockRPCClient) Status() (*ctypes.ResultStatus, error) { + if m.status != nil { + return m.status() + } + return nil, nil +} + +func (m *mockRPCClient) UnconfirmedTxs(limit int) (*ctypes.ResultUnconfirmedTxs, error) { + if m.unconfirmedTxs != nil { + return m.unconfirmedTxs(limit) + } + return nil, nil +} + +func (m *mockRPCClient) NumUnconfirmedTxs() (*ctypes.ResultUnconfirmedTxs, error) { + if m.numUnconfirmedTxs != nil { + return m.numUnconfirmedTxs() + } + return nil, nil +} diff --git a/gno.land/pkg/gnoclient/util.go b/gno.land/pkg/gnoclient/util.go new file mode 100644 index 00000000000..398bbca08fc --- /dev/null +++ b/gno.land/pkg/gnoclient/util.go @@ -0,0 +1,35 @@ +package gnoclient + +import "github.com/gnolang/gno/tm2/pkg/std" + +func (cfg BaseTxCfg) validateBaseTxConfig() error { + if cfg.GasWanted <= 0 { + return ErrInvalidGasWanted + } + if cfg.GasFee == "" { + return ErrInvalidGasFee + } + + return nil +} + +func (msg MsgCall) validateMsgCall() error { + if msg.PkgPath == "" { + return ErrEmptyPkgPath + } + if msg.FuncName == "" { + return ErrEmptyFuncName + } + return nil +} + +func (msg MsgSend) validateMsgSend() error { + if msg.ToAddress.IsZero() { + return ErrInvalidToAddress + } + _, err := std.ParseCoins(msg.Send) + if err != nil { + return ErrInvalidSendAmount + } + return nil +} diff --git a/gno.land/pkg/gnoland/app.go b/gno.land/pkg/gnoland/app.go index 0b0488fc98e..007ec4a7633 100644 --- a/gno.land/pkg/gnoland/app.go +++ b/gno.land/pkg/gnoland/app.go @@ -2,10 +2,9 @@ package gnoland import ( "fmt" + "log/slog" "path/filepath" - "golang.org/x/exp/slog" - "github.com/gnolang/gno/gno.land/pkg/sdk/vm" "github.com/gnolang/gno/gnovm/pkg/gnoenv" "github.com/gnolang/gno/tm2/pkg/amino" diff --git a/gno.land/pkg/gnoland/node_inmemory.go b/gno.land/pkg/gnoland/node_inmemory.go index 2db8544a909..6301883128a 100644 --- a/gno.land/pkg/gnoland/node_inmemory.go +++ b/gno.land/pkg/gnoland/node_inmemory.go @@ -2,11 +2,10 @@ package gnoland import ( "fmt" + "log/slog" "sync" "time" - "golang.org/x/exp/slog" - abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" tmcfg "github.com/gnolang/gno/tm2/pkg/bft/config" "github.com/gnolang/gno/tm2/pkg/bft/node" diff --git a/gno.land/pkg/gnoweb/gnoweb.go b/gno.land/pkg/gnoweb/gnoweb.go index 451389c7d73..4854ed4791e 100644 --- a/gno.land/pkg/gnoweb/gnoweb.go +++ b/gno.land/pkg/gnoweb/gnoweb.go @@ -7,6 +7,7 @@ import ( "fmt" "io" "io/fs" + "log/slog" "net/http" "os" "path/filepath" @@ -14,8 +15,6 @@ import ( "strings" "time" - "golang.org/x/exp/slog" - "github.com/gnolang/gno/tm2/pkg/amino" abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" "github.com/gnolang/gno/tm2/pkg/bft/rpc/client" diff --git a/gno.land/pkg/integration/testing_integration.go b/gno.land/pkg/integration/testing_integration.go index b0dcc5737e6..04382076816 100644 --- a/gno.land/pkg/integration/testing_integration.go +++ b/gno.land/pkg/integration/testing_integration.go @@ -5,14 +5,13 @@ import ( "errors" "fmt" "hash/crc32" + "log/slog" "os" "path/filepath" "strconv" "strings" "testing" - "golang.org/x/exp/slog" - "github.com/gnolang/gno/gno.land/pkg/gnoland" "github.com/gnolang/gno/gno.land/pkg/keyscli" "github.com/gnolang/gno/gno.land/pkg/log" diff --git a/gno.land/pkg/integration/testing_node.go b/gno.land/pkg/integration/testing_node.go index b0aa9f7c2af..b164c267e87 100644 --- a/gno.land/pkg/integration/testing_node.go +++ b/gno.land/pkg/integration/testing_node.go @@ -1,11 +1,10 @@ package integration import ( + "log/slog" "path/filepath" "time" - "golang.org/x/exp/slog" - "github.com/gnolang/gno/gno.land/pkg/gnoland" abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" tmcfg "github.com/gnolang/gno/tm2/pkg/bft/config" @@ -32,8 +31,8 @@ func TestingInMemoryNode(t TestingTS, logger *slog.Logger, config *gnoland.InMem require.NoError(t, err) select { - case <-gnoland.GetNodeReadiness(node): - case <-time.After(time.Second * 6): + case <-node.Ready(): + case <-time.After(time.Second * 10): require.FailNow(t, "timeout while waiting for the node to start") } diff --git a/gno.land/pkg/keyscli/run.go b/gno.land/pkg/keyscli/run.go index e04452dde09..7d329c18566 100644 --- a/gno.land/pkg/keyscli/run.go +++ b/gno.land/pkg/keyscli/run.go @@ -114,7 +114,8 @@ func execMakeRun(cfg *MakeRunCfg, args []string, cmdio commands.IO) error { panic(err) } memPkg.Name = "main" - memPkg.Path = "gno.land/r/" + caller.String() + "/run" + // Set to empty; this will be automatically set by the VM keeper. + memPkg.Path = "" // construct msg & tx and marshal. msg := vm.MsgRun{ diff --git a/gno.land/pkg/log/zap.go b/gno.land/pkg/log/zap.go index a68e034eab6..38a9f13e4fc 100644 --- a/gno.land/pkg/log/zap.go +++ b/gno.land/pkg/log/zap.go @@ -2,8 +2,7 @@ package log import ( "io" - - "golang.org/x/exp/slog" + "log/slog" "go.uber.org/zap" "go.uber.org/zap/exp/zapslog" @@ -72,5 +71,5 @@ func NewZapLogger(enc zapcore.Encoder, w io.Writer, level zapcore.Level, opts .. // ZapLoggerToSlog wraps the given zap logger to an log/slog Logger func ZapLoggerToSlog(logger *zap.Logger) *slog.Logger { - return slog.New(zapslog.NewHandler(logger.Core())) + return slog.New(zapslog.NewHandler(logger.Core(), nil)) } diff --git a/gno.land/pkg/sdk/vm/convert.go b/gno.land/pkg/sdk/vm/convert.go index de4db67fb04..f70f99403a8 100644 --- a/gno.land/pkg/sdk/vm/convert.go +++ b/gno.land/pkg/sdk/vm/convert.go @@ -5,9 +5,16 @@ import ( "fmt" "strconv" + "github.com/cockroachdb/apd/v3" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" ) +func assertCharNotPlus(b byte) { + if b == '+' { + panic("numbers cannot start with +") + } +} + // These convert string representations of public-facing arguments to GNO types. // The limited set of input types available should map 1:1 to types supported // in FunctionSignature{}. @@ -34,9 +41,7 @@ func convertArgToGno(arg string, argT gno.Type) (tv gno.TypedValue) { tv.SetString(gno.StringValue(arg)) return case gno.IntType: - if arg[0] == '+' { - panic("numbers cannot start with +") - } + assertCharNotPlus(arg[0]) i64, err := strconv.ParseInt(arg, 10, 64) if err != nil { panic(fmt.Sprintf( @@ -46,9 +51,7 @@ func convertArgToGno(arg string, argT gno.Type) (tv gno.TypedValue) { tv.SetInt(int(i64)) return case gno.Int8Type: - if arg[0] == '+' { - panic("numbers cannot start with +") - } + assertCharNotPlus(arg[0]) i8, err := strconv.ParseInt(arg, 10, 8) if err != nil { panic(fmt.Sprintf( @@ -58,9 +61,7 @@ func convertArgToGno(arg string, argT gno.Type) (tv gno.TypedValue) { tv.SetInt8(int8(i8)) return case gno.Int16Type: - if arg[0] == '+' { - panic("numbers cannot start with +") - } + assertCharNotPlus(arg[0]) i16, err := strconv.ParseInt(arg, 10, 16) if err != nil { panic(fmt.Sprintf( @@ -70,9 +71,7 @@ func convertArgToGno(arg string, argT gno.Type) (tv gno.TypedValue) { tv.SetInt16(int16(i16)) return case gno.Int32Type: - if arg[0] == '+' { - panic("numbers cannot start with +") - } + assertCharNotPlus(arg[0]) i32, err := strconv.ParseInt(arg, 10, 32) if err != nil { panic(fmt.Sprintf( @@ -82,9 +81,7 @@ func convertArgToGno(arg string, argT gno.Type) (tv gno.TypedValue) { tv.SetInt32(int32(i32)) return case gno.Int64Type: - if arg[0] == '+' { - panic("numbers cannot start with +") - } + assertCharNotPlus(arg[0]) i64, err := strconv.ParseInt(arg, 10, 64) if err != nil { panic(fmt.Sprintf( @@ -94,9 +91,7 @@ func convertArgToGno(arg string, argT gno.Type) (tv gno.TypedValue) { tv.SetInt64(i64) return case gno.UintType: - if arg[0] == '+' { - panic("numbers cannot start with +") - } + assertCharNotPlus(arg[0]) u64, err := strconv.ParseUint(arg, 10, 64) if err != nil { panic(fmt.Sprintf( @@ -106,9 +101,7 @@ func convertArgToGno(arg string, argT gno.Type) (tv gno.TypedValue) { tv.SetUint(uint(u64)) return case gno.Uint8Type: - if arg[0] == '+' { - panic("numbers cannot start with +") - } + assertCharNotPlus(arg[0]) u8, err := strconv.ParseUint(arg, 10, 8) if err != nil { panic(fmt.Sprintf( @@ -118,9 +111,7 @@ func convertArgToGno(arg string, argT gno.Type) (tv gno.TypedValue) { tv.SetUint8(uint8(u8)) return case gno.Uint16Type: - if arg[0] == '+' { - panic("numbers cannot start with +") - } + assertCharNotPlus(arg[0]) u16, err := strconv.ParseUint(arg, 10, 16) if err != nil { panic(fmt.Sprintf( @@ -130,9 +121,7 @@ func convertArgToGno(arg string, argT gno.Type) (tv gno.TypedValue) { tv.SetUint16(uint16(u16)) return case gno.Uint32Type: - if arg[0] == '+' { - panic("numbers cannot start with +") - } + assertCharNotPlus(arg[0]) u32, err := strconv.ParseUint(arg, 10, 32) if err != nil { panic(fmt.Sprintf( @@ -142,9 +131,7 @@ func convertArgToGno(arg string, argT gno.Type) (tv gno.TypedValue) { tv.SetUint32(uint32(u32)) return case gno.Uint64Type: - if arg[0] == '+' { - panic("numbers cannot start with +") - } + assertCharNotPlus(arg[0]) u64, err := strconv.ParseUint(arg, 10, 64) if err != nil { panic(fmt.Sprintf( @@ -153,6 +140,14 @@ func convertArgToGno(arg string, argT gno.Type) (tv gno.TypedValue) { } tv.SetUint64(u64) return + case gno.Float32Type: + value := convertFloat(arg, 32) + tv.SetFloat32(float32(value)) + return + case gno.Float64Type: + value := convertFloat(arg, 64) + tv.SetFloat64(value) + return default: panic(fmt.Sprintf("unexpected primitive type %s", bt.String())) } @@ -195,3 +190,18 @@ func convertArgToGno(arg string, argT gno.Type) (tv gno.TypedValue) { panic(fmt.Sprintf("unexpected type in contract arg: %v", argT)) } } + +func convertFloat(value string, precision int) float64 { + assertCharNotPlus(value[0]) + dec, _, err := apd.NewFromString(value) + if err != nil { + panic(fmt.Sprintf("error parsing float%d %s: %v", precision, value, err)) + } + + f64, err := strconv.ParseFloat(dec.String(), precision) + if err != nil { + panic(fmt.Sprintf("error value exceeds float%d precision %s: %v", precision, value, err)) + } + + return f64 +} diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index 16162e1004c..54f424ee058 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -131,7 +131,7 @@ func (vm *VMKeeper) getGnoStore(ctx sdk.Context) gno.Store { } } -var reReservedPath = regexp.MustCompile(`gno\.land/r/g[a-z0-9]+/run`) +var reRunPath = regexp.MustCompile(`gno\.land/r/g[a-z0-9]+/run`) // AddPackage adds a package with given fileset. func (vm *VMKeeper) AddPackage(ctx sdk.Context, msg MsgAddPackage) error { @@ -156,7 +156,7 @@ func (vm *VMKeeper) AddPackage(ctx sdk.Context, msg MsgAddPackage) error { return ErrInvalidPkgPath("package already exists: " + pkgPath) } - if reReservedPath.MatchString(pkgPath) { + if reRunPath.MatchString(pkgPath) { return ErrInvalidPkgPath("reserved package name: " + pkgPath) } @@ -240,6 +240,9 @@ func (vm *VMKeeper) Call(ctx sdk.Context, msg MsgCall) (res string, err error) { if cx.Varg { panic("variadic calls not yet supported") } + if len(msg.Args) != len(ft.Params) { + panic(fmt.Sprintf("wrong number of arguments in call to %s: want %d got %d", fnc, len(ft.Params), len(msg.Args))) + } for i, arg := range msg.Args { argType := ft.Params[i].Type atv := convertArgToGno(arg, argType) @@ -300,6 +303,11 @@ func (vm *VMKeeper) Run(ctx sdk.Context, msg MsgRun) (res string, err error) { send := msg.Send memPkg := msg.Package + // coerce path to right one. + // the path in the message must be "" or the following path. + // this is already checked in MsgRun.ValidateBasic + memPkg.Path = "gno.land/r/" + msg.Caller.String() + "/run" + // Validate arguments. callerAcc := vm.acck.GetAccount(ctx, caller) if callerAcc == nil { diff --git a/gno.land/pkg/sdk/vm/keeper_test.go b/gno.land/pkg/sdk/vm/keeper_test.go index 294efa66fa5..bc6bc285704 100644 --- a/gno.land/pkg/sdk/vm/keeper_test.go +++ b/gno.land/pkg/sdk/vm/keeper_test.go @@ -395,3 +395,44 @@ func main() { expectedString := fmt.Sprintf("hello world! %s\n", addr.String()) assert.Equal(t, res, expectedString) } + +func TestNumberOfArgsError(t *testing.T) { + env := setupTestEnv() + ctx := env.ctx + + // Give "addr1" some gnots. + addr := crypto.AddressFromPreimage([]byte("addr1")) + acc := env.acck.NewAccountWithAddress(ctx, addr) + env.acck.SetAccount(ctx, acc) + env.bank.SetCoins(ctx, addr, std.MustParseCoins("10000000ugnot")) + assert.True(t, env.bank.GetCoins(ctx, addr).IsEqual(std.MustParseCoins("10000000ugnot"))) + + // Create test package. + files := []*std.MemFile{ + { + Name: "test.gno", + Body: `package test + +import "std" + +func Echo(msg string) string { + return "echo:"+msg +}`, + }, + } + pkgPath := "gno.land/r/test" + msg1 := NewMsgAddPackage(addr, pkgPath, files) + err := env.vmk.AddPackage(ctx, msg1) + assert.NoError(t, err) + + // Call Echo function with wrong number of arguments + coins := std.MustParseCoins("1ugnot") + msg2 := NewMsgCall(addr, coins, pkgPath, "Echo", []string{"hello world", "extra arg"}) + assert.PanicsWithValue( + t, + func() { + env.vmk.Call(ctx, msg2) + }, + "wrong number of arguments in call to Echo: want 1 got 2", + ) +} diff --git a/gno.land/pkg/sdk/vm/msgs.go b/gno.land/pkg/sdk/vm/msgs.go index f1e65ae25cb..e42babe1510 100644 --- a/gno.land/pkg/sdk/vm/msgs.go +++ b/gno.land/pkg/sdk/vm/msgs.go @@ -1,6 +1,7 @@ package vm import ( + "fmt" "strings" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" @@ -162,7 +163,7 @@ func NewMsgRun(caller crypto.Address, send std.Coins, files []*std.MemFile) MsgR Send: send, Package: &std.MemPackage{ Name: "main", - Path: "gno.land/r/" + caller.String() + "/run", + Path: "", // auto set by the handler Files: files, }, } @@ -179,9 +180,13 @@ func (msg MsgRun) ValidateBasic() error { if msg.Caller.IsZero() { return std.ErrInvalidAddress("missing caller address") } - if msg.Package.Path == "" { // XXX - return ErrInvalidPkgPath("missing package path") + + // Force memPkg path to the reserved run path. + wantPath := "gno.land/r/" + msg.Caller.String() + "/run" + if path := msg.Package.Path; path != "" && path != wantPath { + return ErrInvalidPkgPath(fmt.Sprintf("invalid pkgpath for MsgRun: %q", path)) } + return nil } diff --git a/gnovm/cmd/gno/test.go b/gnovm/cmd/gno/test.go index ae3f2334ecf..1deac5aac48 100644 --- a/gnovm/cmd/gno/test.go +++ b/gnovm/cmd/gno/test.go @@ -174,7 +174,7 @@ func execTest(cfg *testCfg, args []string, io commands.IO) error { // go.mod modPath := filepath.Join(tempdirRoot, "go.mod") - err = makeTestGoMod(modPath, gno.ImportPrefix, "1.20") + err = makeTestGoMod(modPath, gno.ImportPrefix, "1.21") if err != nil { return fmt.Errorf("write .mod file: %w", err) } diff --git a/gnovm/cmd/gno/testdata/gno_precompile/03_invalid_gno_files.txtar b/gnovm/cmd/gno/testdata/gno_precompile/03_gno_files_parse_error.txtar similarity index 65% rename from gnovm/cmd/gno/testdata/gno_precompile/03_invalid_gno_files.txtar rename to gnovm/cmd/gno/testdata/gno_precompile/03_gno_files_parse_error.txtar index 26e12a9c750..f4cd79c1db5 100644 --- a/gnovm/cmd/gno/testdata/gno_precompile/03_invalid_gno_files.txtar +++ b/gnovm/cmd/gno/testdata/gno_precompile/03_gno_files_parse_error.txtar @@ -1,4 +1,4 @@ -# Run gno precompile with invalid gno files +# Run gno precompile with gno files with parse errors ! gno precompile . @@ -6,6 +6,10 @@ stderr 'precompile: parse: main.gno:3:1: expected declaration, found invalid' stderr 'precompile: parse: sub/sub.gno:3:1: expected declaration, found invalid' +# no *.gen.go files are created +! exec test -f main.gno.gen.go +! exec test -f sub/sub.gno.gen.go + -- main.gno -- package main diff --git a/gnovm/cmd/gno/testdata/gno_precompile/08_build_flag_with_parse_error.txtar b/gnovm/cmd/gno/testdata/gno_precompile/08_build_flag_with_parse_error.txtar new file mode 100644 index 00000000000..4d2b5ad8041 --- /dev/null +++ b/gnovm/cmd/gno/testdata/gno_precompile/08_build_flag_with_parse_error.txtar @@ -0,0 +1,14 @@ +# Run gno precompile with -gobuild flag on file with parse error + +! gno precompile -gobuild . + +! stdout .+ +stderr 'main.gno: precompile: parse: main.gno:3:1: expected declaration, found invalid' + +# no *.gen.go files are created +! exec test -f main.gno.gen.go + +-- main.gno -- +package main + +invalid diff --git a/gnovm/cmd/gno/testdata/gno_precompile/09_gno_files_whitelist_error.txtar b/gnovm/cmd/gno/testdata/gno_precompile/09_gno_files_whitelist_error.txtar new file mode 100644 index 00000000000..f2386716ce6 --- /dev/null +++ b/gnovm/cmd/gno/testdata/gno_precompile/09_gno_files_whitelist_error.txtar @@ -0,0 +1,26 @@ +# Run gno precompile with gno files with whitelist errors + +! gno precompile . + +! stdout .+ +stderr 'main.gno: precompile: import "xxx" is not in the whitelist' +stderr 'sub/sub.gno: precompile: import "xxx" is not in the whitelist' + +# no *.gen.go files are created +! exec test -f main.gno.gen.go +! exec test -f sub/sub.gno.gen.go + +-- main.gno -- +package main + +import ( + "std" + "xxx" +) + +func main() {} + +-- sub/sub.gno -- +package sub + +import "xxx" diff --git a/gnovm/pkg/gnolang/benchdata/fib.gno b/gnovm/pkg/gnolang/benchdata/fib.gno new file mode 100644 index 00000000000..75f2b0b15d6 --- /dev/null +++ b/gnovm/pkg/gnolang/benchdata/fib.gno @@ -0,0 +1,16 @@ +// param: 4 8 16 + +package main + +func main() { + for i := 0; i < {{ .N }}; i++ { + fib({{ .Param }}) + } +} + +func fib(n int) int { + if n < 2 { + return 1 + } + return fib(n-1) + fib(n-2) +} diff --git a/gnovm/pkg/gnolang/benchdata/loop.gno b/gnovm/pkg/gnolang/benchdata/loop.gno new file mode 100644 index 00000000000..0effa823f0d --- /dev/null +++ b/gnovm/pkg/gnolang/benchdata/loop.gno @@ -0,0 +1,5 @@ +package main + +func main() { + for i := 0; i < {{ .N }}; i++ {} +} diff --git a/gnovm/pkg/gnolang/benchdata/matrix.gno b/gnovm/pkg/gnolang/benchdata/matrix.gno new file mode 100644 index 00000000000..429323df65d --- /dev/null +++ b/gnovm/pkg/gnolang/benchdata/matrix.gno @@ -0,0 +1,90 @@ +// param: 3 4 5 6 + +package main + +func main() { + const p = {{ .Param }} + for i := 0; i < {{ .N }}; i++ { + _ = det(mul(dist(p), mul(id(p), dist(p)))) + } +} + +// identity matrix +func id(sz int) [][]int { + r := make([][]int, sz) + for i := range r { + r[i] = make([]int, sz) + r[i][i] = 1 + } + return r +} + +// distance from corner +func dist(sz int) [][]int { + half := sz / 2 + r := make([][]int, sz) + for i := range r { + r[i] = make([]int, sz) + vdist := i + if vdist >= half { + vdist = sz - 1 - i + } + for j := range r[i] { + hdist := j + if hdist >= half { + hdist = sz - 1 - j + } + r[i][j] = vdist + hdist + } + } + return r +} + +func det(m [][]int) int { + size := len(m) + if size == 2 { + return m[0][0]*m[1][1] - m[0][1]*m[1][0] + } + subMatrix := make([][]int, size-1) + for j := range subMatrix { + subMatrix[j] = make([]int, size-1) + } + + determinant := 0 + for i := 0; i < size; i++ { + for j := 1; j < size; j++ { + t := 0 + for k := 0; k < size; k++ { + if k == i { + continue + } + subMatrix[j-1][t] = m[j][k] + t++ + } + } + sign := 1 + if i % 2 == 1 { + sign = -1 + } + determinant += m[0][i] * det(subMatrix) * sign + } + return determinant +} + +func mul(m1, m2 [][]int) [][]int { + size := len(m1) + result := make([][]int, size) + for i := range result { + result[i] = make([]int, size) + } + + for i := 0; i < size; i++ { + for j := 0; j < size; j++ { + for k := 0; k < size; k++ { + result[i][j] += m1[i][k] * m2[k][j] + } + } + } + + return result +} diff --git a/gnovm/pkg/gnolang/gno_test.go b/gnovm/pkg/gnolang/gno_test.go index 5c50b0830a6..d8bdcdfd4a0 100644 --- a/gnovm/pkg/gnolang/gno_test.go +++ b/gnovm/pkg/gnolang/gno_test.go @@ -3,12 +3,18 @@ package gnolang import ( "bytes" "fmt" + "io" + "os" + "path/filepath" "reflect" + "strings" "testing" + "text/template" "unsafe" // "github.com/davecgh/go-spew/spew" "github.com/jaekwon/testify/assert" + "github.com/jaekwon/testify/require" ) // run empty main(). @@ -192,43 +198,84 @@ func main() { // Benchmarks func BenchmarkPreprocess(b *testing.B) { - for i := 0; i < b.N; i++ { - // stop timer - b.StopTimer() - pkg := &PackageNode{ - PkgName: "main", - PkgPath: ".main", - FileSet: nil, - } - pkg.InitStaticBlock(pkg, nil) - main := FuncD("main", nil, nil, Ss( - A("mx", ":=", "1000000"), - For( - A("i", ":=", "0"), - X("i < mx"), - Inc("i"), - ), - )) - b.StartTimer() - // timer started - main = Preprocess(nil, pkg, main).(*FuncDecl) + pkg := &PackageNode{ + PkgName: "main", + PkgPath: ".main", + FileSet: nil, } -} - -func BenchmarkLoopyMain(b *testing.B) { - m := NewMachine("test", nil) + pkg.InitStaticBlock(pkg, nil) main := FuncD("main", nil, nil, Ss( - A("mx", ":=", "10000000"), + A("mx", ":=", "1000000"), For( A("i", ":=", "0"), - // X("i < 10000000"), X("i < mx"), Inc("i"), ), )) - m.RunDeclaration(main) + copies := make([]*FuncDecl, b.N) + for i := 0; i < b.N; i++ { + copies[i] = main.Copy().(*FuncDecl) + } + b.ResetTimer() + for i := 0; i < b.N; i++ { - m.RunMain() + main = Preprocess(nil, pkg, copies[i]).(*FuncDecl) + } +} + +type bdataParams struct { + N int + Param string +} + +func BenchmarkBenchdata(b *testing.B) { + const bdDir = "./benchdata" + files, err := os.ReadDir(bdDir) + require.NoError(b, err) + for _, file := range files { + // Read file and parse template. + bcont, err := os.ReadFile(filepath.Join(bdDir, file.Name())) + cont := string(bcont) + require.NoError(b, err) + tpl, err := template.New("").Parse(cont) + require.NoError(b, err) + + // Determine parameters. + const paramString = "// param: " + var params []string + pos := strings.Index(cont, paramString) + if pos >= 0 { + paramsRaw := strings.SplitN(cont[pos+len(paramString):], "\n", 2)[0] + params = strings.Fields(paramsRaw) + } else { + params = []string{""} + } + + for _, param := range params { + name := file.Name() + if param != "" { + name += "_param:" + param + } + b.Run(name, func(b *testing.B) { + // Gen template with N and param. + var buf bytes.Buffer + require.NoError(b, tpl.Execute(&buf, bdataParams{ + N: b.N, + Param: param, + })) + + // Set up machine. + m := NewMachineWithOptions(MachineOptions{ + PkgPath: "main", + Output: io.Discard, + }) + n := MustParseFile("main.go", buf.String()) + m.RunFiles(n) + + b.ResetTimer() + m.RunMain() + }) + } } } diff --git a/gnovm/pkg/gnolang/go_bench_test.go b/gnovm/pkg/gnolang/go_bench_test.go deleted file mode 100644 index 837d7625f35..00000000000 --- a/gnovm/pkg/gnolang/go_bench_test.go +++ /dev/null @@ -1,420 +0,0 @@ -package gnolang - -import ( - "fmt" - "reflect" - "testing" -) - -type BenchValue interface { - Int32() int32 -} - -type ( - Int32 int32 - Int32a int32 - Int32b int32 - Int32c int32 - Int32d int32 - Int32e int32 - Int32f int32 - Int32g int32 - Int32h int32 - Int32i int32 - Int32j int32 - Int32k int32 -) - -func (i Int32) Int32() int32 { return int32(i) } -func (i Int32a) Int32() int32 { return int32(i) } -func (i Int32b) Int32() int32 { return int32(i) } -func (i Int32c) Int32() int32 { return int32(i) } -func (i Int32d) Int32() int32 { return int32(i) } -func (i Int32e) Int32() int32 { return int32(i) } -func (i Int32f) Int32() int32 { return int32(i) } -func (i Int32g) Int32() int32 { return int32(i) } -func (i Int32h) Int32() int32 { return int32(i) } -func (i Int32i) Int32() int32 { return int32(i) } -func (i Int32j) Int32() int32 { return int32(i) } -func (i Int32k) Int32() int32 { return int32(i) } - -func BenchmarkMapSet(b *testing.B) { - m := make(map[int32]int32) - for i := 0; i < b.N; i++ { - m[int32(i%20)] = int32(i) - } -} - -func BenchmarkMapCreateSet(b *testing.B) { - for i := 0; i < b.N; i++ { - m := make(map[int32]int32) - m[int32(i%20)] = int32(i) - } -} - -func BenchmarkMapCreateSetString(b *testing.B) { - for i := 0; i < b.N; i++ { - m := make(map[string]int32) - m["5"] += 1 - } -} - -// shows that it might be kinda worth it to not use maps but slices for struct -// fields, but for small structs. -func BenchmarkSliceIterate10(b *testing.B) { - fs := []TestField{} - for i := 0; i < 10; i++ { - fs = append(fs, TestField{fmt.Sprintf("%v", i%10), int32(i)}) - } - for i := 0; i < b.N; i++ { - i10 := i % 10 - for j := 0; j < 10; j++ { - if fs[i10].Name == "5" { - fs[i10].Value += 1 - } - } - } - b.Log(fs) -} - -type SomeStruct struct { - Field1 int32 - Field2 int32 -} - -func (s SomeStruct) it() int32 { - return s.Field1 + s.Field2 -} - -// seems to inline. -func BenchmarkStructStack(b *testing.B) { - x := int32(0) - for i := 0; i < b.N; i++ { - s := SomeStruct{Field1: int32(i) % 20, Field2: 1} - x = s.it() - } - b.Log(x) -} - -// this doesn't work -func BenchmarkStructGC(b *testing.B) { - x := int32(0) - gen := func(i int) *SomeStruct { return &SomeStruct{Field1: int32(i) % 20} } - for i := 0; i < b.N; i++ { - s := gen(i) - x = s.Field1 - } - b.Log(x) -} - -type TestField struct { - Name string - Value int32 -} - -func BenchmarkTypeAssertionMethodCall(b *testing.B) { - // This uses no interface. - b.Run("Int32().Int32() (no interface)", func(b *testing.B) { - var v Int32 = Int32(1) - x := int32(0) - for i := 0; i < b.N; i++ { - x += v.Int32() - } - }) - // This calls a method on the interface. - // It's surprising that this is slower than switch concrete assert method - // by an order of magnitude when the alternative enables inlining. - // Perhaps go could do better by first grouping each interface into a - // single giant switch statement. - b.Run("BenchValue().Int32() (interface method)", func(b *testing.B) { - var v BenchValue = Int32(1) - x := int32(0) - for i := 0; i < b.N; i++ { - x += v.Int32() - } - }) - // This type-asserts to a concrete type and calls its method. - b.Run("v.(Int32).Int32() (concrete assert method)", func(b *testing.B) { - var v interface{} = Int32(1) - x := int32(0) - for i := 0; i < b.N; i++ { - x += v.(Int32).Int32() - } - }) - // This switch-type-asserts to a concrete type and calls its method. - // This actually ends up being the best choice, and is even faster than - // calling a method on an interface. - b.Run("case v.(Int32).Int32() (type switch concrete assert method)", func(b *testing.B) { - var v interface{} = Int32(1) - x := int32(0) - for i := 0; i < b.N; i++ { - switch v := v.(type) { - case Int32: - x += v.Int32() - case Int32a: - x += v.Int32() + 1 - case Int32b: - x += v.Int32() + 2 - case Int32c: - x += v.Int32() + 3 - case Int32d: - x += v.Int32() + 4 - case Int32e: - x += v.Int32() + 5 - case Int32f: - x += v.Int32() + 6 - case Int32g: - x += v.Int32() + 7 - case Int32h: - x += v.Int32() + 8 - case Int32i: - x += v.Int32() + 9 - case Int32j: - x += v.Int32() + 10 - case Int32k: - x += v.Int32() + 11 - default: - panic("should not happen") - } - } - }) - // This appears to run fast, not sure what optimization is happening, - // but maybe the initial interface setting is fine as the itable - // info is known statically. - b.Run("MyStruct{Value:Int32(i)} (struct interface field init)", func(b *testing.B) { - type MyStruct struct { - Value BenchValue - } - x := int32(0) - for i := 0; i < b.N; i++ { - s := MyStruct{Value: Int32(i)} - x += s.Value.(Int32).Int32() - } - }) - // This type-asserts to an interface type and calls its method. - // v.(BenchValue) is super slow, see https://billglover.me/2018/09/17/how-expensive-is-a-go-function-call/ - // or use `go tool compile -S test.go` for more info. - b.Run("v.(BenchValue).Int32() (interface assert method)", func(b *testing.B) { - var v interface{} = Int32(1) - x := int32(0) - for i := 0; i < b.N; i++ { - x += v.(BenchValue).Int32() - } - }) -} - -// there is a choice between type-switching on a slice of interfaces, or to -// iterate over a slice of super-structs. -func BenchmarkTypeSwitchOrCreate(b *testing.B) { - type Object interface{} - type StructA struct { - Inner Object - A int - B int - } - type StructB struct { - C int - D int - } - x := make([]Object, 1000) - y := make([]StructA, 1000) - for i := 0; i < 1000; i++ { - x[i] = StructA{StructB{0, 0}, 0, 0} - y[i] = StructA{StructB{0, 0}, 0, 0} - } - c := 0 - b.Run("type-switch", func(b *testing.B) { - for j := 0; j < b.N; j++ { - for i := 0; i < 1000; i++ { - switch xi := x[i].(type) { - case StructA: - switch xi.Inner.(type) { - case StructA: - panic("shouldn't happen") - case StructB: - c++ - } - case StructB: - panic("shouldn't happen") - } - } - } - b.Log(c) - }) - b.Run("super-struct", func(b *testing.B) { - for j := 0; j < b.N; j++ { - for i := 0; i < 1000; i++ { - switch y[i].Inner.(type) { - case StructA: - panic("shouldn't happen") - case StructB: - c++ - } - } - } - b.Log(c) - }) -} - -func BenchmarkReflectValueOf(b *testing.B) { - things := []interface{}{ - int(0), - string(""), - struct{}{}, - } - var rv reflect.Value - for _, thing := range things { - b.Run(reflect.TypeOf(thing).String(), func(b *testing.B) { - for i := 0; i < b.N; i++ { - rv = reflect.ValueOf(thing) - } - }) - } - b.Log(rv) -} - -func BenchmarkReflectAddInt64(b *testing.B) { - var rv reflect.Value = reflect.ValueOf(int64(1)) - var x int64 - for i := 0; i < b.N; i++ { - x += rv.Int() - } - b.Log(x) -} - -func BenchmarkNativeAddInt64(b *testing.B) { - var x int64 - for i := 0; i < b.N; i++ { - x += 1 - } - b.Log(x) -} - -func BenchmarkReflectTypeOf(b *testing.B) { - var x int64 - var rt reflect.Type - for i := 0; i < b.N; i++ { - rt = reflect.TypeOf(x) - } - b.Log(x, rt) -} - -func BenchmarkInterfaceEquality(b *testing.B) { - ctr := 0 - var x interface{} - var y interface{} - for i := 0; i < b.N; i++ { - if x == y { - ctr++ - } - } - b.Log(ctr) -} - -func BenchmarkPointerEquality(b *testing.B) { - ctr := 0 - a := 1 - c := 2 - x := &a - y := &c - for i := 0; i < b.N; i++ { - if x == y { - ctr++ - } - } - b.Log(ctr) -} - -func BenchmarkPointerDerefEquality(b *testing.B) { - ctr := 0 - a := 1 - c := 2 - x := &a - y := &c - for i := 0; i < b.N; i++ { - if *x == *y { - ctr++ - } - } - b.Log(ctr) -} - -func BenchmarkArrayEquality(b *testing.B) { - b.Run("ArrayEquality[1]", func(b *testing.B) { - ctr := 0 - x := [1]byte{0x00} - y := [1]byte{0x00} - for i := 0; i < b.N; i++ { - if x == y { - ctr++ - } - } - b.Log(ctr) - }) - b.Run("ArrayEquality[8]", func(b *testing.B) { - ctr := 0 - x := [8]byte{} - y := [8]byte{} - for i := 0; i < b.N; i++ { - if x == y { - ctr++ - } - } - b.Log(ctr) - }) - b.Run("ArrayEquality[16]", func(b *testing.B) { - ctr := 0 - x := [16]byte{} - y := [16]byte{} - for i := 0; i < b.N; i++ { - if x == y { - ctr++ - } - } - b.Log(ctr) - }) - b.Run("ArrayEquality[20]", func(b *testing.B) { - ctr := 0 - x := [20]byte{} - y := [20]byte{} - for i := 0; i < b.N; i++ { - if x == y { - ctr++ - } - } - b.Log(ctr) - }) - b.Run("ArrayEquality[32]", func(b *testing.B) { - ctr := 0 - x := [32]byte{} - y := [32]byte{} - for i := 0; i < b.N; i++ { - if x == y { - ctr++ - } - } - b.Log(ctr) - }) - b.Run("ArrayEquality[64]", func(b *testing.B) { - ctr := 0 - x := [64]byte{} - y := [64]byte{} - for i := 0; i < b.N; i++ { - if x == y { - ctr++ - } - } - b.Log(ctr) - }) - b.Run("ArrayEquality[256]", func(b *testing.B) { - ctr := 0 - x := [256]byte{} - y := [256]byte{} - for i := 0; i < b.N; i++ { - if x == y { - ctr++ - } - } - b.Log(ctr) - }) -} diff --git a/gnovm/pkg/gnolang/precompile_test.go b/gnovm/pkg/gnolang/precompile_test.go index e2cb5e92d86..cc24636e5ed 100644 --- a/gnovm/pkg/gnolang/precompile_test.go +++ b/gnovm/pkg/gnolang/precompile_test.go @@ -1,94 +1,286 @@ package gnolang import ( - "bytes" - "errors" - "go/format" - "go/parser" - "go/token" + "go/ast" + "strings" "testing" - "github.com/stretchr/testify/assert" + "github.com/jaekwon/testify/assert" + "github.com/jaekwon/testify/require" ) func TestPrecompile(t *testing.T) { t.Parallel() cases := []struct { - name string - source string - expectedOutput string - expectedPreprocessorError error + name string + tags string + source string + expectedOutput string + expectedImports []*ast.ImportSpec + expectedError string }{ { - name: "hello", - source: "package foo\nfunc hello() string { return \"world\"}", - expectedOutput: "package foo\nfunc hello() string { return \"world\"}", - }, { - name: "use-std", - source: "package foo\nimport \"std\"\nfunc hello() string { _ = std.Foo\nreturn \"world\"}", - expectedOutput: "package foo\nimport \"github.com/gnolang/gno/gnovm/stdlibs/stdshim\"\nfunc hello() string { _ = std.Foo\nreturn \"world\"}", - }, { - name: "use-realm", - source: "package foo\nimport \"gno.land/r/users\"\nfunc foo() { _ = users.Register}", - expectedOutput: "package foo\nimport \"github.com/gnolang/gno/examples/gno.land/r/users\"\nfunc foo() { _ = users.Register}", - }, { - name: "use-avl", - source: "package foo\nimport \"gno.land/p/demo/avl\"\nfunc foo() { _ = avl.Tree}", - expectedOutput: "package foo\nimport \"github.com/gnolang/gno/examples/gno.land/p/demo/avl\"\nfunc foo() { _ = avl.Tree}", - }, { - name: "use-named-std", - source: "package foo\nimport bar \"std\"\nfunc hello() string { _ = bar.Foo\nreturn \"world\"}", - expectedOutput: "package foo\nimport bar \"github.com/gnolang/gno/gnovm/stdlibs/stdshim\"\nfunc hello() string { _ = bar.Foo\nreturn \"world\"}", - }, { - name: "blacklisted-package", - source: "package foo\nimport \"reflect\"\nfunc foo() { _ = reflect.ValueOf}", - expectedPreprocessorError: errors.New(`import "reflect" is not in the whitelist`), - }, { - name: "whitelisted-package", - source: "package foo\nimport \"regexp\"\nfunc foo() { _ = regexp.MatchString}", - expectedOutput: "package foo\nimport \"regexp\"\nfunc foo() { _ = regexp.MatchString}", + name: "hello", + source: ` +package foo + +func hello() string { return "world"} +`, + expectedOutput: ` +// Code generated by github.com/gnolang/gno. DO NOT EDIT. + +package foo + +func hello() string { return "world" } +`, + }, + { + name: "hello with tags", + tags: "gno", + source: ` +package foo + +func hello() string { return "world"} +`, + expectedOutput: ` +// Code generated by github.com/gnolang/gno. DO NOT EDIT. + +//go:build gno + +package foo + +func hello() string { return "world" } +`, + }, + { + name: "use-std", + source: ` +package foo + +import "std" + +func hello() string { + _ = std.Foo + return "world" +} +`, + expectedOutput: ` +// Code generated by github.com/gnolang/gno. DO NOT EDIT. + +package foo + +import "github.com/gnolang/gno/gnovm/stdlibs/stdshim" + +func hello() string { + _ = std.Foo + return "world" +} +`, + expectedImports: []*ast.ImportSpec{ + { + Path: &ast.BasicLit{ + ValuePos: 21, + Kind: 9, + Value: `"github.com/gnolang/gno/gnovm/stdlibs/stdshim"`, + }, + EndPos: 26, + }, + }, + }, + { + name: "use-realm", + source: ` +package foo + +import "gno.land/r/users" + +func foo() { _ = users.Register} +`, + expectedOutput: ` +// Code generated by github.com/gnolang/gno. DO NOT EDIT. + +package foo + +import "github.com/gnolang/gno/examples/gno.land/r/users" + +func foo() { _ = users.Register } +`, + expectedImports: []*ast.ImportSpec{ + { + Path: &ast.BasicLit{ + ValuePos: 21, + Kind: 9, + Value: `"github.com/gnolang/gno/examples/gno.land/r/users"`, + }, + EndPos: 39, + }, + }, + }, + { + name: "use-avl", + source: ` +package foo + +import "gno.land/p/demo/avl" + +func foo() { _ = avl.Tree } +`, + expectedOutput: ` +// Code generated by github.com/gnolang/gno. DO NOT EDIT. + +package foo + +import "github.com/gnolang/gno/examples/gno.land/p/demo/avl" + +func foo() { _ = avl.Tree } +`, + expectedImports: []*ast.ImportSpec{ + { + Path: &ast.BasicLit{ + ValuePos: 21, + Kind: 9, + Value: `"github.com/gnolang/gno/examples/gno.land/p/demo/avl"`, + }, + EndPos: 42, + }, + }, + }, + { + name: "use-named-std", + source: ` +package foo + +import bar "std" + +func hello() string { + _ = bar.Foo + return "world" +} +`, + expectedOutput: ` +// Code generated by github.com/gnolang/gno. DO NOT EDIT. + +package foo + +import bar "github.com/gnolang/gno/gnovm/stdlibs/stdshim" + +func hello() string { + _ = bar.Foo + return "world" +} +`, + expectedImports: []*ast.ImportSpec{ + { + Name: &ast.Ident{ + NamePos: 21, + Name: "bar", + }, + Path: &ast.BasicLit{ + ValuePos: 25, + Kind: 9, + Value: `"github.com/gnolang/gno/gnovm/stdlibs/stdshim"`, + }, + EndPos: 30, + }, + }, + }, + { + name: "blacklisted-package", + source: ` +package foo + +import "reflect" + +func foo() { _ = reflect.ValueOf } +`, + expectedError: `import "reflect" is not in the whitelist`, + }, + { + name: "syntax-error", + source: ` +package foo + +invalid +`, + expectedError: `parse: foo.gno:3:1: expected declaration, found invalid`, + }, + { + name: "unknown-realm", + source: ` +package foo + +import "gno.land/p/demo/unknownxyz" +`, + expectedOutput: ` +// Code generated by github.com/gnolang/gno. DO NOT EDIT. + +package foo + +import "github.com/gnolang/gno/examples/gno.land/p/demo/unknownxyz" +`, + expectedImports: []*ast.ImportSpec{ + { + Path: &ast.BasicLit{ + ValuePos: 21, + Kind: 9, + Value: `"github.com/gnolang/gno/examples/gno.land/p/demo/unknownxyz"`, + }, + EndPos: 49, + }, + }, + }, + { + name: "whitelisted-package", + source: ` +package foo + +import "regexp" + +func foo() { _ = regexp.MatchString } +`, + expectedOutput: ` +// Code generated by github.com/gnolang/gno. DO NOT EDIT. + +package foo + +import "regexp" + +func foo() { _ = regexp.MatchString } +`, + expectedImports: []*ast.ImportSpec{ + { + Path: &ast.BasicLit{ + ValuePos: 21, + Kind: 9, + Value: `"regexp"`, + }, + }, + }, }, - // multiple files - // syntax error - // unknown realm? - // blacklist - // etc } for _, c := range cases { c := c // scopelint t.Run(c.name, func(t *testing.T) { t.Parallel() + // "\n" is added for better test case readability, now trim it + source := strings.TrimPrefix(c.source, "\n") + + res, err := Precompile(source, c.tags, "foo.gno") - // parse gno - fset := token.NewFileSet() - f, err := parser.ParseFile(fset, "foo.go", c.source, parser.ParseComments) - assert.NoError(t, err) - - // call preprocessor - transformed, err := precompileAST(fset, f, true) - if c.expectedPreprocessorError == nil { - assert.NoError(t, err) - } else { - assert.Equal(t, err, c.expectedPreprocessorError) + if c.expectedError != "" { + require.EqualError(t, err, c.expectedError) + return } - // generate go - var buf bytes.Buffer - err = format.Node(&buf, fset, transformed) - assert.NoError(t, err) - got := buf.Bytes() - - // check output - if c.expectedOutput != "" { - expect, err := format.Source([]byte(c.expectedOutput)) - if !bytes.Equal(expect, got) { - t.Logf("got:\n%s", got) - t.Logf("expect:\n%s", expect) - t.Fatal("mismatch") - } - assert.NoError(t, err) + if c.expectedError != "" { + require.EqualError(t, err, c.expectedError) + return } + require.NoError(t, err) + expectedOutput := strings.TrimPrefix(c.expectedOutput, "\n") + assert.Equal(t, res.Translated, expectedOutput, "wrong output") + assert.Equal(t, res.Imports, c.expectedImports, "wrong imports") }) } } diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index c86edb0e515..1d215e4d94b 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -978,11 +978,14 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { arg0)) } } - convertConst(store, last, arg0, ct) constConverted = true + case SliceKind: + if ct.Elem().Kind() == Uint8Kind { // bypass []byte("xxx") + n.SetAttribute(ATTR_TYPEOF_VALUE, ct) + return n, TRANS_CONTINUE + } } - // (const) untyped decimal -> float64. // (const) untyped bigint -> int. if !constConverted { diff --git a/gnovm/stdlibs/std/native.go b/gnovm/stdlibs/std/native.go index 8cdddd916ad..044badaa308 100644 --- a/gnovm/stdlibs/std/native.go +++ b/gnovm/stdlibs/std/native.go @@ -173,9 +173,7 @@ func DecodeBech32(addr crypto.Bech32Address) (prefix string, bytes [20]byte, ok if err != nil || len(bz) != 20 { return "", [20]byte{}, false } - // TODO: can be simplified when we switch to go1.20 in go mod to be a simple [20]byte(bz) - copy(bytes[:], bz) - return prefix, bytes, true + return prefix, [20]byte(bz), true } func typedString(s gno.StringValue) gno.TypedValue { diff --git a/gnovm/tests/files/byte_slice_issue1570.gno b/gnovm/tests/files/byte_slice_issue1570.gno new file mode 100644 index 00000000000..c1956f3d15d --- /dev/null +++ b/gnovm/tests/files/byte_slice_issue1570.gno @@ -0,0 +1,15 @@ +package main + +func main() { + for i := 0; i < 2; i++ { + l := []byte("lead") + if i == 0 { + l[0] = 'f' + } + println(string(l)) + } +} + +// Output: +// fead +// lead diff --git a/go.mod b/go.mod index ac56660dad1..784eb9e784f 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,9 @@ module github.com/gnolang/gno -go 1.20 +go 1.21 require ( + dario.cat/mergo v1.0.0 github.com/btcsuite/btcd/btcutil v1.1.3 github.com/cockroachdb/apd/v3 v3.2.1 github.com/cosmos/ledger-cosmos-go v0.13.3 @@ -32,10 +33,9 @@ require ( github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c go.etcd.io/bbolt v1.3.8 go.uber.org/multierr v1.10.0 - go.uber.org/zap v1.24.0 - go.uber.org/zap/exp v0.1.0 + go.uber.org/zap v1.26.0 + go.uber.org/zap/exp v0.2.0 golang.org/x/crypto v0.18.0 - golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 golang.org/x/mod v0.14.0 golang.org/x/net v0.20.0 golang.org/x/term v0.16.0 @@ -44,15 +44,6 @@ require ( gopkg.in/yaml.v3 v3.0.1 ) -require dario.cat/mergo v1.0.0 - -require ( - github.com/zondax/hid v0.9.2 // indirect - github.com/zondax/ledger-go v0.14.3 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20231009173412-8bfb1ae86b6c // indirect - google.golang.org/grpc v1.58.3 // indirect -) - require ( github.com/btcsuite/btcd/btcec/v2 v2.3.2 github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 // indirect @@ -72,14 +63,16 @@ require ( github.com/gorilla/securecookie v1.1.1 // indirect github.com/gorilla/sessions v1.2.1 // indirect github.com/klauspost/compress v1.12.3 // indirect - github.com/kr/text v0.2.0 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/nxadm/tail v1.4.11 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/rivo/uniseg v0.4.3 // indirect + github.com/zondax/hid v0.9.2 // indirect + github.com/zondax/ledger-go v0.14.3 // indirect go.opencensus.io v0.22.5 // indirect - go.uber.org/atomic v1.10.0 // indirect golang.org/x/sys v0.16.0 // indirect golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231009173412-8bfb1ae86b6c // indirect + google.golang.org/grpc v1.58.3 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect ) diff --git a/go.sum b/go.sum index cdde46147e8..5b96b00b117 100644 --- a/go.sum +++ b/go.sum @@ -6,7 +6,6 @@ github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= 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= @@ -45,13 +44,13 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee github.com/cosmos/ledger-cosmos-go v0.13.3 h1:7ehuBGuyIytsXbd4MP43mLeoN2LTOEnk5nvue4rK+yM= github.com/cosmos/ledger-cosmos-go v0.13.3/go.mod h1:HENcEP+VtahZFw38HZ3+LS3Iv5XV6svsnkk9vdJtLr8= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= @@ -114,6 +113,7 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 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/gorilla/csrf v1.7.0/go.mod h1:+a/4tCmqhG6/w4oafeAZ9pEa3/NZOWYVbD9fV0FwIQA= @@ -151,6 +151,7 @@ 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/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/linxGnu/grocksdb v1.8.11 h1:BGol9e5gB1BrsTvOxloC88pe70TCqgrfLNwkyWW0kD8= @@ -225,15 +226,14 @@ go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA= go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= go.opencensus.io v0.22.5 h1:dntmOdLpSpHlVqbW5Eay97DelsZHe+55D+xC6i0dDS0= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= -go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= +go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= +go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= -go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= -go.uber.org/zap/exp v0.1.0 h1:Ol9zQNvAEAgFHSBiR5LlwS9Xq8u5QF+7HBwNHUB8rcI= -go.uber.org/zap/exp v0.1.0/go.mod h1:z/0T3As39ttolxZGOsvk1OEvQfwwfTZpmV9YTp+VAkc= +go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +go.uber.org/zap/exp v0.2.0 h1:FtGenNNeCATRB3CmB/yEUnjEFeJWpB/pMcy7e2bKPYs= +go.uber.org/zap/exp v0.2.0/go.mod h1:t0gqAIdh1MfKv9EwN/dLwfZnJxe9ITAZN78HEWPFWDQ= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -243,8 +243,6 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 h1:hNQpMuAJe5CtcUqCXaWga3FHu+kQvCqcsoVaQgSV60o= -golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -358,6 +356,7 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/misc/devdeps/go.mod b/misc/devdeps/go.mod index bd4e19f6221..3a1f87c0664 100644 --- a/misc/devdeps/go.mod +++ b/misc/devdeps/go.mod @@ -1,6 +1,6 @@ module github.com/gnolang/gno/misc/devdeps -go 1.20 +go 1.21 require ( github.com/golangci/golangci-lint v1.54.2 // sync with github action @@ -171,9 +171,8 @@ require ( github.com/yuin/goldmark v1.4.13 // indirect gitlab.com/bosi/decorder v0.4.0 // indirect go.tmz.dev/musttag v0.7.2 // indirect - go.uber.org/atomic v1.10.0 // indirect - go.uber.org/multierr v1.8.0 // indirect - go.uber.org/zap v1.24.0 // indirect + go.uber.org/multierr v1.10.0 // indirect + go.uber.org/zap v1.26.0 // indirect golang.org/x/exp v0.0.0-20230510235704-dd950f8aeaea // indirect golang.org/x/exp/typeparams v0.0.0-20230307190834-24139beb5833 // indirect golang.org/x/mod v0.12.0 // indirect diff --git a/misc/devdeps/go.sum b/misc/devdeps/go.sum index 5cc9c75e475..9146980fe7d 100644 --- a/misc/devdeps/go.sum +++ b/misc/devdeps/go.sum @@ -75,7 +75,6 @@ github.com/ashanbrown/forbidigo v1.6.0 h1:D3aewfM37Yb3pxHujIPSpTf6oQk9sc9WZi8ger github.com/ashanbrown/forbidigo v1.6.0/go.mod h1:Y8j9jy9ZYAEHXdu723cUlraTqbzjKF1MUyfOKL+AjcU= github.com/ashanbrown/makezero v1.1.1 h1:iCQ87C0V0vSyO+M9E/FZYbu65auqH0lnsOkf5FcB28s= github.com/ashanbrown/makezero v1.1.1/go.mod h1:i1bJLCRSCHOcOa9Y6MyF2FTfMZMFdHvxKHxgO5Z1axI= -github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -140,6 +139,7 @@ github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4 github.com/firefart/nonamedreturns v1.0.4 h1:abzI1p7mAEPYuR4A+VLKn4eNDOycjYo2phmY9sfv40Y= github.com/firefart/nonamedreturns v1.0.4/go.mod h1:TDhe/tjI1BXo48CmYbUduTV7BdIga8MAO/xbKdcVsGI= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= +github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= @@ -156,8 +156,10 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/go-toolsmith/astcast v1.1.0 h1:+JN9xZV1A+Re+95pgnMgDboWNVnIMMQXwfBwLRPgSC8= github.com/go-toolsmith/astcast v1.1.0/go.mod h1:qdcuFWeGGS2xX5bLM/c3U9lewg7+Zu4mr+xPwZIB4ZU= github.com/go-toolsmith/astcopy v1.1.0 h1:YGwBN0WM+ekI/6SS6+52zLDEf8Yvp3n2seZITCUBt5s= @@ -170,6 +172,7 @@ github.com/go-toolsmith/astfmt v1.1.0/go.mod h1:OrcLlRwu0CuiIBp/8b5PYF9ktGVZUjlN github.com/go-toolsmith/astp v1.1.0 h1:dXPuCl6u2llURjdPLLDxJeZInAeZ0/eZwFJmqZMnpQA= github.com/go-toolsmith/astp v1.1.0/go.mod h1:0T1xFGz9hicKs8Z5MfAqSUitoUYS30pDMsRVIDHs8CA= github.com/go-toolsmith/pkgload v1.2.2 h1:0CtmHq/02QhxcF7E9N5LIFcYFsMR5rdovfqTtRKkgIk= +github.com/go-toolsmith/pkgload v1.2.2/go.mod h1:R2hxLNRKuAsiXCo2i5J6ZQPhnPMOVtU+f0arbFPWCus= github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= github.com/go-toolsmith/strparse v1.1.0 h1:GAioeZUK9TGxnLS+qfdqNbA4z0SSm5zVNtCQiyP2Bvw= github.com/go-toolsmith/strparse v1.1.0/go.mod h1:7ksGy58fsaQkGQlY8WVoBFNyEPMGuJin1rfoPS4lBSQ= @@ -262,6 +265,7 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe 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-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= @@ -280,6 +284,7 @@ github.com/gostaticanalysis/nilerr v0.1.1 h1:ThE+hJP0fEp4zWLkWHWcRyI2Od0p7DlgYG3 github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW0HU0GPE3+5PWN4A= github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= github.com/gostaticanalysis/testutil v0.4.0 h1:nhdCmubdmDF6VEatUNjgUZBJKWRqugoISdUv3PPQgHY= +github.com/gostaticanalysis/testutil v0.4.0/go.mod h1:bLIoPefWXrRi/ssLFWX1dx7Repi5x3CuviD3dgAZaBU= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= @@ -328,6 +333,7 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -393,7 +399,9 @@ github.com/nunnatsa/ginkgolinter v0.13.5/go.mod h1:OBHy4536xtuX3102NM63XRtOyxqZO github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU= +github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= github.com/otiai10/copy v1.2.0 h1:HvG945u96iNadPoG2/Ja2+AUJeW5YuFQMixq9yirC+k= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= @@ -412,7 +420,6 @@ github.com/pkg/diff v0.0.0-20200914180035-5b29258ca4f7/go.mod h1:zO8QMzTeZd5cpnI 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/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -452,6 +459,7 @@ github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryancurrah/gomodguard v1.3.0 h1:q15RT/pd6UggBXVBuLps8BXRvl5GPBcwVA7BJHMLuTw= github.com/ryancurrah/gomodguard v1.3.0/go.mod h1:ggBxb3luypPEzqVtq33ee7YSN35V28XeGnid8dnni50= @@ -565,6 +573,7 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t gitlab.com/bosi/decorder v0.4.0 h1:HWuxAhSxIvsITcXeP+iIRg9d1cVfvVkmlF7M68GaoDY= gitlab.com/bosi/decorder v0.4.0/go.mod h1:xarnteyUoJiOTEldDysquWKTVDCKo2TOIOIibSuWqOg= go-simpler.org/assert v0.6.0 h1:QxSrXa4oRuo/1eHMXSBFHKvJIpWABayzKldqZyugG7E= +go-simpler.org/assert v0.6.0/go.mod h1:74Eqh5eI6vCK6Y5l3PI8ZYFXG4Sa+tkr70OIPJAUr28= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -574,15 +583,14 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.tmz.dev/musttag v0.7.2 h1:1J6S9ipDbalBSODNT5jCep8dhZyMr4ttnjQagmGYR5s= go.tmz.dev/musttag v0.7.2/go.mod h1:m6q5NiiSKMnQYokefa2xGoyoXnrswCbJ0AWYzf4Zs28= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= -go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= +go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= +go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= -go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= -go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= -go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= -go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= +go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -683,6 +691,7 @@ golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= 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= diff --git a/misc/docusaurus/docusaurus.config.js b/misc/docusaurus/docusaurus.config.js index 5fdbbacf98c..6daec1be821 100644 --- a/misc/docusaurus/docusaurus.config.js +++ b/misc/docusaurus/docusaurus.config.js @@ -28,7 +28,7 @@ const config = { src: "https://sa.gno.services/latest.js", async: true, defer: true, - } + }, ], presets: [ @@ -40,6 +40,8 @@ const config = { path: "../../docs", routeBasePath: "/", sidebarPath: require.resolve("./sidebars.js"), + showLastUpdateTime: true, + editUrl: ({ docPath }) => `https://github.com/gnolang/gno/edit/master/docs/${docPath}`, }, blog: false, theme: { @@ -61,12 +63,28 @@ const config = { srcDark: "img/gnoland_light.svg", }, items: [ + { + position: "right", + label: "Back to Gno.Land", + to: "https://gno.land", + className: "gno-header__copy", + }, { type: "docSidebar", sidebarId: "tutorialSidebar", position: "left", label: "Docs", }, + { + position: "left", + label: "Playground", + to: "https://play.gno.land", + }, + { + position: "left", + label: "Blog", + to: "https://test3.gno.land/r/gnoland/blog", + }, { href: "https://github.com/gnolang/gno", html: ` diff --git a/misc/docusaurus/sidebars.js b/misc/docusaurus/sidebars.js index 021c58dd90b..b6317cbbae0 100644 --- a/misc/docusaurus/sidebars.js +++ b/misc/docusaurus/sidebars.js @@ -52,10 +52,11 @@ const sidebars = { 'concepts/standard-library/gnopher-hole-stdlib', ] }, - 'concepts/tendermint2', 'concepts/gnovm', - 'concepts/proof-of-contribution', 'concepts/gno-language', + 'concepts/effective-gno', + 'concepts/proof-of-contribution', + 'concepts/tendermint2', 'concepts/gno-modules', 'concepts/gno-test', 'concepts/from-go-to-gno', @@ -70,7 +71,6 @@ const sidebars = { 'gno-tooling/cli/gno-tooling-gnodev', 'gno-tooling/cli/gno-tooling-gnoland', 'gno-tooling/cli/gno-tooling-gnofaucet', - 'gno-tooling/cli/gno-tooling-tm2txsync', ] }, { diff --git a/misc/docusaurus/src/css/custom.css b/misc/docusaurus/src/css/custom.css index 9955c1cae78..a0512068943 100644 --- a/misc/docusaurus/src/css/custom.css +++ b/misc/docusaurus/src/css/custom.css @@ -118,7 +118,8 @@ body nav[class*="navbarHidden"] { } } -.theme-doc-markdown { +.theme-doc-markdown, +.theme-doc-footer { max-width: var(--content-max-w, 700px); } @@ -331,3 +332,12 @@ a.footer__link-item > svg { .gno-footer__copy { font-size: 0.8em; } + +.gno-header__copy { + font-size: 1em; +} +@media (min-width: 997px) { + .gno-header__copy { + font-size: 0.8em; + } +} diff --git a/misc/genstd/genstd.go b/misc/genstd/genstd.go index 318a63e5ee8..9d0c21c5229 100644 --- a/misc/genstd/genstd.go +++ b/misc/genstd/genstd.go @@ -106,7 +106,9 @@ func walkStdlibs(stdlibsPath string) ([]*pkgData, error) { // skip non-source and test files. ext := filepath.Ext(fpath) noExt := fpath[:len(fpath)-len(ext)] - if (ext != ".go" && ext != ".gno") || strings.HasSuffix(noExt, "_test") { + if (ext != ".go" && ext != ".gno") || + strings.HasSuffix(noExt, "_test") || + strings.HasSuffix(fpath, ".gen.go") { return nil } diff --git a/misc/loop/go.mod b/misc/loop/go.mod index 6e81efe3df8..1f1dedd6074 100644 --- a/misc/loop/go.mod +++ b/misc/loop/go.mod @@ -1,6 +1,6 @@ module loop -go 1.20 +go 1.21 require ( github.com/gnolang/gno v0.0.0-20231112174927-b1a53c018ea4 @@ -47,7 +47,6 @@ require ( go.uber.org/zap v1.26.0 // indirect go.uber.org/zap/exp v0.2.0 // indirect golang.org/x/crypto v0.18.0 // indirect - golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 // indirect golang.org/x/mod v0.14.0 // indirect golang.org/x/net v0.20.0 // indirect golang.org/x/sys v0.16.0 // indirect diff --git a/misc/loop/go.sum b/misc/loop/go.sum index ed31b7ca9f7..4bd5ab654a1 100644 --- a/misc/loop/go.sum +++ b/misc/loop/go.sum @@ -21,6 +21,7 @@ github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9E github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 h1:KdUfX2zKommPRa+PD0sWZUyXe9w277ABlgELO7H04IM= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/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= @@ -42,6 +43,7 @@ github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/cosmos/ledger-cosmos-go v0.13.3 h1:7ehuBGuyIytsXbd4MP43mLeoN2LTOEnk5nvue4rK+yM= +github.com/cosmos/ledger-cosmos-go v0.13.3/go.mod h1:HENcEP+VtahZFw38HZ3+LS3Iv5XV6svsnkk9vdJtLr8= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/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= @@ -49,6 +51,7 @@ 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/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= @@ -62,9 +65,13 @@ github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUn github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c h1:8ISkoahWXwZR41ois5lSJBSVw4D0OV19Ht/JSTzvSv0= +github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= +github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk= +github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= @@ -106,6 +113,7 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ 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/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= @@ -125,10 +133,13 @@ github.com/klauspost/compress v1.12.3 h1:G5AfA94pHPysR56qqrkO2pxEexdDzrpFJ6yt/Vq github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 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/linxGnu/grocksdb v1.8.11 h1:BGol9e5gB1BrsTvOxloC88pe70TCqgrfLNwkyWW0kD8= @@ -138,6 +149,7 @@ github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= +github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= @@ -158,6 +170,7 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE 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/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= @@ -185,12 +198,15 @@ github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1: github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= +github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw= +github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI= go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA= go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= go.opencensus.io v0.22.5 h1:dntmOdLpSpHlVqbW5Eay97DelsZHe+55D+xC6i0dDS0= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= +go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= @@ -205,8 +221,6 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 h1:hNQpMuAJe5CtcUqCXaWga3FHu+kQvCqcsoVaQgSV60o= -golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -257,6 +271,7 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 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/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -294,6 +309,7 @@ google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHh gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= @@ -302,6 +318,7 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/tm2/pkg/bft/abci/example/kvstore/persistent_kvstore.go b/tm2/pkg/bft/abci/example/kvstore/persistent_kvstore.go index 5042fcf9313..0e31f83b3c0 100644 --- a/tm2/pkg/bft/abci/example/kvstore/persistent_kvstore.go +++ b/tm2/pkg/bft/abci/example/kvstore/persistent_kvstore.go @@ -3,11 +3,10 @@ package kvstore import ( "encoding/base64" "fmt" + "log/slog" "strconv" "strings" - "golang.org/x/exp/slog" - "github.com/gnolang/gno/tm2/pkg/amino" "github.com/gnolang/gno/tm2/pkg/bft/abci/example/errors" abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" diff --git a/tm2/pkg/bft/blockchain/pool.go b/tm2/pkg/bft/blockchain/pool.go index a3a24d265a8..5a82eb4d1d6 100644 --- a/tm2/pkg/bft/blockchain/pool.go +++ b/tm2/pkg/bft/blockchain/pool.go @@ -3,13 +3,12 @@ package blockchain import ( "errors" "fmt" + "log/slog" "math" "sync" "sync/atomic" "time" - "golang.org/x/exp/slog" - "github.com/gnolang/gno/tm2/pkg/bft/types" "github.com/gnolang/gno/tm2/pkg/flow" "github.com/gnolang/gno/tm2/pkg/log" diff --git a/tm2/pkg/bft/blockchain/reactor.go b/tm2/pkg/bft/blockchain/reactor.go index bf5f7ea71b3..09e1225b717 100644 --- a/tm2/pkg/bft/blockchain/reactor.go +++ b/tm2/pkg/bft/blockchain/reactor.go @@ -3,11 +3,10 @@ package blockchain import ( "errors" "fmt" + "log/slog" "reflect" "time" - "golang.org/x/exp/slog" - "github.com/gnolang/gno/tm2/pkg/amino" sm "github.com/gnolang/gno/tm2/pkg/bft/state" "github.com/gnolang/gno/tm2/pkg/bft/store" diff --git a/tm2/pkg/bft/blockchain/reactor_test.go b/tm2/pkg/bft/blockchain/reactor_test.go index 982c29033fa..6101956051d 100644 --- a/tm2/pkg/bft/blockchain/reactor_test.go +++ b/tm2/pkg/bft/blockchain/reactor_test.go @@ -1,13 +1,12 @@ package blockchain import ( + "log/slog" "os" "sort" "testing" "time" - "golang.org/x/exp/slog" - "github.com/stretchr/testify/assert" abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" diff --git a/tm2/pkg/bft/consensus/common_test.go b/tm2/pkg/bft/consensus/common_test.go index 4a0a4eebf03..c95c104ce3a 100644 --- a/tm2/pkg/bft/consensus/common_test.go +++ b/tm2/pkg/bft/consensus/common_test.go @@ -3,6 +3,7 @@ package consensus import ( "bytes" "fmt" + "log/slog" "os" "path" "path/filepath" @@ -11,8 +12,6 @@ import ( "testing" "time" - "golang.org/x/exp/slog" - abcicli "github.com/gnolang/gno/tm2/pkg/bft/abci/client" "github.com/gnolang/gno/tm2/pkg/bft/abci/example/counter" "github.com/gnolang/gno/tm2/pkg/bft/abci/example/kvstore" diff --git a/tm2/pkg/bft/consensus/reactor.go b/tm2/pkg/bft/consensus/reactor.go index 27ead3f08f0..ed7a6ae6547 100644 --- a/tm2/pkg/bft/consensus/reactor.go +++ b/tm2/pkg/bft/consensus/reactor.go @@ -2,12 +2,11 @@ package consensus import ( "fmt" + "log/slog" "reflect" "sync" "time" - "golang.org/x/exp/slog" - "github.com/gnolang/gno/tm2/pkg/amino" cstypes "github.com/gnolang/gno/tm2/pkg/bft/consensus/types" sm "github.com/gnolang/gno/tm2/pkg/bft/state" diff --git a/tm2/pkg/bft/consensus/reactor_test.go b/tm2/pkg/bft/consensus/reactor_test.go index 96fd2ed987b..42f944b7481 100644 --- a/tm2/pkg/bft/consensus/reactor_test.go +++ b/tm2/pkg/bft/consensus/reactor_test.go @@ -2,12 +2,11 @@ package consensus import ( "fmt" + "log/slog" "sync" "testing" "time" - "golang.org/x/exp/slog" - "github.com/stretchr/testify/assert" "github.com/gnolang/gno/tm2/pkg/amino" diff --git a/tm2/pkg/bft/consensus/replay.go b/tm2/pkg/bft/consensus/replay.go index 103cf67f512..5fe24229007 100644 --- a/tm2/pkg/bft/consensus/replay.go +++ b/tm2/pkg/bft/consensus/replay.go @@ -5,11 +5,10 @@ import ( "errors" "fmt" "io" + "log/slog" "reflect" "time" - "golang.org/x/exp/slog" - abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" cstypes "github.com/gnolang/gno/tm2/pkg/bft/consensus/types" "github.com/gnolang/gno/tm2/pkg/bft/mempool/mock" diff --git a/tm2/pkg/bft/consensus/replay_test.go b/tm2/pkg/bft/consensus/replay_test.go index 981e72d6ca3..8a600dc68c4 100644 --- a/tm2/pkg/bft/consensus/replay_test.go +++ b/tm2/pkg/bft/consensus/replay_test.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "io" + "log/slog" "os" "path/filepath" "runtime" @@ -13,8 +14,6 @@ import ( "testing" "time" - "golang.org/x/exp/slog" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tm2/pkg/bft/consensus/state.go b/tm2/pkg/bft/consensus/state.go index c5486bb38a4..e6b4ace8d2f 100644 --- a/tm2/pkg/bft/consensus/state.go +++ b/tm2/pkg/bft/consensus/state.go @@ -4,13 +4,12 @@ import ( "bytes" goerrors "errors" "fmt" + "log/slog" "reflect" "runtime/debug" "sync" "time" - "golang.org/x/exp/slog" - "github.com/gnolang/gno/tm2/pkg/amino" cnscfg "github.com/gnolang/gno/tm2/pkg/bft/consensus/config" cstypes "github.com/gnolang/gno/tm2/pkg/bft/consensus/types" diff --git a/tm2/pkg/bft/consensus/ticker.go b/tm2/pkg/bft/consensus/ticker.go index 4e664304c92..8448e014260 100644 --- a/tm2/pkg/bft/consensus/ticker.go +++ b/tm2/pkg/bft/consensus/ticker.go @@ -1,10 +1,9 @@ package consensus import ( + "log/slog" "time" - "golang.org/x/exp/slog" - "github.com/gnolang/gno/tm2/pkg/service" ) diff --git a/tm2/pkg/bft/consensus/wal_generator.go b/tm2/pkg/bft/consensus/wal_generator.go index 8a737452425..fd322f221fe 100644 --- a/tm2/pkg/bft/consensus/wal_generator.go +++ b/tm2/pkg/bft/consensus/wal_generator.go @@ -5,12 +5,11 @@ import ( "bytes" "fmt" "io" + "log/slog" "path/filepath" "testing" "time" - "golang.org/x/exp/slog" - "github.com/gnolang/gno/tm2/pkg/bft/abci/example/kvstore" cfg "github.com/gnolang/gno/tm2/pkg/bft/config" "github.com/gnolang/gno/tm2/pkg/bft/mempool/mock" diff --git a/tm2/pkg/bft/mempool/clist_mempool.go b/tm2/pkg/bft/mempool/clist_mempool.go index da0a2c22c11..e7a356d1ad3 100644 --- a/tm2/pkg/bft/mempool/clist_mempool.go +++ b/tm2/pkg/bft/mempool/clist_mempool.go @@ -5,12 +5,11 @@ import ( "container/list" "crypto/sha256" "fmt" + "log/slog" "sync" "sync/atomic" "time" - "golang.org/x/exp/slog" - auto "github.com/gnolang/gno/tm2/pkg/autofile" abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" cfg "github.com/gnolang/gno/tm2/pkg/bft/mempool/config" diff --git a/tm2/pkg/bft/mempool/reactor.go b/tm2/pkg/bft/mempool/reactor.go index 7147c11169b..3ef85b80a21 100644 --- a/tm2/pkg/bft/mempool/reactor.go +++ b/tm2/pkg/bft/mempool/reactor.go @@ -2,13 +2,12 @@ package mempool import ( "fmt" + "log/slog" "math" "reflect" "sync" "time" - "golang.org/x/exp/slog" - "github.com/gnolang/gno/tm2/pkg/amino" cfg "github.com/gnolang/gno/tm2/pkg/bft/mempool/config" "github.com/gnolang/gno/tm2/pkg/bft/types" diff --git a/tm2/pkg/bft/node/node.go b/tm2/pkg/bft/node/node.go index a6c67fa2485..a588f860f63 100644 --- a/tm2/pkg/bft/node/node.go +++ b/tm2/pkg/bft/node/node.go @@ -5,14 +5,13 @@ package node import ( "fmt" + "log/slog" "net" "net/http" - _ "net/http/pprof" //nolint:gosec "strings" + "sync" "time" - "golang.org/x/exp/slog" - "github.com/gnolang/gno/tm2/pkg/bft/state/eventstore/file" "github.com/rs/cors" @@ -168,6 +167,7 @@ type Node struct { rpcListeners []net.Listener // rpc servers txEventStore eventstore.TxEventStore eventStoreService *eventstore.Service + firstBlockSignal <-chan struct{} } func initDBs(config *cfg.Config, dbProvider DBProvider) (blockStore *store.BlockStore, stateDB dbm.DB, err error) { @@ -439,6 +439,20 @@ func NewNode(config *cfg.Config, // but before it indexed the txs, or, endblocker panicked) evsw := events.NewEventSwitch() + // Signal readiness when receiving the first block. + const readinessListenerID = "first_block_listener" + + cFirstBlock := make(chan struct{}) + var once sync.Once + evsw.AddListener(readinessListenerID, func(ev events.Event) { + if _, ok := ev.(types.EventNewBlock); ok { + once.Do(func() { + close(cFirstBlock) + evsw.RemoveListener(readinessListenerID) + }) + } + }) + // Transaction event storing eventStoreService, txEventStore, err := createAndStartEventStoreService(config, evsw, logger) if err != nil { @@ -554,6 +568,7 @@ func NewNode(config *cfg.Config, proxyApp: proxyApp, txEventStore: txEventStore, eventStoreService: eventStoreService, + firstBlockSignal: cFirstBlock, } node.BaseService = *service.NewBaseService(logger, "Node", node) @@ -653,6 +668,11 @@ func (n *Node) OnStop() { } } +// Ready signals that the node is ready by returning a blocking channel. This channel is closed when the node receives its first block. +func (n *Node) Ready() <-chan struct{} { + return n.firstBlockSignal +} + // ConfigureRPC sets all variables in rpccore so they will serve // rpc calls from this node func (n *Node) ConfigureRPC() { diff --git a/tm2/pkg/bft/node/node_test.go b/tm2/pkg/bft/node/node_test.go index d182b7fb0d5..3057a41b5f3 100644 --- a/tm2/pkg/bft/node/node_test.go +++ b/tm2/pkg/bft/node/node_test.go @@ -108,6 +108,39 @@ func TestNodeDelayedStart(t *testing.T) { assert.Equal(t, true, startTime.After(n.GenesisDoc().GenesisTime)) } +func TestNodeReady(t *testing.T) { + config := cfg.ResetTestRoot("node_node_test") + defer os.RemoveAll(config.RootDir) + + // Create & start node + n, err := DefaultNewNode(config, log.NewTestingLogger(t)) + require.NoError(t, err) + + // Assert that blockstore has zero block before waiting for the first block + require.Equal(t, int64(0), n.BlockStore().Height()) + + // Assert that first block signal is not alreay received by calling Ready + select { + case <-n.Ready(): + require.FailNow(t, "first block signal should not be close before starting the node") + default: // ok + } + + err = n.Start() + require.NoError(t, err) + defer n.Stop() + + // Wait until the node is ready or timeout + select { + case <-time.After(time.Second): + require.FailNow(t, "timeout while waiting for first block signal") + case <-n.Ready(): // ready + } + + // Check that blockstore have at last one block + require.GreaterOrEqual(t, n.BlockStore().Height(), int64(1)) +} + func TestNodeSetAppVersion(t *testing.T) { config := cfg.ResetTestRoot("node_app_version_test") defer os.RemoveAll(config.RootDir) diff --git a/tm2/pkg/bft/privval/signer_dialer_endpoint.go b/tm2/pkg/bft/privval/signer_dialer_endpoint.go index 275c406919f..fa4f5891fc1 100644 --- a/tm2/pkg/bft/privval/signer_dialer_endpoint.go +++ b/tm2/pkg/bft/privval/signer_dialer_endpoint.go @@ -1,10 +1,9 @@ package privval import ( + "log/slog" "time" - "golang.org/x/exp/slog" - "github.com/gnolang/gno/tm2/pkg/service" ) diff --git a/tm2/pkg/bft/privval/signer_listener_endpoint.go b/tm2/pkg/bft/privval/signer_listener_endpoint.go index 7ce42534290..df28d7d3722 100644 --- a/tm2/pkg/bft/privval/signer_listener_endpoint.go +++ b/tm2/pkg/bft/privval/signer_listener_endpoint.go @@ -2,12 +2,11 @@ package privval import ( "fmt" + "log/slog" "net" "sync" "time" - "golang.org/x/exp/slog" - "github.com/gnolang/gno/tm2/pkg/service" ) diff --git a/tm2/pkg/bft/privval/signer_listener_endpoint_test.go b/tm2/pkg/bft/privval/signer_listener_endpoint_test.go index bb026cd9acc..fd9ffb8a245 100644 --- a/tm2/pkg/bft/privval/signer_listener_endpoint_test.go +++ b/tm2/pkg/bft/privval/signer_listener_endpoint_test.go @@ -1,12 +1,11 @@ package privval import ( + "log/slog" "net" "testing" "time" - "golang.org/x/exp/slog" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tm2/pkg/bft/privval/utils.go b/tm2/pkg/bft/privval/utils.go index 904474ba4f7..c759d9dde9d 100644 --- a/tm2/pkg/bft/privval/utils.go +++ b/tm2/pkg/bft/privval/utils.go @@ -2,10 +2,9 @@ package privval import ( "fmt" + "log/slog" "net" - "golang.org/x/exp/slog" - "github.com/gnolang/gno/tm2/pkg/crypto/ed25519" "github.com/gnolang/gno/tm2/pkg/errors" osm "github.com/gnolang/gno/tm2/pkg/os" diff --git a/tm2/pkg/bft/rpc/client/localclient.go b/tm2/pkg/bft/rpc/client/localclient.go index 15e2b916c71..cdd2cd31bb1 100644 --- a/tm2/pkg/bft/rpc/client/localclient.go +++ b/tm2/pkg/bft/rpc/client/localclient.go @@ -1,7 +1,7 @@ package client import ( - "golang.org/x/exp/slog" + "log/slog" nm "github.com/gnolang/gno/tm2/pkg/bft/node" "github.com/gnolang/gno/tm2/pkg/bft/rpc/core" diff --git a/tm2/pkg/bft/rpc/core/pipe.go b/tm2/pkg/bft/rpc/core/pipe.go index 977dfd54e1f..01d558f0b2b 100644 --- a/tm2/pkg/bft/rpc/core/pipe.go +++ b/tm2/pkg/bft/rpc/core/pipe.go @@ -2,8 +2,7 @@ package core import ( "fmt" - - "golang.org/x/exp/slog" + "log/slog" "github.com/gnolang/gno/tm2/pkg/bft/consensus" cnscfg "github.com/gnolang/gno/tm2/pkg/bft/consensus/config" diff --git a/tm2/pkg/bft/rpc/lib/server/handlers.go b/tm2/pkg/bft/rpc/lib/server/handlers.go index 4cfade23711..1957d9a9fc0 100644 --- a/tm2/pkg/bft/rpc/lib/server/handlers.go +++ b/tm2/pkg/bft/rpc/lib/server/handlers.go @@ -7,6 +7,7 @@ import ( "encoding/json" "fmt" "io" + "log/slog" "net/http" "reflect" "regexp" @@ -15,8 +16,6 @@ import ( "strings" "time" - "golang.org/x/exp/slog" - "github.com/gorilla/websocket" "github.com/gnolang/gno/tm2/pkg/amino" @@ -293,7 +292,7 @@ func makeHTTPHandler(rpcFunc *RPCFunc, logger *slog.Logger) func(http.ResponseWr } } -// Covert an http query to a list of properly typed values. +// Convert an http query to a list of properly typed values. // To be properly decoded the arg must be a concrete type from tendermint (if its an interface). func httpParamsToArgs(rpcFunc *RPCFunc, r *http.Request) ([]reflect.Value, error) { // skip types.Context diff --git a/tm2/pkg/bft/rpc/lib/server/http_server.go b/tm2/pkg/bft/rpc/lib/server/http_server.go index 102a8203ac5..23ac851512f 100644 --- a/tm2/pkg/bft/rpc/lib/server/http_server.go +++ b/tm2/pkg/bft/rpc/lib/server/http_server.go @@ -5,14 +5,13 @@ import ( "bufio" "encoding/json" "fmt" + "log/slog" "net" "net/http" "runtime/debug" "strings" "time" - "golang.org/x/exp/slog" - "golang.org/x/net/netutil" types "github.com/gnolang/gno/tm2/pkg/bft/rpc/lib/types" diff --git a/tm2/pkg/bft/state/execution.go b/tm2/pkg/bft/state/execution.go index d831fc3678e..00660646b6e 100644 --- a/tm2/pkg/bft/state/execution.go +++ b/tm2/pkg/bft/state/execution.go @@ -2,8 +2,7 @@ package state import ( "fmt" - - "golang.org/x/exp/slog" + "log/slog" "github.com/gnolang/gno/tm2/pkg/amino" abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" diff --git a/tm2/pkg/bft/store/store_test.go b/tm2/pkg/bft/store/store_test.go index 6b5dd8a96bb..547069bc8a8 100644 --- a/tm2/pkg/bft/store/store_test.go +++ b/tm2/pkg/bft/store/store_test.go @@ -2,14 +2,13 @@ package store import ( "fmt" + "log/slog" "os" "runtime/debug" "strings" "testing" "time" - "golang.org/x/exp/slog" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tm2/pkg/bft/wal/wal.go b/tm2/pkg/bft/wal/wal.go index 26f3deeb49c..2424f45dfd2 100644 --- a/tm2/pkg/bft/wal/wal.go +++ b/tm2/pkg/bft/wal/wal.go @@ -8,11 +8,10 @@ import ( "fmt" "hash/crc32" "io" + "log/slog" "path/filepath" "time" - "golang.org/x/exp/slog" - "github.com/gnolang/gno/tm2/pkg/amino" auto "github.com/gnolang/gno/tm2/pkg/autofile" tmtime "github.com/gnolang/gno/tm2/pkg/bft/types/time" diff --git a/tm2/pkg/log/noop.go b/tm2/pkg/log/noop.go index b7c465ede0f..40656d941e1 100644 --- a/tm2/pkg/log/noop.go +++ b/tm2/pkg/log/noop.go @@ -2,8 +2,7 @@ package log import ( "context" - - "golang.org/x/exp/slog" + "log/slog" ) // NewNoopLogger returns a new no-op logger diff --git a/tm2/pkg/log/testing.go b/tm2/pkg/log/testing.go index be610ee38d2..220e3239c30 100644 --- a/tm2/pkg/log/testing.go +++ b/tm2/pkg/log/testing.go @@ -2,6 +2,7 @@ package log import ( "fmt" + "log/slog" "os" "path/filepath" "strings" @@ -9,7 +10,6 @@ import ( "time" "github.com/jaekwon/testify/require" - "golang.org/x/exp/slog" ) // NewTestingLogger returns a new testing logger diff --git a/tm2/pkg/p2p/conn/connection.go b/tm2/pkg/p2p/conn/connection.go index 7f0cf39fe5f..41b6a06629e 100644 --- a/tm2/pkg/p2p/conn/connection.go +++ b/tm2/pkg/p2p/conn/connection.go @@ -5,6 +5,7 @@ import ( goerrors "errors" "fmt" "io" + "log/slog" "math" "net" "reflect" @@ -13,8 +14,6 @@ import ( "sync/atomic" "time" - "golang.org/x/exp/slog" - "github.com/gnolang/gno/tm2/pkg/amino" "github.com/gnolang/gno/tm2/pkg/errors" "github.com/gnolang/gno/tm2/pkg/flow" diff --git a/tm2/pkg/p2p/peer.go b/tm2/pkg/p2p/peer.go index 11814b585c1..ef2ddcf2c25 100644 --- a/tm2/pkg/p2p/peer.go +++ b/tm2/pkg/p2p/peer.go @@ -2,10 +2,9 @@ package p2p import ( "fmt" + "log/slog" "net" - "golang.org/x/exp/slog" - "github.com/gnolang/gno/tm2/pkg/cmap" connm "github.com/gnolang/gno/tm2/pkg/p2p/conn" "github.com/gnolang/gno/tm2/pkg/service" diff --git a/tm2/pkg/p2p/upnp/probe.go b/tm2/pkg/p2p/upnp/probe.go index 29498124aa7..29480e7cecc 100644 --- a/tm2/pkg/p2p/upnp/probe.go +++ b/tm2/pkg/p2p/upnp/probe.go @@ -2,10 +2,9 @@ package upnp import ( "fmt" + "log/slog" "net" "time" - - "golang.org/x/exp/slog" ) type UPNPCapabilities struct { diff --git a/tm2/pkg/sdk/auth/keeper.go b/tm2/pkg/sdk/auth/keeper.go index 405256c6877..e43b5389844 100644 --- a/tm2/pkg/sdk/auth/keeper.go +++ b/tm2/pkg/sdk/auth/keeper.go @@ -2,8 +2,7 @@ package auth import ( "fmt" - - "golang.org/x/exp/slog" + "log/slog" "github.com/gnolang/gno/tm2/pkg/amino" "github.com/gnolang/gno/tm2/pkg/crypto" diff --git a/tm2/pkg/sdk/bank/keeper.go b/tm2/pkg/sdk/bank/keeper.go index 87791258108..5d3699c99ef 100644 --- a/tm2/pkg/sdk/bank/keeper.go +++ b/tm2/pkg/sdk/bank/keeper.go @@ -2,8 +2,7 @@ package bank import ( "fmt" - - "golang.org/x/exp/slog" + "log/slog" "github.com/gnolang/gno/tm2/pkg/crypto" "github.com/gnolang/gno/tm2/pkg/sdk" diff --git a/tm2/pkg/sdk/baseapp.go b/tm2/pkg/sdk/baseapp.go index e564435456a..1f62f53f81a 100644 --- a/tm2/pkg/sdk/baseapp.go +++ b/tm2/pkg/sdk/baseapp.go @@ -2,14 +2,13 @@ package sdk import ( "fmt" + "log/slog" "os" "runtime/debug" "sort" "strings" "syscall" - "golang.org/x/exp/slog" - "github.com/gnolang/gno/tm2/pkg/amino" abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" bft "github.com/gnolang/gno/tm2/pkg/bft/types" diff --git a/tm2/pkg/sdk/baseapp_test.go b/tm2/pkg/sdk/baseapp_test.go index 1d8e73acc8d..403b2521b8f 100644 --- a/tm2/pkg/sdk/baseapp_test.go +++ b/tm2/pkg/sdk/baseapp_test.go @@ -4,12 +4,11 @@ import ( "bytes" "encoding/binary" "fmt" + "log/slog" "os" "reflect" "testing" - "golang.org/x/exp/slog" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tm2/pkg/sdk/context.go b/tm2/pkg/sdk/context.go index c208a3e2e75..0e1021e0174 100644 --- a/tm2/pkg/sdk/context.go +++ b/tm2/pkg/sdk/context.go @@ -2,10 +2,9 @@ package sdk import ( "context" + "log/slog" "time" - "golang.org/x/exp/slog" - "github.com/gnolang/gno/tm2/pkg/amino" abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" "github.com/gnolang/gno/tm2/pkg/store" diff --git a/tm2/pkg/service/service.go b/tm2/pkg/service/service.go index 2a9fa0c3bfc..05f7a4f4ae6 100644 --- a/tm2/pkg/service/service.go +++ b/tm2/pkg/service/service.go @@ -3,10 +3,9 @@ package service import ( "errors" "fmt" + "log/slog" "sync/atomic" - "golang.org/x/exp/slog" - "github.com/gnolang/gno/tm2/pkg/log" )