diff --git a/.github/golangci.yml b/.github/golangci.yml index 53141a3143d..6f2d808932f 100644 --- a/.github/golangci.yml +++ b/.github/golangci.yml @@ -37,6 +37,7 @@ linters: - errorlint # errorlint is a linter for that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13 - gofumpt # Stricter gofmt - unused # Checks Go code for unused constants, variables, functions and types + - gomodguard # Enforces an allow and block list for direct Go module dependencies linters-settings: gofmt: @@ -59,6 +60,17 @@ 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 diff --git a/.github/workflows/db-tests.yml b/.github/workflows/db-tests.yml index f8da78cc3d8..b259a0bcf74 100644 --- a/.github/workflows/db-tests.yml +++ b/.github/workflows/db-tests.yml @@ -47,6 +47,15 @@ jobs: wget http://ftp.us.debian.org/debian/pool/main/l/leveldb/libleveldb-dev_1.22-3_amd64.deb sudo dpkg -i *.deb + - name: Set environment variables for debug mode + if: env.ACTIONS_STEP_DEBUG == 'true' + run: | + export LOG_PATH_DIR=${{ runner.temp }}/logs + mkdir -p $LOG_PATH_DIR + + echo "LOG_LEVEL=debug" >> $GITHUB_ENV + echo "LOG_PATH_DIR=$LOG_PATH_DIR" >> $GITHUB_ENV + # test ./pkgs/db - name: test ./tm2/pkg/db run: go test -tags ${{ matrix.tags }} ./tm2/pkg/db/... diff --git a/.github/workflows/dependabot-tidy.yml b/.github/workflows/dependabot-tidy.yml index 9db199a9605..8234de91924 100644 --- a/.github/workflows/dependabot-tidy.yml +++ b/.github/workflows/dependabot-tidy.yml @@ -23,18 +23,14 @@ jobs: go-version: 1.21.x - name: Tidy all Go mods + env: + VERIFY_MOD_SUMS: false run: | - set -e - # Find all go.mod files - gomods=$(find . -type f -name go.mod) - - # Tidy each go.mod file - for modfile in $gomods; do - dir=$(dirname "$modfile") + # Ensure Make is installed + make --version - # Run go mod tidy in the directory - (cd "$dir" && go mod tidy -v) || exit 1 - done + # Run the tidy target + make tidy - name: Commit changes, if any uses: stefanzweifel/git-auto-commit-action@v5 diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index b72b9b24dc1..35917d38e99 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -48,6 +48,14 @@ jobs: - uses: actions/setup-go@v4 with: go-version: ${{ matrix.goversion }} + - name: Set environment variables for debug mode + if: env.ACTIONS_STEP_DEBUG == 'true' + run: | + export LOG_PATH_DIR=${{ runner.temp }}/logs + mkdir -p $LOG_PATH_DIR + + echo "LOG_LEVEL=debug" >> $GITHUB_ENV + echo "LOG_PATH_DIR=$LOG_PATH_DIR" >> $GITHUB_ENV - run: go install -v ./gnovm/cmd/gno - run: go run ./gnovm/cmd/gno test --verbose ./examples/... lint: diff --git a/.github/workflows/gnoland.yml b/.github/workflows/gnoland.yml index d305bed2dcd..25b14c0db04 100644 --- a/.github/workflows/gnoland.yml +++ b/.github/workflows/gnoland.yml @@ -60,7 +60,7 @@ jobs: - _test.gnoland - _test.gnokey - _test.pkgs - - _test.gnoweb + - _test.gnoweb runs-on: ubuntu-latest timeout-minutes: 15 steps: @@ -68,24 +68,31 @@ jobs: - uses: actions/setup-go@v4 with: go-version: ${{ matrix.goversion }} + - name: Set environment variables for debug mode + if: ${{ runner.debug == 1 }} + run: | + export LOG_PATH_DIR=${{ runner.temp }}/logs-go${{ matrix.goversion }}-${{ matrix.args }} + mkdir -p $LOG_PATH_DIR + + echo "LOG_LEVEL=debug" >> $GITHUB_ENV + echo "LOG_PATH_DIR=$LOG_PATH_DIR" >> $GITHUB_ENV - name: test working-directory: gno.land run: | export GOPATH=$HOME/go export GOTEST_FLAGS="-v -p 1 -timeout=30m -coverprofile=coverage.out -covermode=atomic" - export LOG_DIR="${{ runner.temp }}/logs/test-${{ matrix.goversion }}-gnoland" make ${{ matrix.args }} - - name: Upload Test Log - if: always() - uses: actions/upload-artifact@v3 - with: - name: logs-test-gnoland-go${{ matrix.goversion }} - path: ${{ runner.temp }}/logs/**/*.log - uses: actions/upload-artifact@v3 if: ${{ runner.os == 'Linux' && matrix.goversion == '1.21.x' }} with: name: ${{runner.os}}-coverage-gnoland-${{ matrix.args}}-${{matrix.goversion}} path: ./gno.land/coverage.out + - name: Upload Debug Logs + uses: actions/upload-artifact@v3 + if: ${{ always() && runner.debug == 1 }} + with: + name: logs-test-go${{ matrix.goversion }}-${{ matrix.args }} + path: ${{ env.LOG_PATH_DIR }}/**/* upload-coverage: needs: test @@ -99,7 +106,7 @@ jobs: uses: codecov/codecov-action@v3 with: directory: ${{ runner.temp }}/coverage - token: ${{ secrets.CODECOV_TOKEN }} + token: ${{ secrets.CODECOV_TOKEN }} fail_ci_if_error: ${{ github.repository == 'gnolang/gno' }} docker-integration: diff --git a/.github/workflows/gnovm.yml b/.github/workflows/gnovm.yml index 5fa68ac305a..15e0f886e1b 100644 --- a/.github/workflows/gnovm.yml +++ b/.github/workflows/gnovm.yml @@ -74,6 +74,14 @@ jobs: - uses: actions/setup-go@v4 with: go-version: ${{ matrix.goversion }} + - name: Set environment variables for debug mode + if: ${{ runner.debug == 1 }} + run: | + export LOG_PATH_DIR=${{ runner.temp }}/logs-go${{ matrix.goversion }}-${{ matrix.args }} + mkdir -p $LOG_PATH_DIR + + echo "LOG_LEVEL=debug" >> $GITHUB_ENV + echo "LOG_PATH_DIR=$LOG_PATH_DIR" >> $GITHUB_ENV - name: test working-directory: gnovm env: @@ -92,6 +100,12 @@ jobs: with: name: ${{runner.os}}-coverage-gnovm-${{ matrix.args}}-${{matrix.goversion}} path: ${{ env.COVERAGE_DIR }} + - name: Upload Debug Logs + uses: actions/upload-artifact@v3 + if: ${{ always() && runner.debug == 1 }} + with: + name: logs-test-go${{ matrix.goversion }}-${{ matrix.args }} + path: ${{ env.LOG_PATH_DIR }}/**/* upload-coverage: needs: test @@ -129,6 +143,6 @@ jobs: uses: codecov/codecov-action@v3 with: files: ${{ env.COVERAGE_PROFILE }} - token: ${{ secrets.CODECOV_TOKEN }} + token: ${{ secrets.CODECOV_TOKEN }} fail_ci_if_error: ${{ github.repository == 'gnolang/gno' }} diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index b874159473e..b417e904e7c 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -48,11 +48,11 @@ jobs: # inspired by: # https://github.com/Jerome1337/gofmt-action/blob/d5eabd189843f1d568286a54578159978b7c0fb1/entrypoint.sh - - name: Check gofumpt + - name: Check gofumpt / goimports run: | - output="$(GOFMT_FLAGS=-l make -s fmt)" + output="$(GOFMT_FLAGS=-l GOIMPORTS_FLAGS=-l make -s fmt)" if [ ! -z "$output" ]; then - echo "The following files are not properly formatted; run 'make fmt' to format them." + echo "The following files are not properly formatted; run 'make fmt imports' to format them." echo "$output" exit 1 else @@ -70,22 +70,15 @@ jobs: with: go-version: 1.21.x + - name: Install make + run: sudo apt-get install -y make + - name: Check go.mods + env: + VERIFY_MOD_SUMS: true run: | - set -xe - # Find all go.mod files - gomods=$(find . -type f -name go.mod) - - # Calculate sums for all go.mod files - sums=$(sha256sum $gomods) - - # Iterate over each go.mod file - for modfile in $gomods; do - dir=$(dirname "$modfile") - - # Run go mod tidy in the directory - (cd "$dir" && go mod tidy -v) || exit 1 - done - - # Verify the sums - echo "$sums" | sha256sum -c + # Ensure Make is installed + make --version + + # Run the tidy target + make tidy diff --git a/.github/workflows/misc.yml b/.github/workflows/misc.yml index 9c666675fa4..52329e9c7d6 100644 --- a/.github/workflows/misc.yml +++ b/.github/workflows/misc.yml @@ -63,6 +63,15 @@ jobs: with: go-version: ${{ matrix.goversion }} + - name: Set environment variables for debug mode + if: env.ACTIONS_STEP_DEBUG == 'true' + run: | + export LOG_PATH_DIR=${{ runner.temp }}/logs + mkdir -p $LOG_PATH_DIR + + echo "LOG_LEVEL=debug" >> $GITHUB_ENV + echo "LOG_PATH_DIR=$LOG_PATH_DIR" >> $GITHUB_ENV + - name: Test working-directory: misc run: | diff --git a/.github/workflows/tm2.yml b/.github/workflows/tm2.yml index d5c6d9ddda6..bbe379bb069 100644 --- a/.github/workflows/tm2.yml +++ b/.github/workflows/tm2.yml @@ -42,6 +42,7 @@ jobs: working-directory: tm2 run: GOOS=${{ matrix.goos }} GOARCH=${{ matrix.goarch }} go install ${{ matrix.program }} + test: strategy: fail-fast: false @@ -61,6 +62,14 @@ jobs: - uses: actions/setup-go@v4 with: go-version: ${{ matrix.goversion }} + - name: Set environment variables for debug mode + if: ${{ runner.debug == 1 }} + run: | + export LOG_PATH_DIR=${{ runner.temp }}/logs-go${{ matrix.goversion }}-${{ matrix.args }} + mkdir -p $LOG_PATH_DIR + + echo "LOG_LEVEL=debug" >> $GITHUB_ENV + echo "LOG_PATH_DIR=$LOG_PATH_DIR" >> $GITHUB_ENV - name: test working-directory: tm2 run: | @@ -73,6 +82,12 @@ jobs: with: name: ${{runner.os}}-coverage-tm2-${{ matrix.args}}-${{matrix.goversion}} path: ./tm2/coverage.out + - name: Upload Debug Logs + uses: actions/upload-artifact@v3 + if: ${{ always() && runner.debug == 1 }} + with: + name: logs-test-go${{ matrix.goversion }}-${{ matrix.args }} + path: ${{ env.LOG_PATH_DIR }}/**/* upload-coverage: needs: test @@ -86,6 +101,6 @@ jobs: uses: codecov/codecov-action@v3 with: directory: ${{ runner.temp }}/coverage - token: ${{ secrets.CODECOV_TOKEN }} + token: ${{ secrets.CODECOV_TOKEN }} fail_ci_if_error: ${{ github.repository == 'gnolang/gno' }} diff --git a/Makefile b/Makefile index 80c9bef2ed7..dc3f8e47089 100644 --- a/Makefile +++ b/Makefile @@ -37,11 +37,15 @@ test.docker: .PHONY: fmt fmt: - $(MAKE) --no-print-directory -C tm2 fmt - $(MAKE) --no-print-directory -C gnovm fmt - $(MAKE) --no-print-directory -C gno.land fmt + $(MAKE) --no-print-directory -C tm2 fmt imports + $(MAKE) --no-print-directory -C gnovm fmt imports + $(MAKE) --no-print-directory -C gno.land fmt imports $(MAKE) --no-print-directory -C examples fmt .PHONY: lint lint: $(rundep) github.com/golangci/golangci-lint/cmd/golangci-lint run --config .github/golangci.yml + +.PHONY: tidy +tidy: + $(MAKE) --no-print-directory -C misc tidy diff --git a/contribs/gnodev/go.mod b/contribs/gnodev/go.mod index 52ceb547f90..97b5830263e 100644 --- a/contribs/gnodev/go.mod +++ b/contribs/gnodev/go.mod @@ -7,6 +7,8 @@ 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 golang.org/x/term v0.16.0 ) @@ -38,6 +40,7 @@ require ( github.com/jaekwon/testify v1.6.1 // indirect github.com/jmhodges/levigo v1.0.0 // indirect github.com/klauspost/compress v1.12.3 // indirect + github.com/kr/pretty v0.2.1 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/linxGnu/grocksdb v1.8.11 // indirect github.com/pelletier/go-toml v1.9.5 // indirect @@ -50,7 +53,9 @@ require ( github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // 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 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 8957131a347..710163dd86d 100644 --- a/contribs/gnodev/go.sum +++ b/contribs/gnodev/go.sum @@ -6,6 +6,7 @@ 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= @@ -98,8 +99,8 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= 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= @@ -128,8 +129,9 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/klauspost/compress v1.12.3 h1:G5AfA94pHPysR56qqrkO2pxEexdDzrpFJ6yt/VqWxVU= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= -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/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 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= @@ -194,8 +196,15 @@ 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/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= 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= @@ -204,6 +213,8 @@ 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= diff --git a/contribs/gnodev/main.go b/contribs/gnodev/main.go index ea9c3fe2451..6ae2633c6f3 100644 --- a/contribs/gnodev/main.go +++ b/contribs/gnodev/main.go @@ -16,11 +16,12 @@ import ( gnodev "github.com/gnolang/gno/contribs/gnodev/pkg/dev" "github.com/gnolang/gno/contribs/gnodev/pkg/rawterm" "github.com/gnolang/gno/gno.land/pkg/gnoweb" + "github.com/gnolang/gno/gno.land/pkg/log" "github.com/gnolang/gno/gnovm/pkg/gnoenv" "github.com/gnolang/gno/gnovm/pkg/gnomod" "github.com/gnolang/gno/tm2/pkg/commands" - tmlog "github.com/gnolang/gno/tm2/pkg/log" osm "github.com/gnolang/gno/tm2/pkg/os" + "go.uber.org/zap/zapcore" ) const ( @@ -61,6 +62,7 @@ additional specified paths.`, cmd.Execute(context.Background(), os.Args[1:]) } + func (c *devCfg) RegisterFlags(fs *flag.FlagSet) { fs.StringVar( &c.webListenerAddr, @@ -89,7 +91,6 @@ func (c *devCfg) RegisterFlags(fs *flag.FlagSet) { defaultDevOptions.noWatch, "do not watch for files change", ) - } func execDev(cfg *devCfg, args []string, io commands.IO) error { @@ -303,9 +304,9 @@ func setupRawTerm(io commands.IO) (rt *rawterm.RawTerm, restore func() error, er func setupDevNode(ctx context.Context, rt *rawterm.RawTerm, pkgspath []string) (*gnodev.Node, error) { nodeOut := rt.NamespacedWriter("Node") - logger := tmlog.NewTMLogger(nodeOut) - logger.SetLevel(tmlog.LevelError) - return gnodev.NewDevNode(ctx, logger, pkgspath) + zapLogger := log.NewZapConsoleLogger(nodeOut, zapcore.ErrorLevel) + + return gnodev.NewDevNode(ctx, log.ZapLoggerToSlog(zapLogger), pkgspath) } // setupGnowebServer initializes and starts the Gnoweb server. @@ -317,10 +318,9 @@ func serveGnoWebServer(l net.Listener, dnode *gnodev.Node, rt *rawterm.RawTerm) webConfig.HelpChainID = dnode.Config().ChainID() webConfig.HelpRemote = dnode.GetRemoteAddress() - loggerweb := tmlog.NewTMLogger(rt.NamespacedWriter("GnoWeb")) - loggerweb.SetLevel(tmlog.LevelDebug) + zapLogger := log.NewZapConsoleLogger(rt.NamespacedWriter("GnoWeb"), zapcore.DebugLevel) - app := gnoweb.MakeApp(loggerweb, webConfig) + app := gnoweb.MakeApp(log.ZapLoggerToSlog(zapLogger), webConfig) server.ReadHeaderTimeout = 60 * time.Second server.Handler = app.Router diff --git a/contribs/gnodev/pkg/dev/node.go b/contribs/gnodev/pkg/dev/node.go index 514d13cd858..c1eddc7c91d 100644 --- a/contribs/gnodev/pkg/dev/node.go +++ b/contribs/gnodev/pkg/dev/node.go @@ -15,10 +15,10 @@ import ( "github.com/gnolang/gno/tm2/pkg/bft/rpc/client" bft "github.com/gnolang/gno/tm2/pkg/bft/types" "github.com/gnolang/gno/tm2/pkg/crypto" - "github.com/gnolang/gno/tm2/pkg/log" "github.com/gnolang/gno/tm2/pkg/std" - //backup "github.com/gnolang/tx-archive/backup/client" - //restore "github.com/gnolang/tx-archive/restore/client" + "golang.org/x/exp/slog" + // backup "github.com/gnolang/tx-archive/backup/client" + // restore "github.com/gnolang/tx-archive/restore/client" ) const gnoDevChainID = "tendermint_test" // XXX: this is hardcoded and cannot be change bellow @@ -28,7 +28,7 @@ type Node struct { *node.Node client client.Client - logger log.Logger + logger *slog.Logger pkgs PkgsMap // path -> pkg // keep track of number of loaded package to be able to skip them on restore loadedPackages int @@ -45,7 +45,7 @@ var ( } ) -func NewDevNode(ctx context.Context, logger log.Logger, pkgslist []string) (*Node, error) { +func NewDevNode(ctx context.Context, logger *slog.Logger, pkgslist []string) (*Node, error) { mpkgs, err := newPkgsMap(pkgslist) if err != nil { return nil, fmt.Errorf("unable map pkgs list: %w", err) @@ -411,7 +411,7 @@ func (pm PkgsMap) Load(creator bft.Address, fee std.Fee, deposit std.Coins) ([]s return txs, nil } -func newNode(logger log.Logger, genesis gnoland.GnoGenesisState) (*node.Node, error) { +func newNode(logger *slog.Logger, genesis gnoland.GnoGenesisState) (*node.Node, error) { rootdir := gnoenv.RootDir() nodeConfig := gnoland.NewDefaultInMemoryNodeConfig(rootdir) diff --git a/contribs/gnodev/pkg/rawterm/rawterm.go b/contribs/gnodev/pkg/rawterm/rawterm.go index 8f29e88fc92..f6d6e7534e2 100644 --- a/contribs/gnodev/pkg/rawterm/rawterm.go +++ b/contribs/gnodev/pkg/rawterm/rawterm.go @@ -11,9 +11,7 @@ import ( "golang.org/x/term" ) -var ( - CRLF = []byte{'\r', '\n'} -) +var CRLF = []byte{'\r', '\n'} // rawTerminal wraps an io.Writer, converting \n to \r\n type RawTerm struct { diff --git a/contribs/gnokeykc/go.mod b/contribs/gnokeykc/go.mod index 6c2cfa690df..088be921408 100644 --- a/contribs/gnokeykc/go.mod +++ b/contribs/gnokeykc/go.mod @@ -17,6 +17,7 @@ require ( github.com/cespare/xxhash v1.1.0 // indirect github.com/cespare/xxhash/v2 v2.1.1 // indirect github.com/danieljoos/wincred v1.2.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/dgraph-io/badger/v3 v3.2103.5 // indirect github.com/dgraph-io/ristretto v0.1.1 // indirect @@ -31,6 +32,7 @@ require ( github.com/golang/snappy v0.0.4 // indirect github.com/google/flatbuffers v1.12.1 // indirect github.com/gorilla/websocket v1.5.1 // indirect + github.com/jaekwon/testify v1.6.1 // indirect github.com/jmhodges/levigo v1.0.0 // indirect github.com/klauspost/compress v1.12.3 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect @@ -38,14 +40,18 @@ require ( github.com/pelletier/go-toml v1.9.5 // indirect github.com/peterbourgon/ff/v3 v3.4.0 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rs/cors v1.10.1 // indirect + github.com/stretchr/testify v1.8.4 // indirect github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect 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 golang.org/x/term v0.16.0 // indirect google.golang.org/protobuf v1.31.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/contribs/gnokeykc/go.sum b/contribs/gnokeykc/go.sum index c5f601b5ec2..5dcad4034c9 100644 --- a/contribs/gnokeykc/go.sum +++ b/contribs/gnokeykc/go.sum @@ -101,8 +101,8 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= @@ -110,6 +110,7 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jaekwon/testify v1.6.1 h1:4AtAJcR9GzXN5W4DdY7ie74iCPiJV1JJUJL90t2ZUyw= +github.com/jaekwon/testify v1.6.1/go.mod h1:Oun0RXIHI7osufabQ60i4Lqkj0GXLbqI1I7kgzBNm1U= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= @@ -120,9 +121,11 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/klauspost/compress v1.12.3 h1:G5AfA94pHPysR56qqrkO2pxEexdDzrpFJ6yt/VqWxVU= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= +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/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= @@ -167,8 +170,10 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= 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= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c h1:g+WoO5jjkqGAzHWCjJB1zZfXPIAaDpzXIEJ0eS6B5Ok= github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8= @@ -190,6 +195,8 @@ 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= @@ -270,6 +277,7 @@ google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 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/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= diff --git a/examples/Makefile b/examples/Makefile index 9b628e01ce5..56ad4b30b42 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -38,6 +38,11 @@ GOFMT_FLAGS ?= -w fmt: go run -modfile ../misc/devdeps/go.mod mvdan.cc/gofumpt $(GOFMT_FLAGS) `find . -name "*.gno"` +.PHONY: imports +GOIMPORTS_FLAGS ?= -w +imports: + $(rundep) golang.org/x/tools/cmd/goimports $(GOIMPORTS_FLAGS) . + .PHONY: tidy tidy: find . -name "gno.mod" -execdir go run github.com/gnolang/gno/gnovm/cmd/gno mod tidy \; diff --git a/gno.land/Makefile b/gno.land/Makefile index 982063d155c..8138dfcfe3e 100644 --- a/gno.land/Makefile +++ b/gno.land/Makefile @@ -56,6 +56,11 @@ GOFMT_FLAGS ?= -w fmt: $(rundep) mvdan.cc/gofumpt $(GOFMT_FLAGS) . +.PHONY: imports +GOIMPORTS_FLAGS ?= -w +imports: + $(rundep) golang.org/x/tools/cmd/goimports $(GOIMPORTS_FLAGS) . + ######################################## # Test suite .PHONY: test diff --git a/gno.land/cmd/gnoland/start.go b/gno.land/cmd/gnoland/start.go index 40d33a218cc..d82647b5b2e 100644 --- a/gno.land/cmd/gnoland/start.go +++ b/gno.land/cmd/gnoland/start.go @@ -10,6 +10,7 @@ import ( "time" "github.com/gnolang/gno/gno.land/pkg/gnoland" + "github.com/gnolang/gno/gno.land/pkg/log" "github.com/gnolang/gno/gnovm/pkg/gnoenv" abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" "github.com/gnolang/gno/tm2/pkg/bft/config" @@ -21,9 +22,9 @@ import ( bft "github.com/gnolang/gno/tm2/pkg/bft/types" "github.com/gnolang/gno/tm2/pkg/commands" "github.com/gnolang/gno/tm2/pkg/crypto" - "github.com/gnolang/gno/tm2/pkg/log" osm "github.com/gnolang/gno/tm2/pkg/os" "github.com/gnolang/gno/tm2/pkg/std" + "go.uber.org/zap/zapcore" ) type startCfg struct { @@ -41,6 +42,9 @@ type startCfg struct { txEventStoreType string txEventStorePath string nodeConfigPath string + + logLevel string + logFormat string } func newStartCmd(io commands.IO) *commands.Command { @@ -165,6 +169,20 @@ func (c *startCfg) RegisterFlags(fs *flag.FlagSet) { fmt.Sprintf("path for the file tx event store (required if event store is '%s')", file.EventStoreType), ) + fs.StringVar( + &c.logLevel, + "log-level", + zapcore.DebugLevel.String(), + "log level for the gnoland node,", + ) + + fs.StringVar( + &c.logFormat, + "log-format", + log.ConsoleFormat.String(), + "log format for the gnoland node", + ) + // XXX(deprecated): use data-dir instead fs.StringVar( &c.dataDir, @@ -175,7 +193,6 @@ func (c *startCfg) RegisterFlags(fs *flag.FlagSet) { } func execStart(c *startCfg, io commands.IO) error { - logger := log.NewTMLogger(log.NewSyncWriter(io.Out())) dataDir := c.dataDir var ( @@ -197,6 +214,21 @@ func execStart(c *startCfg, io commands.IO) error { return fmt.Errorf("unable to load node configuration, %w", loadCfgErr) } + // Initialize the log level + logLevel, err := zapcore.ParseLevel(c.logLevel) + if err != nil { + return fmt.Errorf("unable to parse log level, %w", err) + } + + // Initialize the log format + logFormat := log.Format(strings.ToLower(c.logFormat)) + + // Initialize the zap logger + zapLogger := log.GetZapLoggerFn(logFormat)(io.Out(), logLevel) + + // Wrap the zap logger + logger := log.ZapLoggerToSlog(zapLogger) + // Write genesis file if missing. genesisFilePath := filepath.Join(dataDir, cfg.Genesis) @@ -248,6 +280,9 @@ func execStart(c *startCfg, io commands.IO) error { if gnoNode.IsRunning() { _ = gnoNode.Stop() } + + // Sync the logger before exiting + _ = zapLogger.Sync() }) // Run forever diff --git a/gno.land/cmd/gnoweb/main.go b/gno.land/cmd/gnoweb/main.go index 34b12928367..547134548ff 100644 --- a/gno.land/cmd/gnoweb/main.go +++ b/gno.land/cmd/gnoweb/main.go @@ -9,7 +9,8 @@ import ( // for static files "github.com/gnolang/gno/gno.land/pkg/gnoweb" - "github.com/gnolang/gno/tm2/pkg/log" + "github.com/gnolang/gno/gno.land/pkg/log" + "go.uber.org/zap/zapcore" // for error types // "github.com/gnolang/gno/tm2/pkg/sdk" // for baseapp (info, status) ) @@ -41,8 +42,8 @@ func runMain(args []string) error { return err } - logger := log.NewTMLogger(os.Stdout) - logger.SetLevel(log.LevelDebug) + zapLogger := log.NewZapConsoleLogger(os.Stdout, zapcore.DebugLevel) + logger := log.ZapLoggerToSlog(zapLogger) logger.Info("Running", "listener", "http://"+bindAddress) server := &http.Server{ @@ -54,5 +55,6 @@ func runMain(args []string) error { if err := server.ListenAndServe(); err != nil { logger.Error("HTTP server stopped", " error:", err) } - return nil + + return zapLogger.Sync() } diff --git a/gno.land/pkg/gnoclient/client_test.go b/gno.land/pkg/gnoclient/client_test.go index 418a95aa997..86af2858275 100644 --- a/gno.land/pkg/gnoclient/client_test.go +++ b/gno.land/pkg/gnoclient/client_test.go @@ -31,7 +31,7 @@ func newInMemorySigner(t *testing.T, chainid string) *SignerFromKeybase { func TestClient_Request(t *testing.T) { config, _ := integration.TestingNodeConfig(t, gnoenv.RootDir()) - node, remoteAddr := integration.TestingInMemoryNode(t, log.NewNopLogger(), config) + node, remoteAddr := integration.TestingInMemoryNode(t, log.NewNoopLogger(), config) defer node.Stop() signer := newInMemorySigner(t, config.TMConfig.ChainID()) diff --git a/gno.land/pkg/gnoland/app.go b/gno.land/pkg/gnoland/app.go index 689ae1ae106..0b0488fc98e 100644 --- a/gno.land/pkg/gnoland/app.go +++ b/gno.land/pkg/gnoland/app.go @@ -4,6 +4,8 @@ import ( "fmt" "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" @@ -25,13 +27,13 @@ type AppOptions struct { // It serves as the gno equivalent of GOROOT. GnoRootDir string SkipFailingGenesisTxs bool - Logger log.Logger + Logger *slog.Logger MaxCycles int64 } func NewAppOptions() *AppOptions { return &AppOptions{ - Logger: log.NewNopLogger(), + Logger: log.NewNoopLogger(), DB: dbm.NewMemDB(), GnoRootDir: gnoenv.RootDir(), } @@ -118,7 +120,7 @@ func NewAppWithOptions(cfg *AppOptions) (abci.Application, error) { } // NewApp creates the GnoLand application. -func NewApp(dataRootDir string, skipFailingGenesisTxs bool, logger log.Logger, maxCycles int64) (abci.Application, error) { +func NewApp(dataRootDir string, skipFailingGenesisTxs bool, logger *slog.Logger, maxCycles int64) (abci.Application, error) { var err error cfg := NewAppOptions() @@ -153,15 +155,15 @@ func InitChainer(baseApp *sdk.BaseApp, acctKpr auth.AccountKeeperI, bankKpr bank for i, tx := range genState.Txs { res := baseApp.Deliver(tx) if res.IsErr() { - ctx.Logger().Error("LOG", res.Log) - ctx.Logger().Error("#", i, string(amino.MustMarshalJSON(tx))) + ctx.Logger().Error("LOG", "log", res.Log) + ctx.Logger().Error(fmt.Sprintf("#%d", i), "value", string(amino.MustMarshalJSON(tx))) // NOTE: comment out to ignore. if !skipFailingGenesisTxs { panic(res.Log) } } else { - ctx.Logger().Info("SUCCESS:", string(amino.MustMarshalJSON(tx))) + ctx.Logger().Info("SUCCESS:", "value", string(amino.MustMarshalJSON(tx))) } } // Done! diff --git a/gno.land/pkg/gnoland/node_inmemory.go b/gno.land/pkg/gnoland/node_inmemory.go index bb6dae0085f..2db8544a909 100644 --- a/gno.land/pkg/gnoland/node_inmemory.go +++ b/gno.land/pkg/gnoland/node_inmemory.go @@ -5,6 +5,8 @@ import ( "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" @@ -14,7 +16,6 @@ import ( "github.com/gnolang/gno/tm2/pkg/crypto/ed25519" "github.com/gnolang/gno/tm2/pkg/db" "github.com/gnolang/gno/tm2/pkg/events" - "github.com/gnolang/gno/tm2/pkg/log" "github.com/gnolang/gno/tm2/pkg/p2p" "github.com/gnolang/gno/tm2/pkg/std" ) @@ -104,7 +105,7 @@ func (cfg *InMemoryNodeConfig) validate() error { // NewInMemoryNode creates an in-memory gnoland node. In this mode, the node does not // persist any data and uses an in-memory database. The `InMemoryNodeConfig.TMConfig.RootDir` // should point to the correct gno repository to load the stdlibs. -func NewInMemoryNode(logger log.Logger, cfg *InMemoryNodeConfig) (*node.Node, error) { +func NewInMemoryNode(logger *slog.Logger, cfg *InMemoryNodeConfig) (*node.Node, error) { if err := cfg.validate(); err != nil { return nil, fmt.Errorf("validate config error: %w", err) } diff --git a/gno.land/pkg/gnoweb/gnoweb.go b/gno.land/pkg/gnoweb/gnoweb.go index c250842fb50..451389c7d73 100644 --- a/gno.land/pkg/gnoweb/gnoweb.go +++ b/gno.land/pkg/gnoweb/gnoweb.go @@ -14,10 +14,11 @@ 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" - "github.com/gnolang/gno/tm2/pkg/log" "github.com/gnolang/gno/tm2/pkg/std" "github.com/gorilla/mux" "github.com/gotuna/gotuna" @@ -57,7 +58,7 @@ func NewDefaultConfig() Config { } } -func MakeApp(logger log.Logger, cfg Config) gotuna.App { +func MakeApp(logger *slog.Logger, cfg Config) gotuna.App { var viewFiles fs.FS // Get specific views directory if specified @@ -131,7 +132,7 @@ func MakeApp(logger log.Logger, cfg Config) gotuna.App { // url is intended to be shorter. // UX is intended to be more minimalistic. // A link to the realm realm is added. -func handlerRealmAlias(logger log.Logger, app gotuna.App, cfg *Config, rlmpath string) http.Handler { +func handlerRealmAlias(logger *slog.Logger, app gotuna.App, cfg *Config, rlmpath string) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { rlmfullpath := "gno.land" + rlmpath querystr := "" // XXX: "?gnoweb-alias=1" @@ -176,7 +177,7 @@ func handlerRealmAlias(logger log.Logger, app gotuna.App, cfg *Config, rlmpath s }) } -func handlerFaucet(logger log.Logger, app gotuna.App, cfg *Config) http.Handler { +func handlerFaucet(logger *slog.Logger, app gotuna.App, cfg *Config) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { app.NewTemplatingEngine(). Set("Config", cfg). @@ -184,7 +185,7 @@ func handlerFaucet(logger log.Logger, app gotuna.App, cfg *Config) http.Handler }) } -func handlerStatusJSON(logger log.Logger, app gotuna.App, cfg *Config) http.Handler { +func handlerStatusJSON(logger *slog.Logger, app gotuna.App, cfg *Config) http.Handler { startedAt := time.Now() return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var ret struct { @@ -235,7 +236,7 @@ func handlerStatusJSON(logger log.Logger, app gotuna.App, cfg *Config) http.Hand }) } -func handlerRedirect(logger log.Logger, app gotuna.App, cfg *Config, to string) http.Handler { +func handlerRedirect(logger *slog.Logger, app gotuna.App, cfg *Config, to string) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, to, http.StatusFound) tmpl := app.NewTemplatingEngine() @@ -245,7 +246,7 @@ func handlerRedirect(logger log.Logger, app gotuna.App, cfg *Config, to string) }) } -func handlerRealmMain(logger log.Logger, app gotuna.App, cfg *Config) http.Handler { +func handlerRealmMain(logger *slog.Logger, app gotuna.App, cfg *Config) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) rlmname := vars["rlmname"] @@ -302,13 +303,13 @@ type pathLink struct { Text string } -func handlerRealmRender(logger log.Logger, app gotuna.App, cfg *Config) http.Handler { +func handlerRealmRender(logger *slog.Logger, app gotuna.App, cfg *Config) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { handleRealmRender(logger, app, cfg, w, r) }) } -func handleRealmRender(logger log.Logger, app gotuna.App, cfg *Config, w http.ResponseWriter, r *http.Request) { +func handleRealmRender(logger *slog.Logger, app gotuna.App, cfg *Config, w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) rlmname := vars["rlmname"] rlmpath := "gno.land/r/" + rlmname @@ -353,7 +354,7 @@ func handleRealmRender(logger log.Logger, app gotuna.App, cfg *Config, w http.Re tmpl.Render(w, r, "realm_render.html", "funcs.html") } -func handlerRealmFile(logger log.Logger, app gotuna.App, cfg *Config) http.Handler { +func handlerRealmFile(logger *slog.Logger, app gotuna.App, cfg *Config) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) diruri := "gno.land/r/" + vars["rlmname"] @@ -362,7 +363,7 @@ func handlerRealmFile(logger log.Logger, app gotuna.App, cfg *Config) http.Handl }) } -func handlerPackageFile(logger log.Logger, app gotuna.App, cfg *Config) http.Handler { +func handlerPackageFile(logger *slog.Logger, app gotuna.App, cfg *Config) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) pkgpath := "gno.land/p/" + vars["filepath"] @@ -376,7 +377,7 @@ func handlerPackageFile(logger log.Logger, app gotuna.App, cfg *Config) http.Han }) } -func renderPackageFile(logger log.Logger, app gotuna.App, cfg *Config, w http.ResponseWriter, r *http.Request, diruri string, filename string) { +func renderPackageFile(logger *slog.Logger, app gotuna.App, cfg *Config, w http.ResponseWriter, r *http.Request, diruri string, filename string) { if filename == "" { // Request is for a folder. qpath := qFileStr @@ -415,7 +416,7 @@ func renderPackageFile(logger log.Logger, app gotuna.App, cfg *Config, w http.Re } } -func makeRequest(log log.Logger, cfg *Config, qpath string, data []byte) (res *abci.ResponseQuery, err error) { +func makeRequest(log *slog.Logger, cfg *Config, qpath string, data []byte) (res *abci.ResponseQuery, err error) { opts2 := client.ABCIQueryOptions{ // Height: height, XXX // Prove: false, XXX @@ -435,7 +436,7 @@ func makeRequest(log log.Logger, cfg *Config, qpath string, data []byte) (res *a return &qres.Response, nil } -func handlerStaticFile(logger log.Logger, app gotuna.App, cfg *Config) http.Handler { +func handlerStaticFile(logger *slog.Logger, app gotuna.App, cfg *Config) http.Handler { fs := http.FS(app.Static) fileapp := http.StripPrefix("/static", http.FileServer(fs)) @@ -460,7 +461,7 @@ func handlerStaticFile(logger log.Logger, app gotuna.App, cfg *Config) http.Hand }) } -func handlerFavicon(logger log.Logger, app gotuna.App, cfg *Config) http.Handler { +func handlerFavicon(logger *slog.Logger, app gotuna.App, cfg *Config) http.Handler { fs := http.FS(app.Static) return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -485,7 +486,7 @@ func handleNotFound(app gotuna.App, cfg *Config, path string, w http.ResponseWri Render(w, r, "404.html", "funcs.html") } -func writeError(logger log.Logger, w http.ResponseWriter, err error) { +func writeError(logger *slog.Logger, w http.ResponseWriter, err error) { if details := errors.Unwrap(err); details != nil { logger.Error("handler", "error", err, "details", details) } else { diff --git a/gno.land/pkg/gnoweb/gnoweb_test.go b/gno.land/pkg/gnoweb/gnoweb_test.go index 61f7244141e..82c76266683 100644 --- a/gno.land/pkg/gnoweb/gnoweb_test.go +++ b/gno.land/pkg/gnoweb/gnoweb_test.go @@ -45,12 +45,12 @@ func TestRoutes(t *testing.T) { } config, _ := integration.TestingNodeConfig(t, gnoenv.RootDir()) - node, remoteAddr := integration.TestingInMemoryNode(t, log.NewNopLogger(), config) + node, remoteAddr := integration.TestingInMemoryNode(t, log.NewTestingLogger(t), config) defer node.Stop() cfg := NewDefaultConfig() - logger := log.TestingLogger() + logger := log.NewTestingLogger(t) // set the `remoteAddr` of the client to the listening address of the // node, which is randomly assigned. @@ -94,13 +94,13 @@ func TestAnalytics(t *testing.T) { } config, _ := integration.TestingNodeConfig(t, gnoenv.RootDir()) - node, remoteAddr := integration.TestingInMemoryNode(t, log.NewNopLogger(), config) + node, remoteAddr := integration.TestingInMemoryNode(t, log.NewTestingLogger(t), config) defer node.Stop() cfg := NewDefaultConfig() cfg.RemoteAddr = remoteAddr - logger := log.TestingLogger() + logger := log.NewTestingLogger(t) t.Run("with", func(t *testing.T) { for _, route := range routes { diff --git a/gno.land/pkg/integration/testing_integration.go b/gno.land/pkg/integration/testing_integration.go index 8974ea75637..b0dcc5737e6 100644 --- a/gno.land/pkg/integration/testing_integration.go +++ b/gno.land/pkg/integration/testing_integration.go @@ -11,17 +11,21 @@ import ( "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" "github.com/gnolang/gno/gnovm/pkg/gnoenv" "github.com/gnolang/gno/tm2/pkg/bft/node" "github.com/gnolang/gno/tm2/pkg/commands" "github.com/gnolang/gno/tm2/pkg/crypto/bip39" "github.com/gnolang/gno/tm2/pkg/crypto/keys" "github.com/gnolang/gno/tm2/pkg/crypto/keys/client" - "github.com/gnolang/gno/tm2/pkg/log" + tm2Log "github.com/gnolang/gno/tm2/pkg/log" "github.com/gnolang/gno/tm2/pkg/std" "github.com/rogpeppe/go-internal/testscript" + "go.uber.org/zap/zapcore" ) const numTestAccounts int = 4 @@ -104,11 +108,11 @@ func setupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params { } // setup logger - var logger log.Logger + var logger *slog.Logger { - logger = log.NewNopLogger() - if persistWorkDir || os.Getenv("LOG_DIR") != "" { - logname := fmt.Sprintf("gnoland-%s.log", sid) + logger = tm2Log.NewNoopLogger() + if persistWorkDir || os.Getenv("LOG_PATH_DIR") != "" { + logname := fmt.Sprintf("txtar-gnoland-%s.log", sid) logger, err = getTestingLogger(env, logname) if err != nil { return fmt.Errorf("unable to setup logger: %w", err) @@ -149,8 +153,8 @@ func setupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params { return } - logger := ts.Value("_logger").(log.Logger) // grab logger - sid := getNodeSID(ts) // grab session id + logger := ts.Value("_logger").(*slog.Logger) // grab logger + sid := getNodeSID(ts) // grab session id var cmd string cmd, args = args[0], args[1:] @@ -208,8 +212,8 @@ func setupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params { tsValidateError(ts, "gnoland "+cmd, neg, err) }, "gnokey": func(ts *testscript.TestScript, neg bool, args []string) { - logger := ts.Value("_logger").(log.Logger) // grab logger - sid := ts.Getenv("SID") // grab session id + logger := ts.Value("_logger").(*slog.Logger) // grab logger + sid := ts.Getenv("SID") // grab session id // Setup IO command io := commands.NewTestIO() @@ -232,8 +236,8 @@ func setupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params { headerlog := fmt.Sprintf("%.02d!EXEC_GNOKEY", n.nGnoKeyExec) // Log the command inside gnoland logger, so we can better scope errors. - logger.Info(headerlog, strings.Join(args, " ")) - defer logger.Info(headerlog, "END") + logger.Info(headerlog, "args", strings.Join(args, " ")) + defer logger.Info(headerlog, "delimiter", "END") } // Inject default argument, if duplicate @@ -281,22 +285,22 @@ func nodeIsRunning(nodes map[string]*testNode, sid string) bool { return ok } -func getTestingLogger(env *testscript.Env, logname string) (log.Logger, error) { +func getTestingLogger(env *testscript.Env, logname string) (*slog.Logger, error) { var path string - if logdir := os.Getenv("LOG_DIR"); logdir != "" { + if logdir := os.Getenv("LOG_PATH_DIR"); logdir != "" { if err := os.MkdirAll(logdir, 0o755); err != nil { return nil, fmt.Errorf("unable to make log directory %q", logdir) } var err error if path, err = filepath.Abs(filepath.Join(logdir, logname)); err != nil { - return nil, fmt.Errorf("uanble to get absolute path of logdir %q", logdir) + return nil, fmt.Errorf("unable to get absolute path of logdir %q", logdir) } } else if workdir := env.Getenv("WORK"); workdir != "" { path = filepath.Join(workdir, logname) } else { - return log.NewNopLogger(), nil + return tm2Log.NewNoopLogger(), nil } f, err := os.Create(path) @@ -310,21 +314,18 @@ func getTestingLogger(env *testscript.Env, logname string) (log.Logger, error) { } }) - logger := log.NewTMLogger(f) - switch level := os.Getenv("LOG_LEVEL"); strings.ToLower(level) { - case "error": - logger.SetLevel(log.LevelError) - case "debug": - logger.SetLevel(log.LevelDebug) - case "info": - logger.SetLevel(log.LevelInfo) - case "": - default: - return nil, fmt.Errorf("invalid log level %q", level) + // Initialize the logger + logLevel, err := zapcore.ParseLevel(strings.ToLower(os.Getenv("LOG_LEVEL"))) + if err != nil { + return nil, fmt.Errorf("unable to parse log level, %w", err) } - env.T().Log("starting logger: %q", path) - return logger, nil + // Build zap logger for testing + zapLogger := log.NewZapTestingLogger(f, logLevel) + env.Defer(func() { zapLogger.Sync() }) + + env.T().Log("starting logger", path) + return log.ZapLoggerToSlog(zapLogger), nil } func tsValidateError(ts *testscript.TestScript, cmd string, neg bool, err error) { diff --git a/gno.land/pkg/integration/testing_node.go b/gno.land/pkg/integration/testing_node.go index 4705f4e3d73..b0aa9f7c2af 100644 --- a/gno.land/pkg/integration/testing_node.go +++ b/gno.land/pkg/integration/testing_node.go @@ -4,13 +4,14 @@ import ( "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" "github.com/gnolang/gno/tm2/pkg/bft/node" bft "github.com/gnolang/gno/tm2/pkg/bft/types" "github.com/gnolang/gno/tm2/pkg/crypto" - "github.com/gnolang/gno/tm2/pkg/log" "github.com/gnolang/gno/tm2/pkg/std" "github.com/jaekwon/testify/require" ) @@ -23,7 +24,7 @@ const ( // TestingInMemoryNode initializes and starts an in-memory node for testing. // It returns the node instance and its RPC remote address. -func TestingInMemoryNode(t TestingTS, logger log.Logger, config *gnoland.InMemoryNodeConfig) (*node.Node, string) { +func TestingInMemoryNode(t TestingTS, logger *slog.Logger, config *gnoland.InMemoryNodeConfig) (*node.Node, string) { node, err := gnoland.NewInMemoryNode(logger, config) require.NoError(t, err) diff --git a/gno.land/pkg/log/format.go b/gno.land/pkg/log/format.go new file mode 100644 index 00000000000..1272ffe23b6 --- /dev/null +++ b/gno.land/pkg/log/format.go @@ -0,0 +1,14 @@ +package log + +// Format is the log format +type Format string + +const ( + JSONFormat Format = "json" + ConsoleFormat Format = "console" + TestingFormat Format = "testing" +) + +func (f Format) String() string { + return string(f) +} diff --git a/gno.land/pkg/log/zap.go b/gno.land/pkg/log/zap.go new file mode 100644 index 00000000000..a68e034eab6 --- /dev/null +++ b/gno.land/pkg/log/zap.go @@ -0,0 +1,76 @@ +package log + +import ( + "io" + + "golang.org/x/exp/slog" + + "go.uber.org/zap" + "go.uber.org/zap/exp/zapslog" + "go.uber.org/zap/zapcore" +) + +// NewZapLoggerFn is the zap logger init declaration +type NewZapLoggerFn func(w io.Writer, level zapcore.Level, opts ...zap.Option) *zap.Logger + +// GetZapLoggerFn returns the appropriate init callback +// for the zap logger, given the requested format +func GetZapLoggerFn(format Format) NewZapLoggerFn { + switch format { + case JSONFormat: + return NewZapJSONLogger + case TestingFormat: + return NewZapTestingLogger + default: + return NewZapConsoleLogger + } +} + +// NewZapJSONLogger creates a zap logger with a JSON encoder for production use. +func NewZapJSONLogger(w io.Writer, level zapcore.Level, opts ...zap.Option) *zap.Logger { + // Build encoder config + jsonConfig := zap.NewProductionEncoderConfig() + + // Build encoder + enc := zapcore.NewJSONEncoder(jsonConfig) + return NewZapLogger(enc, w, level, opts...) +} + +// NewZapConsoleLogger creates a zap logger with a console encoder for development use. +func NewZapConsoleLogger(w io.Writer, level zapcore.Level, opts ...zap.Option) *zap.Logger { + // Build encoder config + consoleConfig := zap.NewDevelopmentEncoderConfig() + consoleConfig.EncodeLevel = stableWidthCapitalColorLevelEncoder + consoleConfig.EncodeName = stableWidthNameEncoder + + // Build encoder + enc := zapcore.NewConsoleEncoder(consoleConfig) + return NewZapLogger(enc, w, level, opts...) +} + +// NewZapTestingLogger creates a zap logger with a console encoder optimized for testing. +func NewZapTestingLogger(w io.Writer, level zapcore.Level, opts ...zap.Option) *zap.Logger { + // Build encoder config + consoleConfig := zap.NewDevelopmentEncoderConfig() + consoleConfig.TimeKey = "" + consoleConfig.EncodeLevel = stableWidthCapitalLevelEncoder + consoleConfig.EncodeName = stableWidthNameEncoder + + // Build encoder + enc := zapcore.NewConsoleEncoder(consoleConfig) + return NewZapLogger(enc, w, level, opts...) +} + +// NewZapLogger creates a new zap logger instance, for the given level, writer and zap encoder. +func NewZapLogger(enc zapcore.Encoder, w io.Writer, level zapcore.Level, opts ...zap.Option) *zap.Logger { + ws := zapcore.AddSync(w) + + // Create zap core + core := zapcore.NewCore(enc, ws, zap.NewAtomicLevelAt(level)) + return zap.New(core, 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())) +} diff --git a/gno.land/pkg/log/zap_encoder.go b/gno.land/pkg/log/zap_encoder.go new file mode 100644 index 00000000000..a8459197301 --- /dev/null +++ b/gno.land/pkg/log/zap_encoder.go @@ -0,0 +1,48 @@ +package log + +import ( + "fmt" + + "go.uber.org/zap/zapcore" +) + +func stableWidthCapitalLevelEncoder(l zapcore.Level, enc zapcore.PrimitiveArrayEncoder) { + enc.AppendString(fmt.Sprintf("%-5s", l.CapitalString())) +} + +func stableWidthNameEncoder(loggerName string, enc zapcore.PrimitiveArrayEncoder) { + enc.AppendString(fmt.Sprintf("%-18s", loggerName)) +} + +//nolint:varcheck,deadcode // we don't care if it's unused +const ( + black uint8 = iota + 30 + red + green + yellow + blue + magenta + cyan + white +) + +func stableWidthCapitalColorLevelEncoder(l zapcore.Level, enc zapcore.PrimitiveArrayEncoder) { + switch l { + case zapcore.DebugLevel: + enc.AppendString(fmt.Sprintf("\x1b[%dm%s\x1b[0m", magenta, "DEBUG")) + case zapcore.InfoLevel: + enc.AppendString(fmt.Sprintf("\x1b[%dm%s\x1b[0m", blue, "INFO ")) + case zapcore.WarnLevel: + enc.AppendString(fmt.Sprintf("\x1b[%dm%s\x1b[0m", yellow, "WARN ")) + case zapcore.ErrorLevel: + enc.AppendString(fmt.Sprintf("\x1b[%dm%s\x1b[0m", red, "ERROR")) + case zapcore.DPanicLevel: + enc.AppendString(fmt.Sprintf("\x1b[%dm%s\x1b[0m", red, "DPANIC")) + case zapcore.PanicLevel: + enc.AppendString(fmt.Sprintf("\x1b[%dm%s\x1b[0m", red, "PANIC")) + case zapcore.FatalLevel: + enc.AppendString(fmt.Sprintf("\x1b[%dm%s\x1b[0m", red, "FATAL")) + default: + enc.AppendString(fmt.Sprintf("\x1b[%dm%s\x1b[0m", red, l.CapitalString())) + } +} diff --git a/gno.land/pkg/sdk/vm/common_test.go b/gno.land/pkg/sdk/vm/common_test.go index 60a92906cb6..8a75697115f 100644 --- a/gno.land/pkg/sdk/vm/common_test.go +++ b/gno.land/pkg/sdk/vm/common_test.go @@ -35,7 +35,7 @@ func setupTestEnv() testEnv { ms.MountStoreWithDB(iavlCapKey, iavl.StoreConstructor, db) ms.LoadLatestVersion() - ctx := sdk.NewContext(sdk.RunTxModeDeliver, ms, &bft.Header{ChainID: "test-chain-id"}, log.NewNopLogger()) + ctx := sdk.NewContext(sdk.RunTxModeDeliver, ms, &bft.Header{ChainID: "test-chain-id"}, log.NewNoopLogger()) acck := authm.NewAccountKeeper(iavlCapKey, std.ProtoBaseAccount) bank := bankm.NewBankKeeper(acck) stdlibsDir := filepath.Join("..", "..", "..", "..", "gnovm", "stdlibs") diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index b0ae2180c36..b4d29c99fec 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -283,7 +283,7 @@ func (vm *VMKeeper) Call(ctx sdk.Context, msg MsgCall) (res string, err error) { m.Release() }() rtvs := m.Eval(xn) - ctx.Logger().Info("CPUCYCLES call: ", m.Cycles) + ctx.Logger().Info("CPUCYCLES call", "num-cycles", m.Cycles) for i, rtv := range rtvs { res = res + rtv.String() if i < len(rtvs)-1 { @@ -363,7 +363,9 @@ func (vm *VMKeeper) Run(ctx sdk.Context, msg MsgRun) (res string, err error) { m2.Release() }() m2.RunMain() - ctx.Logger().Info("CPUCYCLES call: ", m2.Cycles) + ctx.Logger().Info("CPUCYCLES call", + "cycles", m2.Cycles, + ) res = buf.String() return res, nil } diff --git a/gnovm/Makefile b/gnovm/Makefile index cc7154492d8..599ca58cd39 100644 --- a/gnovm/Makefile +++ b/gnovm/Makefile @@ -34,6 +34,11 @@ fmt: $(rundep) mvdan.cc/gofumpt $(GOFMT_FLAGS) . $(rundep) mvdan.cc/gofumpt $(GOFMT_FLAGS) `find stdlibs -name "*.gno"` +.PHONY: imports +GOIMPORTS_FLAGS ?= -w +imports: + $(rundep) golang.org/x/tools/cmd/goimports $(GOIMPORTS_FLAGS) . + ######################################## # Test suite .PHONY: test diff --git a/go.mod b/go.mod index 3c83a12ec3c..49265300aec 100644 --- a/go.mod +++ b/go.mod @@ -30,8 +30,11 @@ require ( github.com/stretchr/testify v1.8.4 github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c go.etcd.io/bbolt v1.3.8 - go.uber.org/multierr v1.9.0 + go.uber.org/multierr v1.10.0 + go.uber.org/zap v1.24.0 + go.uber.org/zap/exp v0.1.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 @@ -67,7 +70,7 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/rivo/uniseg v0.4.3 // indirect go.opencensus.io v0.22.5 // indirect - go.uber.org/atomic v1.7.0 // 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 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect diff --git a/go.sum b/go.sum index 13cee4401f9..8d62638eacc 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,7 @@ 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= @@ -107,8 +108,8 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= 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= @@ -199,7 +200,6 @@ 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/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -217,10 +217,15 @@ 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.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= -go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= +go.uber.org/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/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= 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= @@ -230,6 +235,8 @@ 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= diff --git a/misc/Makefile b/misc/Makefile index 84acc40e387..44dd9b2c98a 100644 --- a/misc/Makefile +++ b/misc/Makefile @@ -26,3 +26,11 @@ GOTEST_FLAGS ?= -v -p 1 -timeout=30m .PHONY: _test.genstd _test.genstd: go test ./genstd/... $(GOTEST_FLAGS) + +.PHONY: tidy +VERIFY_MOD_SUMS ?= false +tidy: + # Give execute permissions + chmod +x ./mod_tidy.sh + # Tidy go mods + VERIFY_MOD_SUMS=$(VERIFY_MOD_SUMS) ./mod_tidy.sh diff --git a/misc/devdeps/deps.go b/misc/devdeps/deps.go index 3454e5b13f6..7ac068c71ac 100644 --- a/misc/devdeps/deps.go +++ b/misc/devdeps/deps.go @@ -11,6 +11,9 @@ import ( // required to generate String method _ "golang.org/x/tools/cmd/stringer" + // required for import formatting + _ "golang.org/x/tools/cmd/goimports" + // required for formatting, linting, pls. _ "golang.org/x/tools/gopls" _ "mvdan.cc/gofumpt" diff --git a/misc/loop/go.mod b/misc/loop/go.mod index 1dfc778e000..7b124c7dc86 100644 --- a/misc/loop/go.mod +++ b/misc/loop/go.mod @@ -28,6 +28,7 @@ require ( github.com/golang/snappy v0.0.4 // indirect github.com/google/flatbuffers v1.12.1 // indirect github.com/gorilla/websocket v1.5.1 // indirect + github.com/jaekwon/testify v1.6.1 // indirect github.com/jmhodges/levigo v1.0.0 // indirect github.com/klauspost/compress v1.12.3 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect @@ -35,19 +36,24 @@ require ( github.com/pelletier/go-toml v1.9.5 // indirect github.com/peterbourgon/ff/v3 v3.4.0 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rs/cors v1.10.1 // indirect + github.com/stretchr/testify v1.8.4 // indirect github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect go.etcd.io/bbolt v1.3.8 // indirect go.opencensus.io v0.22.5 // indirect go.uber.org/multierr v1.10.0 // indirect 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 golang.org/x/term v0.16.0 // indirect golang.org/x/tools v0.17.0 // indirect google.golang.org/protobuf v1.31.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) replace github.com/gnolang/gno => ../../ diff --git a/misc/loop/go.sum b/misc/loop/go.sum index d67564b4c46..4a09c040cf5 100644 --- a/misc/loop/go.sum +++ b/misc/loop/go.sum @@ -99,8 +99,8 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= @@ -108,6 +108,7 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jaekwon/testify v1.6.1 h1:4AtAJcR9GzXN5W4DdY7ie74iCPiJV1JJUJL90t2ZUyw= +github.com/jaekwon/testify v1.6.1/go.mod h1:Oun0RXIHI7osufabQ60i4Lqkj0GXLbqI1I7kgzBNm1U= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= @@ -119,8 +120,10 @@ github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6 github.com/klauspost/compress v1.12.3 h1:G5AfA94pHPysR56qqrkO2pxEexdDzrpFJ6yt/VqWxVU= 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/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/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= 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= @@ -166,8 +169,10 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 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= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c h1:g+WoO5jjkqGAzHWCjJB1zZfXPIAaDpzXIEJ0eS6B5Ok= github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8= @@ -184,6 +189,8 @@ 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= +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= @@ -192,6 +199,8 @@ 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= @@ -274,6 +283,7 @@ google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 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/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= diff --git a/misc/mod_tidy.sh b/misc/mod_tidy.sh new file mode 100755 index 00000000000..eb65bf8ee25 --- /dev/null +++ b/misc/mod_tidy.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash + +# This script finds and tidies all go.mod +# files recursively from the repository root and +# optionally verifies the last echo based on an +# environment variable VERIFY_MOD_SUMS + +set -e # exit on error + +# CD into the repo root +cd .. + +# Check for the verify argument +verify=${VERIFY_MOD_SUMS:-false} + +# Find all go.mod files +gomods=$(find . -type f -name go.mod) + +if $verify; then + # Calculate sums for all go.mod files + sums=$(shasum $gomods) +fi + +# Tidy each go.mod file +for modfile in $gomods; do + dir=$(dirname "$modfile") + + # Run go mod tidy in the directory + (cd "$dir" && go mod tidy -v) || exit 1 +done + +# Optionally verify the sums +if $verify; then + echo "Verifying sums..." + echo "$sums" | shasum -c +else + echo "Skipping sum verification" +fi diff --git a/tm2/Makefile b/tm2/Makefile index a5a8b8ade0d..0fa231415b2 100644 --- a/tm2/Makefile +++ b/tm2/Makefile @@ -27,6 +27,11 @@ GOFMT_FLAGS ?= -w fmt: $(rundep) mvdan.cc/gofumpt $(GOFMT_FLAGS) . +.PHONY: imports +GOIMPORTS_FLAGS ?= -w +imports: + $(rundep) golang.org/x/tools/cmd/goimports $(GOIMPORTS_FLAGS) . + .PHONY: lint lint: $(rundep) github.com/golangci/golangci-lint/cmd/golangci-lint run --config ../.github/golangci.yml ./... diff --git a/tm2/pkg/amino/tests/pb/tests.pb.go b/tm2/pkg/amino/tests/pb/tests.pb.go index bff4f37f862..6776f5ecb57 100644 --- a/tm2/pkg/amino/tests/pb/tests.pb.go +++ b/tm2/pkg/amino/tests/pb/tests.pb.go @@ -7,13 +7,14 @@ package pb import ( + reflect "reflect" + sync "sync" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" anypb "google.golang.org/protobuf/types/known/anypb" durationpb "google.golang.org/protobuf/types/known/durationpb" timestamppb "google.golang.org/protobuf/types/known/timestamppb" - reflect "reflect" - sync "sync" ) const ( diff --git a/tm2/pkg/amino/tests/proto3/proto/compat.pb.go b/tm2/pkg/amino/tests/proto3/proto/compat.pb.go index 9f38d4ef589..b03a9273125 100644 --- a/tm2/pkg/amino/tests/proto3/proto/compat.pb.go +++ b/tm2/pkg/amino/tests/proto3/proto/compat.pb.go @@ -7,11 +7,12 @@ package proto3 import ( + reflect "reflect" + sync "sync" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" timestamppb "google.golang.org/protobuf/types/known/timestamppb" - reflect "reflect" - sync "sync" ) const ( diff --git a/tm2/pkg/bft/abci/example/kvstore/persistent_kvstore.go b/tm2/pkg/bft/abci/example/kvstore/persistent_kvstore.go index 2e0adb5656f..5042fcf9313 100644 --- a/tm2/pkg/bft/abci/example/kvstore/persistent_kvstore.go +++ b/tm2/pkg/bft/abci/example/kvstore/persistent_kvstore.go @@ -6,6 +6,8 @@ import ( "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" @@ -31,7 +33,7 @@ type PersistentKVStoreApplication struct { // validator set ValSetChanges []abci.ValidatorUpdate - logger log.Logger + logger *slog.Logger } func NewPersistentKVStoreApplication(dbDir string) *PersistentKVStoreApplication { @@ -45,11 +47,11 @@ func NewPersistentKVStoreApplication(dbDir string) *PersistentKVStoreApplication return &PersistentKVStoreApplication{ app: &KVStoreApplication{state: state}, - logger: log.NewNopLogger(), + logger: log.NewNoopLogger(), } } -func (app *PersistentKVStoreApplication) SetLogger(l log.Logger) { +func (app *PersistentKVStoreApplication) SetLogger(l *slog.Logger) { app.logger = l } diff --git a/tm2/pkg/bft/blockchain/pool.go b/tm2/pkg/bft/blockchain/pool.go index a44926ec7b2..a3a24d265a8 100644 --- a/tm2/pkg/bft/blockchain/pool.go +++ b/tm2/pkg/bft/blockchain/pool.go @@ -8,6 +8,8 @@ import ( "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" @@ -419,7 +421,7 @@ func (pool *BlockPool) debug() string { return str } -//------------------------------------- +// ------------------------------------- type bpPeer struct { pool *BlockPool @@ -431,7 +433,7 @@ type bpPeer struct { timeout *time.Timer didTimeout bool - logger log.Logger + logger *slog.Logger } func newBPPeer(pool *BlockPool, peerID p2p.ID, height int64) *bpPeer { @@ -440,12 +442,12 @@ func newBPPeer(pool *BlockPool, peerID p2p.ID, height int64) *bpPeer { id: peerID, height: height, numPending: 0, - logger: log.NewNopLogger(), + logger: log.NewNoopLogger(), } return peer } -func (peer *bpPeer) setLogger(l log.Logger) { +func (peer *bpPeer) setLogger(l *slog.Logger) { peer.logger = l } @@ -491,7 +493,7 @@ func (peer *bpPeer) onTimeout() { peer.didTimeout = true } -//------------------------------------- +// ------------------------------------- type bpRequester struct { service.BaseService diff --git a/tm2/pkg/bft/blockchain/pool_test.go b/tm2/pkg/bft/blockchain/pool_test.go index 39c17d8428f..a4d5636d5e3 100644 --- a/tm2/pkg/bft/blockchain/pool_test.go +++ b/tm2/pkg/bft/blockchain/pool_test.go @@ -79,7 +79,7 @@ func TestBlockPoolBasic(t *testing.T) { errorsCh := make(chan peerError, 1000) requestsCh := make(chan BlockRequest, 1000) pool := NewBlockPool(start, requestsCh, errorsCh) - pool.SetLogger(log.TestingLogger()) + pool.SetLogger(log.NewNoopLogger()) err := pool.Start() if err != nil { @@ -137,7 +137,7 @@ func TestBlockPoolTimeout(t *testing.T) { errorsCh := make(chan peerError, 1000) requestsCh := make(chan BlockRequest, 1000) pool := NewBlockPool(start, requestsCh, errorsCh) - pool.SetLogger(log.TestingLogger()) + pool.SetLogger(log.NewTestingLogger(t)) err := pool.Start() if err != nil { t.Error(err) @@ -203,7 +203,7 @@ func TestBlockPoolRemovePeer(t *testing.T) { errorsCh := make(chan peerError) pool := NewBlockPool(1, requestsCh, errorsCh) - pool.SetLogger(log.TestingLogger()) + pool.SetLogger(log.NewTestingLogger(t)) err := pool.Start() require.NoError(t, err) defer pool.Stop() diff --git a/tm2/pkg/bft/blockchain/reactor.go b/tm2/pkg/bft/blockchain/reactor.go index 007f7ccfb1c..bf5f7ea71b3 100644 --- a/tm2/pkg/bft/blockchain/reactor.go +++ b/tm2/pkg/bft/blockchain/reactor.go @@ -6,11 +6,12 @@ import ( "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" "github.com/gnolang/gno/tm2/pkg/bft/types" - "github.com/gnolang/gno/tm2/pkg/log" "github.com/gnolang/gno/tm2/pkg/p2p" ) @@ -102,7 +103,7 @@ func NewBlockchainReactor(state sm.State, blockExec *sm.BlockExecutor, store *st } // SetLogger implements cmn.Service by setting the logger on reactor and pool. -func (bcR *BlockchainReactor) SetLogger(l log.Logger) { +func (bcR *BlockchainReactor) SetLogger(l *slog.Logger) { bcR.BaseService.Logger = l bcR.pool.Logger = l } diff --git a/tm2/pkg/bft/blockchain/reactor_test.go b/tm2/pkg/bft/blockchain/reactor_test.go index c9ff0ff5f93..982c29033fa 100644 --- a/tm2/pkg/bft/blockchain/reactor_test.go +++ b/tm2/pkg/bft/blockchain/reactor_test.go @@ -6,6 +6,10 @@ import ( "testing" "time" + "golang.org/x/exp/slog" + + "github.com/stretchr/testify/assert" + abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" cfg "github.com/gnolang/gno/tm2/pkg/bft/config" "github.com/gnolang/gno/tm2/pkg/bft/mempool/mock" @@ -19,7 +23,6 @@ import ( "github.com/gnolang/gno/tm2/pkg/log" "github.com/gnolang/gno/tm2/pkg/p2p" "github.com/gnolang/gno/tm2/pkg/testutils" - "github.com/stretchr/testify/assert" ) var config *cfg.Config @@ -49,7 +52,7 @@ type BlockchainReactorPair struct { app proxy.AppConns } -func newBlockchainReactor(logger log.Logger, genDoc *types.GenesisDoc, privVals []types.PrivValidator, maxBlockHeight int64) BlockchainReactorPair { +func newBlockchainReactor(logger *slog.Logger, genDoc *types.GenesisDoc, privVals []types.PrivValidator, maxBlockHeight int64) BlockchainReactorPair { if len(privVals) != 1 { panic("only support one validator") } @@ -76,7 +79,7 @@ func newBlockchainReactor(logger log.Logger, genDoc *types.GenesisDoc, privVals // pool.height is determined from the store. fastSync := true db := dbm.NewMemDB() - blockExec := sm.NewBlockExecutor(db, log.TestingLogger(), proxyApp.Consensus(), mock.Mempool{}) + blockExec := sm.NewBlockExecutor(db, logger, proxyApp.Consensus(), mock.Mempool{}) sm.SaveState(db, state) // let's add some blocks in @@ -124,8 +127,8 @@ func TestNoBlockResponse(t *testing.T) { reactorPairs := make([]BlockchainReactorPair, 2) - reactorPairs[0] = newBlockchainReactor(log.TestingLogger(), genDoc, privVals, maxBlockHeight) - reactorPairs[1] = newBlockchainReactor(log.TestingLogger(), genDoc, privVals, 0) + reactorPairs[0] = newBlockchainReactor(log.NewTestingLogger(t), genDoc, privVals, maxBlockHeight) + reactorPairs[1] = newBlockchainReactor(log.NewTestingLogger(t), genDoc, privVals, 0) p2p.MakeConnectedSwitches(config.P2P, 2, func(i int, s *p2p.Switch) *p2p.Switch { s.AddReactor("BLOCKCHAIN", reactorPairs[i].reactor) @@ -185,7 +188,7 @@ func TestFlappyBadBlockStopsPeer(t *testing.T) { maxBlockHeight := int64(148) - otherChain := newBlockchainReactor(log.TestingLogger(), genDoc, privVals, maxBlockHeight) + otherChain := newBlockchainReactor(log.NewNoopLogger(), genDoc, privVals, maxBlockHeight) defer func() { otherChain.reactor.Stop() otherChain.app.Stop() @@ -193,10 +196,10 @@ func TestFlappyBadBlockStopsPeer(t *testing.T) { reactorPairs := make([]BlockchainReactorPair, 4) - reactorPairs[0] = newBlockchainReactor(log.TestingLogger(), genDoc, privVals, maxBlockHeight) - reactorPairs[1] = newBlockchainReactor(log.TestingLogger(), genDoc, privVals, 0) - reactorPairs[2] = newBlockchainReactor(log.TestingLogger(), genDoc, privVals, 0) - reactorPairs[3] = newBlockchainReactor(log.TestingLogger(), genDoc, privVals, 0) + reactorPairs[0] = newBlockchainReactor(log.NewNoopLogger(), genDoc, privVals, maxBlockHeight) + reactorPairs[1] = newBlockchainReactor(log.NewNoopLogger(), genDoc, privVals, 0) + reactorPairs[2] = newBlockchainReactor(log.NewNoopLogger(), genDoc, privVals, 0) + reactorPairs[3] = newBlockchainReactor(log.NewNoopLogger(), genDoc, privVals, 0) switches := p2p.MakeConnectedSwitches(config.P2P, 4, func(i int, s *p2p.Switch) *p2p.Switch { s.AddReactor("BLOCKCHAIN", reactorPairs[i].reactor) @@ -224,7 +227,7 @@ func TestFlappyBadBlockStopsPeer(t *testing.T) { // mark reactorPairs[3] is an invalid peer reactorPairs[3].reactor.store = otherChain.reactor.store - lastReactorPair := newBlockchainReactor(log.TestingLogger(), genDoc, privVals, 0) + lastReactorPair := newBlockchainReactor(log.NewNoopLogger(), genDoc, privVals, 0) reactorPairs = append(reactorPairs, lastReactorPair) switches = append(switches, p2p.MakeConnectedSwitches(config.P2P, 1, func(i int, s *p2p.Switch) *p2p.Switch { diff --git a/tm2/pkg/bft/config/config.go b/tm2/pkg/bft/config/config.go index e5c331b448c..3cf6afc147b 100644 --- a/tm2/pkg/bft/config/config.go +++ b/tm2/pkg/bft/config/config.go @@ -4,6 +4,7 @@ import ( "fmt" "os" "path/filepath" + "regexp" "dario.cat/mergo" abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" @@ -16,6 +17,35 @@ import ( p2p "github.com/gnolang/gno/tm2/pkg/p2p/config" ) +var ( + errInvalidMoniker = errors.New("moniker not set") + errInvalidDBBackend = errors.New("invalid DB backend") + errInvalidDBPath = errors.New("invalid DB path") + errInvalidGenesisPath = errors.New("invalid genesis path") + errInvalidPrivValidatorKeyPath = errors.New("invalid private validator key path") + errInvalidPrivValidatorStatePath = errors.New("invalid private validator state file path") + errInvalidABCIMechanism = errors.New("invalid ABCI mechanism") + errInvalidPrivValidatorListenAddress = errors.New("invalid PrivValidator listen address") + errInvalidProfListenAddress = errors.New("invalid profiling server listen address") + errInvalidNodeKeyPath = errors.New("invalid p2p node key path") +) + +const ( + levelDBName = "goleveldb" + clevelDBName = "cleveldb" + boltDBName = "boltdb" +) + +const ( + localABCI = "local" + socketABCI = "socket" +) + +// Regular expression for TCP or UNIX socket address +// TCP address: host:port (IPv4 example) +// UNIX address: unix:// followed by the path +var tcpUnixAddressRegex = regexp.MustCompile(`^(?:[0-9]{1,3}(\.[0-9]{1,3}){3}:[0-9]+|unix://.+)`) + // Config defines the top level configuration for a Tendermint node type Config struct { // Top level options use an anonymous struct @@ -171,13 +201,6 @@ func (cfg *Config) ValidateBasic() error { // ----------------------------------------------------------------------------- // BaseConfig -const ( - // LogFormatPlain is a format for colored text - LogFormatPlain = "plain" - // LogFormatJSON is a format for json output - LogFormatJSON = "json" -) - var ( defaultConfigDir = "config" defaultDataDir = "data" @@ -237,12 +260,6 @@ type BaseConfig struct { // Database directory DBPath string `toml:"db_dir" comment:"Database directory"` - // Output level for logging - LogLevel string `toml:"log_level" comment:"Output level for logging, including package level options"` - - // Output format: 'plain' (colored text) or 'json' - LogFormat string `toml:"log_format" comment:"Output format: 'plain' (colored text) or 'json'"` - // Path to the JSON file containing the initial validator set and other meta data Genesis string `toml:"genesis_file" comment:"Path to the JSON file containing the initial validator set and other meta data"` @@ -280,8 +297,6 @@ func DefaultBaseConfig() BaseConfig { Moniker: defaultMoniker, ProxyApp: "tcp://127.0.0.1:26658", ABCI: "socket", - LogLevel: DefaultPackageLogLevels(), - LogFormat: LogFormatPlain, ProfListenAddress: "", FastSyncMode: true, FilterPeers: false, @@ -329,28 +344,6 @@ func (cfg BaseConfig) DBDir() string { return join(cfg.RootDir, cfg.DBPath) } -// ValidateBasic performs basic validation (checking param bounds, etc.) and -// returns an error if any check fails. -func (cfg BaseConfig) ValidateBasic() error { - switch cfg.LogFormat { - case LogFormatPlain, LogFormatJSON: - default: - return errors.New("unknown log_format (must be 'plain' or 'json')") - } - return nil -} - -// DefaultLogLevel returns a default log level of "error" -func DefaultLogLevel() string { - return "error" -} - -// DefaultPackageLogLevels returns a default log level setting so all packages -// log at "error", while the `state` and `main` packages log at "info" -func DefaultPackageLogLevels() string { - return fmt.Sprintf("main:info,state:info,*:%s", DefaultLogLevel()) -} - var defaultMoniker = getDefaultMoniker() // getDefaultMoniker returns a default moniker, which is the host name. If runtime @@ -362,3 +355,63 @@ func getDefaultMoniker() string { } return moniker } + +// ValidateBasic performs basic validation (checking param bounds, etc.) and +// returns an error if any check fails. +func (cfg BaseConfig) ValidateBasic() error { + // Verify the moniker + if cfg.Moniker == "" { + return errInvalidMoniker + } + + // Verify the DB backend + if cfg.DBBackend != levelDBName && + cfg.DBBackend != clevelDBName && + cfg.DBBackend != boltDBName { + return errInvalidDBBackend + } + + // Verify the DB path is set + if cfg.DBPath == "" { + return errInvalidDBPath + } + + // Verify the genesis path is set + if cfg.Genesis == "" { + return errInvalidGenesisPath + } + + // Verify the validator private key path is set + if cfg.PrivValidatorKey == "" { + return errInvalidPrivValidatorKeyPath + } + + // Verify the validator state file path is set + if cfg.PrivValidatorState == "" { + return errInvalidPrivValidatorStatePath + } + + // Verify the PrivValidator listen address + if cfg.PrivValidatorListenAddr != "" && + !tcpUnixAddressRegex.MatchString(cfg.PrivValidatorListenAddr) { + return errInvalidPrivValidatorListenAddress + } + + // Verify the p2p private key exists + if cfg.NodeKey == "" { + return errInvalidNodeKeyPath + } + + // Verify the correct ABCI mechanism is set + if cfg.ABCI != localABCI && + cfg.ABCI != socketABCI { + return errInvalidABCIMechanism + } + + // Verify the profiling listen address + if cfg.ProfListenAddress != "" && !tcpUnixAddressRegex.MatchString(cfg.ProfListenAddress) { + return errInvalidProfListenAddress + } + + return nil +} diff --git a/tm2/pkg/bft/config/config_test.go b/tm2/pkg/bft/config/config_test.go index 1ed58767f2b..adeeade26b3 100644 --- a/tm2/pkg/bft/config/config_test.go +++ b/tm2/pkg/bft/config/config_test.go @@ -88,3 +88,105 @@ func TestConfig_LoadOrMakeConfigWithOptions(t *testing.T) { assert.Equal(t, cfg, loadedCfg) }) } + +func TestConfig_ValidateBaseConfig(t *testing.T) { + t.Parallel() + + t.Run("valid default config", func(t *testing.T) { + t.Parallel() + + c := DefaultConfig() + + assert.NoError(t, c.BaseConfig.ValidateBasic()) + }) + + t.Run("invalid moniker", func(t *testing.T) { + t.Parallel() + + c := DefaultConfig() + c.Moniker = "" + + assert.ErrorIs(t, c.BaseConfig.ValidateBasic(), errInvalidMoniker) + }) + + t.Run("invalid DB backend", func(t *testing.T) { + t.Parallel() + + c := DefaultConfig() + c.DBBackend = "totally valid backend" + + assert.ErrorIs(t, c.BaseConfig.ValidateBasic(), errInvalidDBBackend) + }) + + t.Run("DB path not set", func(t *testing.T) { + t.Parallel() + + c := DefaultConfig() + c.DBPath = "" + + assert.ErrorIs(t, c.BaseConfig.ValidateBasic(), errInvalidDBPath) + }) + + t.Run("genesis path not set", func(t *testing.T) { + t.Parallel() + + c := DefaultConfig() + c.Genesis = "" + + assert.ErrorIs(t, c.BaseConfig.ValidateBasic(), errInvalidGenesisPath) + }) + + t.Run("priv validator key path not set", func(t *testing.T) { + t.Parallel() + + c := DefaultConfig() + c.PrivValidatorKey = "" + + assert.ErrorIs(t, c.BaseConfig.ValidateBasic(), errInvalidPrivValidatorKeyPath) + }) + + t.Run("priv validator state path not set", func(t *testing.T) { + t.Parallel() + + c := DefaultConfig() + c.PrivValidatorState = "" + + assert.ErrorIs(t, c.BaseConfig.ValidateBasic(), errInvalidPrivValidatorStatePath) + }) + + t.Run("invalid priv validator listen address", func(t *testing.T) { + t.Parallel() + + c := DefaultConfig() + c.PrivValidatorListenAddr = "beep.boop" + + assert.ErrorIs(t, c.BaseConfig.ValidateBasic(), errInvalidPrivValidatorListenAddress) + }) + + t.Run("node key path not set", func(t *testing.T) { + t.Parallel() + + c := DefaultConfig() + c.NodeKey = "" + + assert.ErrorIs(t, c.BaseConfig.ValidateBasic(), errInvalidNodeKeyPath) + }) + + t.Run("invalid ABCI mechanism", func(t *testing.T) { + t.Parallel() + + c := DefaultConfig() + c.ABCI = "hopes and dreams" + + assert.ErrorIs(t, c.BaseConfig.ValidateBasic(), errInvalidABCIMechanism) + }) + + t.Run("invalid prof listen address", func(t *testing.T) { + t.Parallel() + + c := DefaultConfig() + c.ProfListenAddress = "beep.boop" + + assert.ErrorIs(t, c.BaseConfig.ValidateBasic(), errInvalidProfListenAddress) + }) +} diff --git a/tm2/pkg/bft/consensus/common_test.go b/tm2/pkg/bft/consensus/common_test.go index ba19881aace..4a0a4eebf03 100644 --- a/tm2/pkg/bft/consensus/common_test.go +++ b/tm2/pkg/bft/consensus/common_test.go @@ -11,6 +11,8 @@ 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" @@ -23,7 +25,6 @@ import ( "github.com/gnolang/gno/tm2/pkg/bft/store" "github.com/gnolang/gno/tm2/pkg/bft/types" tmtime "github.com/gnolang/gno/tm2/pkg/bft/types/time" - "github.com/gnolang/gno/tm2/pkg/colors" "github.com/gnolang/gno/tm2/pkg/crypto" dbm "github.com/gnolang/gno/tm2/pkg/db" "github.com/gnolang/gno/tm2/pkg/events" @@ -280,7 +281,7 @@ func newConsensusStateWithConfigAndBlockStore(thisConfig *cfg.Config, state sm.S // Make Mempool mempool := mempl.NewCListMempool(thisConfig.Mempool, proxyAppConnMem, 0, state.ConsensusParams.Block.MaxTxBytes) - mempool.SetLogger(log.TestingLogger().With("module", "mempool")) + mempool.SetLogger(log.NewNoopLogger().With("module", "mempool")) if thisConfig.Consensus.WaitForTxs() { mempool.EnableTxsAvailable() } @@ -288,13 +289,13 @@ func newConsensusStateWithConfigAndBlockStore(thisConfig *cfg.Config, state sm.S // Make ConsensusState stateDB := blockDB sm.SaveState(stateDB, state) // for save height 1's validators info - blockExec := sm.NewBlockExecutor(stateDB, log.TestingLogger(), proxyAppConnCon, mempool) + blockExec := sm.NewBlockExecutor(stateDB, log.NewNoopLogger(), proxyAppConnCon, mempool) cs := NewConsensusState(thisConfig.Consensus, state, blockExec, blockStore, mempool) - cs.SetLogger(log.TestingLogger().With("module", "consensus")) + cs.SetLogger(log.NewNoopLogger().With("module", "consensus")) cs.SetPrivValidator(pv) evsw := events.NewEventSwitch() - evsw.SetLogger(log.TestingLogger().With("module", "events")) + evsw.SetLogger(log.NewNoopLogger().With("module", "events")) evsw.Start() cs.SetEventSwitch(evsw) return cs @@ -566,46 +567,13 @@ func ensureNewEventOnChannel(ch <-chan events.Event) { // ------------------------------------------------------------------------------- // consensus nets -// consensusLogger is a TestingLogger which uses a different -// color for each validator ("validator" key must exist). -func consensusLogger() log.Logger { - return log.TestingLoggerWithColorFn(func(keyvals ...interface{}) colors.Color { - for i := 0; i < len(keyvals)-1; i += 2 { - if keyvals[i] == "validator" { - num := keyvals[i+1].(int) - switch num % 8 { - case 0: - return colors.Red - case 1: - return colors.Green - case 2: - return colors.Yellow - case 3: - return colors.Blue - case 4: - return colors.Magenta - case 5: - return colors.Cyan - case 6: - return colors.White - case 7: - return colors.Gray - default: - panic("should not happen") - } - } - } - return colors.None - }).With("module", "consensus") -} - func randConsensusNet(nValidators int, testName string, tickerFunc func() TimeoutTicker, appFunc func() abci.Application, configOpts ...func(*cfg.Config), ) ([]*ConsensusState, cleanupFunc) { genDoc, privVals := randGenesisDoc(nValidators, false, 30) css := make([]*ConsensusState, nValidators) apps := make([]abci.Application, nValidators) - logger := consensusLogger() + logger := log.NewNoopLogger() configRootDirs := make([]string, 0, nValidators) for i := 0; i < nValidators; i++ { stateDB := dbm.NewMemDB() // each state needs its own db @@ -644,7 +612,7 @@ func randConsensusNetWithPeers(nValidators, nPeers int, testName string, tickerF genDoc, privVals := randGenesisDoc(nValidators, false, testMinPower) css := make([]*ConsensusState, nPeers) apps := make([]abci.Application, nPeers) - logger := consensusLogger() + logger := log.NewNoopLogger() var peer0Config *cfg.Config configRootDirs := make([]string, 0, nPeers) for i := 0; i < nPeers; i++ { @@ -775,7 +743,7 @@ func (m *mockTicker) Chan() <-chan timeoutInfo { return m.c } -func (*mockTicker) SetLogger(log.Logger) {} +func (*mockTicker) SetLogger(_ *slog.Logger) {} // ------------------------------------ diff --git a/tm2/pkg/bft/consensus/reactor.go b/tm2/pkg/bft/consensus/reactor.go index ab7f3b55e92..27ead3f08f0 100644 --- a/tm2/pkg/bft/consensus/reactor.go +++ b/tm2/pkg/bft/consensus/reactor.go @@ -6,6 +6,8 @@ import ( "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" @@ -30,7 +32,7 @@ const ( votesToContributeToBecomeGoodPeer = 10000 ) -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // ConsensusReactor defines a reactor for the consensus service. type ConsensusReactor struct { @@ -365,7 +367,7 @@ func (conR *ConsensusReactor) FastSync() bool { return conR.fastSync } -//-------------------------------------- +// -------------------------------------- // subscribeToBroadcastEvents subscribes for new round steps and votes // using internal pubsub defined on state to broadcast @@ -545,7 +547,7 @@ OUTER_LOOP: } } -func (conR *ConsensusReactor) gossipDataForCatchup(logger log.Logger, rs *cstypes.RoundState, +func (conR *ConsensusReactor) gossipDataForCatchup(logger *slog.Logger, rs *cstypes.RoundState, prs *cstypes.PeerRoundState, ps *PeerState, peer p2p.Peer, ) { if index, ok := prs.ProposalBlockParts.Not().PickRandom(); ok { @@ -659,7 +661,7 @@ OUTER_LOOP: } } -func (conR *ConsensusReactor) gossipVotesForHeight(logger log.Logger, rs *cstypes.RoundState, prs *cstypes.PeerRoundState, ps *PeerState) bool { +func (conR *ConsensusReactor) gossipVotesForHeight(logger *slog.Logger, rs *cstypes.RoundState, prs *cstypes.PeerRoundState, ps *PeerState) bool { // If there are lastCommits to send... if prs.Step == cstypes.RoundStepNewHeight { if ps.PickSendVote(rs.LastCommit) { @@ -865,7 +867,7 @@ func (conR *ConsensusReactor) StringIndented(indent string) string { return s } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- var ( ErrPeerStateHeightRegression = errors.New("Error peer state height regression") @@ -878,7 +880,7 @@ var ( // Be mindful of what you Expose. type PeerState struct { peer p2p.Peer - logger log.Logger + logger *slog.Logger mtx sync.Mutex // NOTE: Modify below using setters, never directly. PRS cstypes.PeerRoundState `json:"round_state"` // Exposed. @@ -900,7 +902,7 @@ func (pss peerStateStats) String() string { func NewPeerState(peer p2p.Peer) *PeerState { return &PeerState{ peer: peer, - logger: log.NewNopLogger(), + logger: log.NewNoopLogger(), PRS: cstypes.PeerRoundState{ Round: -1, ProposalPOLRound: -1, @@ -913,7 +915,7 @@ func NewPeerState(peer p2p.Peer) *PeerState { // SetLogger allows to set a logger on the peer state. Returns the peer state // itself. -func (ps *PeerState) SetLogger(logger log.Logger) *PeerState { +func (ps *PeerState) SetLogger(logger *slog.Logger) *PeerState { ps.logger = logger return ps } @@ -1336,7 +1338,7 @@ func (ps *PeerState) StringIndented(indent string) string { indent) } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // Messages // ConsensusMessage is a message that can be sent and received on the ConsensusReactor @@ -1352,7 +1354,7 @@ func decodeMsg(bz []byte) (msg ConsensusMessage, err error) { return } -//------------------------------------- +// ------------------------------------- // NewRoundStepMessage is sent for every step taken in the ConsensusState. // For every height/round/step transition @@ -1391,7 +1393,7 @@ func (m *NewRoundStepMessage) String() string { m.Height, m.Round, m.Step, m.LastCommitRound) } -//------------------------------------- +// ------------------------------------- // NewValidBlockMessage is sent when a validator observes a valid block B in some round r, // i.e., there is a Proposal for block B and 2/3+ prevotes for the block B in the round r. @@ -1435,7 +1437,7 @@ func (m *NewValidBlockMessage) String() string { m.Height, m.Round, m.BlockPartsHeader, m.BlockParts, m.IsCommit) } -//------------------------------------- +// ------------------------------------- // ProposalMessage is sent when a new block is proposed. type ProposalMessage struct { @@ -1452,7 +1454,7 @@ func (m *ProposalMessage) String() string { return fmt.Sprintf("[Proposal %v]", m.Proposal) } -//------------------------------------- +// ------------------------------------- // ProposalPOLMessage is sent when a previous proposal is re-proposed. type ProposalPOLMessage struct { @@ -1483,7 +1485,7 @@ func (m *ProposalPOLMessage) String() string { return fmt.Sprintf("[ProposalPOL H:%v POLR:%v POL:%v]", m.Height, m.ProposalPOLRound, m.ProposalPOL) } -//------------------------------------- +// ------------------------------------- // BlockPartMessage is sent when gossipping a piece of the proposed block. type BlockPartMessage struct { @@ -1511,7 +1513,7 @@ func (m *BlockPartMessage) String() string { return fmt.Sprintf("[BlockPart H:%v R:%v P:%v]", m.Height, m.Round, m.Part) } -//------------------------------------- +// ------------------------------------- // VoteMessage is sent when voting for a proposal (or lack thereof). type VoteMessage struct { @@ -1528,7 +1530,7 @@ func (m *VoteMessage) String() string { return fmt.Sprintf("[Vote %v]", m.Vote) } -//------------------------------------- +// ------------------------------------- // HasVoteMessage is sent to indicate that a particular vote has been received. type HasVoteMessage struct { @@ -1560,7 +1562,7 @@ func (m *HasVoteMessage) String() string { return fmt.Sprintf("[HasVote VI:%v V:{%v/%02d/%v}]", m.Index, m.Height, m.Round, m.Type) } -//------------------------------------- +// ------------------------------------- // VoteSetMaj23Message is sent to indicate that a given BlockID has seen +2/3 votes. type VoteSetMaj23Message struct { @@ -1592,7 +1594,7 @@ func (m *VoteSetMaj23Message) String() string { return fmt.Sprintf("[VSM23 %v/%02d/%v %v]", m.Height, m.Round, m.Type, m.BlockID) } -//------------------------------------- +// ------------------------------------- // VoteSetBitsMessage is sent to communicate the bit-array of votes seen for the BlockID. type VoteSetBitsMessage struct { @@ -1629,4 +1631,4 @@ func (m *VoteSetBitsMessage) String() string { return fmt.Sprintf("[VSB %v/%02d/%v %v %v]", m.Height, m.Round, m.Type, m.BlockID, m.Votes) } -//------------------------------------- +// ------------------------------------- diff --git a/tm2/pkg/bft/consensus/reactor_test.go b/tm2/pkg/bft/consensus/reactor_test.go index db084b61395..96fd2ed987b 100644 --- a/tm2/pkg/bft/consensus/reactor_test.go +++ b/tm2/pkg/bft/consensus/reactor_test.go @@ -6,6 +6,8 @@ import ( "testing" "time" + "golang.org/x/exp/slog" + "github.com/stretchr/testify/assert" "github.com/gnolang/gno/tm2/pkg/amino" @@ -67,7 +69,7 @@ func startConsensusNet(css []*ConsensusState, n int) ([]*ConsensusReactor, []<-c return reactors, blocksSubs, eventSwitches, p2pSwitches } -func stopConsensusNet(logger log.Logger, reactors []*ConsensusReactor, eventSwitches []events.EventSwitch, p2pSwitches []*p2p.Switch) { +func stopConsensusNet(logger *slog.Logger, reactors []*ConsensusReactor, eventSwitches []events.EventSwitch, p2pSwitches []*p2p.Switch) { logger.Info("stopConsensusNet", "n", len(reactors)) for i, r := range reactors { logger.Info("stopConsensusNet: Stopping ConsensusReactor", "i", i) @@ -92,7 +94,7 @@ func TestReactorBasic(t *testing.T) { css, cleanup := randConsensusNet(N, "consensus_reactor_test", newMockTickerFunc(true), newCounter) defer cleanup() reactors, blocksSubs, eventSwitches, p2pSwitches := startConsensusNet(css, N) - defer stopConsensusNet(log.TestingLogger(), reactors, eventSwitches, p2pSwitches) + defer stopConsensusNet(log.NewTestingLogger(t), reactors, eventSwitches, p2pSwitches) // wait till everyone makes the first new block timeoutWaitGroup(t, N, func(j int) { <-blocksSubs[j] @@ -112,7 +114,7 @@ func TestReactorCreatesBlockWhenEmptyBlocksFalse(t *testing.T) { }) defer cleanup() reactors, blocksSubs, eventSwitches, p2pSwitches := startConsensusNet(css, N) - defer stopConsensusNet(log.TestingLogger(), reactors, eventSwitches, p2pSwitches) + defer stopConsensusNet(log.NewTestingLogger(t), reactors, eventSwitches, p2pSwitches) // send a tx if err := assertMempool(css[3].txNotifier).CheckTx([]byte{1, 2, 3}, nil); err != nil { @@ -132,7 +134,7 @@ func TestReactorReceiveDoesNotPanicIfAddPeerHasntBeenCalledYet(t *testing.T) { css, cleanup := randConsensusNet(N, "consensus_reactor_test", newMockTickerFunc(true), newCounter) defer cleanup() reactors, _, eventSwitches, p2pSwitches := startConsensusNet(css, N) - defer stopConsensusNet(log.TestingLogger(), reactors, eventSwitches, p2pSwitches) + defer stopConsensusNet(log.NewTestingLogger(t), reactors, eventSwitches, p2pSwitches) var ( reactor = reactors[0] @@ -156,7 +158,7 @@ func TestReactorReceivePanicsIfInitPeerHasntBeenCalledYet(t *testing.T) { css, cleanup := randConsensusNet(N, "consensus_reactor_test", newMockTickerFunc(true), newCounter) defer cleanup() reactors, _, eventSwitches, p2pSwitches := startConsensusNet(css, N) - defer stopConsensusNet(log.TestingLogger(), reactors, eventSwitches, p2pSwitches) + defer stopConsensusNet(log.NewTestingLogger(t), reactors, eventSwitches, p2pSwitches) var ( reactor = reactors[0] @@ -182,7 +184,7 @@ func TestFlappyReactorRecordsVotesAndBlockParts(t *testing.T) { css, cleanup := randConsensusNet(N, "consensus_reactor_test", newMockTickerFunc(true), newCounter) defer cleanup() reactors, blocksSubs, eventSwitches, p2pSwitches := startConsensusNet(css, N) - defer stopConsensusNet(log.TestingLogger(), reactors, eventSwitches, p2pSwitches) + defer stopConsensusNet(log.NewTestingLogger(t), reactors, eventSwitches, p2pSwitches) // wait till everyone makes the first new block timeoutWaitGroup(t, N, func(j int) { @@ -205,7 +207,7 @@ func TestReactorVotingPowerChange(t *testing.T) { t.Parallel() nVals := 4 - logger := log.TestingLogger() + logger := log.NewTestingLogger(t) css, cleanup := randConsensusNet(nVals, "consensus_voting_power_changes_test", newMockTickerFunc(true), newPersistentKVStore) defer cleanup() @@ -273,7 +275,7 @@ func TestReactorValidatorSetChanges(t *testing.T) { css, _, _, cleanup := randConsensusNetWithPeers(nVals, nPeers, "consensus_val_set_changes_test", newMockTickerFunc(true), newPersistentKVStoreWithPath) defer cleanup() - logger := log.TestingLogger() + logger := log.NewTestingLogger(t) reactors, blocksSubs, eventSwitches, p2pSwitches := startConsensusNet(css, nPeers) defer stopConsensusNet(logger, reactors, eventSwitches, p2pSwitches) @@ -375,7 +377,7 @@ func TestReactorWithTimeoutCommit(t *testing.T) { } reactors, blocksSubs, eventSwitches, p2pSwitches := startConsensusNet(css, N-1) - defer stopConsensusNet(log.TestingLogger(), reactors, eventSwitches, p2pSwitches) + defer stopConsensusNet(log.NewTestingLogger(t), reactors, eventSwitches, p2pSwitches) // wait till everyone makes the first new block timeoutWaitGroup(t, N-1, func(j int) { diff --git a/tm2/pkg/bft/consensus/replay.go b/tm2/pkg/bft/consensus/replay.go index b228c1b63e4..103cf67f512 100644 --- a/tm2/pkg/bft/consensus/replay.go +++ b/tm2/pkg/bft/consensus/replay.go @@ -8,6 +8,8 @@ import ( "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" @@ -196,7 +198,7 @@ type Handshaker struct { store sm.BlockStore evsw events.EventSwitch genDoc *types.GenesisDoc - logger log.Logger + logger *slog.Logger nBlocks int // number of blocks applied to the state } @@ -210,12 +212,12 @@ func NewHandshaker(stateDB dbm.DB, state sm.State, store: store, evsw: events.NilEventSwitch(), genDoc: genDoc, - logger: log.NewNopLogger(), + logger: log.NewNoopLogger(), nBlocks: 0, } } -func (h *Handshaker) SetLogger(l log.Logger) { +func (h *Handshaker) SetLogger(l *slog.Logger) { h.logger = l } diff --git a/tm2/pkg/bft/consensus/replay_file.go b/tm2/pkg/bft/consensus/replay_file.go index 4daf1dbb4ab..7bfa3de9231 100644 --- a/tm2/pkg/bft/consensus/replay_file.go +++ b/tm2/pkg/bft/consensus/replay_file.go @@ -320,7 +320,7 @@ func newConsensusStateForReplay(config cfg.BaseConfig, csConfig *cnscfg.Consensu } mempool := mock.Mempool{} - blockExec := sm.NewBlockExecutor(stateDB, log.TestingLogger(), proxyApp.Consensus(), mempool) + blockExec := sm.NewBlockExecutor(stateDB, log.NewNoopLogger(), proxyApp.Consensus(), mempool) consensusState := NewConsensusState(csConfig, state.Copy(), blockExec, blockStore, mempool) diff --git a/tm2/pkg/bft/consensus/replay_test.go b/tm2/pkg/bft/consensus/replay_test.go index d43a06f40c2..981e72d6ca3 100644 --- a/tm2/pkg/bft/consensus/replay_test.go +++ b/tm2/pkg/bft/consensus/replay_test.go @@ -13,6 +13,8 @@ import ( "testing" "time" + "golang.org/x/exp/slog" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -70,7 +72,7 @@ func startNewConsensusStateAndWaitForBlock(t *testing.T, consensusReplayConfig * ) { t.Helper() - logger := log.TestingLogger() + logger := log.NewTestingLogger(t) state, _ := sm.LoadStateFromDBOrGenesisFile(stateDB, consensusReplayConfig.GenesisFile()) privValidator := loadPrivValidator(consensusReplayConfig) cs := newConsensusStateWithConfigAndBlockStore(consensusReplayConfig, state, privValidator, kvstore.NewKVStoreApplication(), blockDB) @@ -169,7 +171,7 @@ LOOP: t.Logf("====== LOOP %d\n", i) // create consensus state from a clean slate - logger := log.NewNopLogger() + logger := log.NewTestingLogger(t) blockDB := dbm.NewMemDB() stateDB := blockDB state, _ := sm.MakeGenesisStateFromFile(consensusReplayConfig.GenesisFile()) @@ -253,7 +255,7 @@ func (e ReachedLastBlockHeightError) Error() string { return fmt.Sprintf("reached height to stop %d", e.height) } -func (w *crashingWAL) SetLogger(logger log.Logger) { +func (w *crashingWAL) SetLogger(logger *slog.Logger) { w.next.SetLogger(logger) } @@ -570,7 +572,7 @@ func TestFlappyHandshakeReplayNone(t *testing.T) { func TestMockProxyApp(t *testing.T) { t.Parallel() - logger := log.TestingLogger() + logger := log.NewTestingLogger(t) validTxs, invalidTxs := 0, 0 txIndex := 0 @@ -662,7 +664,7 @@ func testHandshakeReplay(t *testing.T, config *cfg.Config, nBlocks int, mode uin wal, err := walm.NewWAL(walFile, maxMsgSize) require.NoError(t, err) - wal.SetLogger(log.TestingLogger()) + wal.SetLogger(log.NewTestingLogger(t)) err = wal.Start() require.NoError(t, err) defer wal.Stop() @@ -733,7 +735,7 @@ func testHandshakeReplay(t *testing.T, config *cfg.Config, nBlocks int, mode uin func applyBlock(stateDB dbm.DB, st sm.State, blk *types.Block, proxyApp proxy.AppConns) sm.State { testPartSize := types.BlockPartSizeBytes - blockExec := sm.NewBlockExecutor(stateDB, log.TestingLogger(), proxyApp.Consensus(), mempool) + blockExec := sm.NewBlockExecutor(stateDB, log.NewNoopLogger(), proxyApp.Consensus(), mempool) blkID := types.BlockID{Hash: blk.Hash(), PartsHeader: blk.MakePartSet(testPartSize).Header()} newState, err := blockExec.ApplyBlock(st, blkID, blk) diff --git a/tm2/pkg/bft/consensus/state.go b/tm2/pkg/bft/consensus/state.go index 988a455f117..c5486bb38a4 100644 --- a/tm2/pkg/bft/consensus/state.go +++ b/tm2/pkg/bft/consensus/state.go @@ -9,6 +9,8 @@ import ( "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" @@ -20,7 +22,6 @@ import ( "github.com/gnolang/gno/tm2/pkg/crypto" "github.com/gnolang/gno/tm2/pkg/errors" "github.com/gnolang/gno/tm2/pkg/events" - "github.com/gnolang/gno/tm2/pkg/log" osm "github.com/gnolang/gno/tm2/pkg/os" "github.com/gnolang/gno/tm2/pkg/p2p" "github.com/gnolang/gno/tm2/pkg/service" @@ -184,7 +185,7 @@ func NewConsensusState( // Public interface // SetLogger implements Service. -func (cs *ConsensusState) SetLogger(l log.Logger) { +func (cs *ConsensusState) SetLogger(l *slog.Logger) { cs.BaseService.Logger = l cs.timeoutTicker.SetLogger(l) } diff --git a/tm2/pkg/bft/consensus/ticker.go b/tm2/pkg/bft/consensus/ticker.go index f1a33dd9c38..4e664304c92 100644 --- a/tm2/pkg/bft/consensus/ticker.go +++ b/tm2/pkg/bft/consensus/ticker.go @@ -3,7 +3,8 @@ package consensus import ( "time" - "github.com/gnolang/gno/tm2/pkg/log" + "golang.org/x/exp/slog" + "github.com/gnolang/gno/tm2/pkg/service" ) @@ -18,7 +19,7 @@ type TimeoutTicker interface { Chan() <-chan timeoutInfo // on which to receive a timeout ScheduleTimeout(ti timeoutInfo) // reset the timer - SetLogger(log.Logger) + SetLogger(*slog.Logger) } // timeoutTicker wraps time.Timer, @@ -71,7 +72,7 @@ func (t *timeoutTicker) ScheduleTimeout(ti timeoutInfo) { t.tickChan <- ti } -//------------------------------------------------------------- +// ------------------------------------------------------------- // stop the timer and drain if necessary func (t *timeoutTicker) stopTimer() { diff --git a/tm2/pkg/bft/consensus/wal_generator.go b/tm2/pkg/bft/consensus/wal_generator.go index 7893c544c7f..8a737452425 100644 --- a/tm2/pkg/bft/consensus/wal_generator.go +++ b/tm2/pkg/bft/consensus/wal_generator.go @@ -9,6 +9,8 @@ import ( "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" @@ -37,7 +39,7 @@ func WALGenerateNBlocks(t *testing.T, wr io.Writer, numBlocks int) (err error) { app := kvstore.NewPersistentKVStoreApplication(filepath.Join(config.DBDir(), "wal_generator")) defer app.Close() - logger := log.TestingLogger().With("wal_generator", "wal_generator") + logger := log.NewNoopLogger().With("wal_generator", "wal_generator") logger.Info("generating WAL (last height msg excluded)", "numBlocks", numBlocks) // ----------- @@ -75,7 +77,7 @@ func WALGenerateNBlocks(t *testing.T, wr io.Writer, numBlocks int) (err error) { } defer evsw.Stop() mempool := mock.Mempool{} - blockExec := sm.NewBlockExecutor(stateDB, log.TestingLogger(), proxyApp.Consensus(), mempool) + blockExec := sm.NewBlockExecutor(stateDB, log.NewNoopLogger(), proxyApp.Consensus(), mempool) consensusState := NewConsensusState(config.Consensus, state.Copy(), blockExec, blockStore, mempool) consensusState.SetLogger(logger) consensusState.SetEventSwitch(evsw) @@ -159,13 +161,13 @@ type heightStopWAL struct { heightToStop int64 signalWhenStopsTo chan<- struct{} - logger log.Logger + logger *slog.Logger } // needed for determinism var fixedTime, _ = time.Parse(time.RFC3339, "2017-01-02T15:04:05Z") -func newHeightStopWAL(logger log.Logger, enc *walm.WALWriter, nBlocks int64, signalStop chan<- struct{}) *heightStopWAL { +func newHeightStopWAL(logger *slog.Logger, enc *walm.WALWriter, nBlocks int64, signalStop chan<- struct{}) *heightStopWAL { return &heightStopWAL{ enc: enc, heightToStop: nBlocks, @@ -174,7 +176,7 @@ func newHeightStopWAL(logger log.Logger, enc *walm.WALWriter, nBlocks int64, sig } } -func (w *heightStopWAL) SetLogger(logger log.Logger) { +func (w *heightStopWAL) SetLogger(logger *slog.Logger) { w.logger = logger } diff --git a/tm2/pkg/bft/consensus/wal_test.go b/tm2/pkg/bft/consensus/wal_test.go index 55c9be03508..b5d49dd6354 100644 --- a/tm2/pkg/bft/consensus/wal_test.go +++ b/tm2/pkg/bft/consensus/wal_test.go @@ -54,7 +54,7 @@ func TestWALTruncate(t *testing.T) { const walChunkSize = 409610 // 4KB wal := makeTempWAL(t, walChunkSize) - wal.SetLogger(log.TestingLogger()) + wal.SetLogger(log.NewTestingLogger(t)) type grouper interface { Group() *auto.Group diff --git a/tm2/pkg/bft/mempool/clist_mempool.go b/tm2/pkg/bft/mempool/clist_mempool.go index 14fc52e19b2..da0a2c22c11 100644 --- a/tm2/pkg/bft/mempool/clist_mempool.go +++ b/tm2/pkg/bft/mempool/clist_mempool.go @@ -9,6 +9,8 @@ import ( "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" @@ -63,7 +65,7 @@ type CListMempool struct { // A log of mempool txs wal *auto.AutoFile - logger log.Logger + logger *slog.Logger } var _ Mempool = &CListMempool{} @@ -91,7 +93,7 @@ func NewCListMempool( rechecking: 0, recheckCursor: nil, recheckEnd: nil, - logger: log.NewNopLogger(), + logger: log.NewNoopLogger(), } if config.CacheSize > 0 { mempool.cache = newMapTxCache(config.CacheSize) @@ -111,7 +113,7 @@ func (mem *CListMempool) EnableTxsAvailable() { } // SetLogger sets the Logger. -func (mem *CListMempool) SetLogger(l log.Logger) { +func (mem *CListMempool) SetLogger(l *slog.Logger) { mem.logger = l } diff --git a/tm2/pkg/bft/mempool/clist_mempool_test.go b/tm2/pkg/bft/mempool/clist_mempool_test.go index 60582f1922d..4450dc3b764 100644 --- a/tm2/pkg/bft/mempool/clist_mempool_test.go +++ b/tm2/pkg/bft/mempool/clist_mempool_test.go @@ -35,13 +35,13 @@ func newMempoolWithApp(cc proxy.ClientCreator) (*CListMempool, cleanupFunc) { func newMempoolWithAppAndConfig(cc proxy.ClientCreator, config *cfg.MempoolConfig) (*CListMempool, cleanupFunc) { appConnMem, _ := cc.NewABCIClient() - appConnMem.SetLogger(log.TestingLogger().With("module", "abci-client", "connection", "mempool")) + appConnMem.SetLogger(log.NewNoopLogger().With("module", "abci-client", "connection", "mempool")) err := appConnMem.Start() if err != nil { panic(err) } mempool := NewCListMempool(config, appConnMem, 0, testMaxTxBytes) - mempool.SetLogger(log.TestingLogger()) + mempool.SetLogger(log.NewNoopLogger()) return mempool, func() { if config.RootDir != "" { os.RemoveAll(config.RootDir) @@ -269,7 +269,7 @@ func TestSerialReap(t *testing.T) { defer cleanup() appConnCon, _ := cc.NewABCIClient() - appConnCon.SetLogger(log.TestingLogger().With("module", "abci-client", "connection", "consensus")) + appConnCon.SetLogger(log.NewTestingLogger(t).With("module", "abci-client", "connection", "consensus")) err := appConnCon.Start() require.Nil(t, err) @@ -509,7 +509,7 @@ func TestMempoolMaxPendingTxsBytes(t *testing.T) { assert.EqualValues(t, 8, mempool.TxsBytes()) appConnCon, _ := cc.NewABCIClient() - appConnCon.SetLogger(log.TestingLogger().With("module", "abci-client", "connection", "consensus")) + appConnCon.SetLogger(log.NewTestingLogger(t).With("module", "abci-client", "connection", "consensus")) err = appConnCon.Start() require.Nil(t, err) defer appConnCon.Stop() diff --git a/tm2/pkg/bft/mempool/reactor.go b/tm2/pkg/bft/mempool/reactor.go index f6ee67b3fc4..7147c11169b 100644 --- a/tm2/pkg/bft/mempool/reactor.go +++ b/tm2/pkg/bft/mempool/reactor.go @@ -7,11 +7,12 @@ import ( "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" "github.com/gnolang/gno/tm2/pkg/clist" - "github.com/gnolang/gno/tm2/pkg/log" "github.com/gnolang/gno/tm2/pkg/p2p" ) @@ -112,7 +113,7 @@ func NewReactor(config *cfg.MempoolConfig, mempool *CListMempool) *Reactor { } // SetLogger sets the Logger on the reactor and the underlying mempool. -func (memR *Reactor) SetLogger(l log.Logger) { +func (memR *Reactor) SetLogger(l *slog.Logger) { memR.Logger = l memR.mempool.SetLogger(l) } @@ -248,7 +249,7 @@ func (memR *Reactor) broadcastTxRoutine(peer p2p.Peer) { } } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // Messages // MempoolMessage is a message sent or received by the Reactor. @@ -259,7 +260,7 @@ func (memR *Reactor) decodeMsg(bz []byte) (msg MempoolMessage, err error) { return } -//------------------------------------- +// ------------------------------------- // TxMessage is a MempoolMessage containing a transaction. type TxMessage struct { diff --git a/tm2/pkg/bft/mempool/reactor_test.go b/tm2/pkg/bft/mempool/reactor_test.go index 154cb1a7132..e7a3c43a6b9 100644 --- a/tm2/pkg/bft/mempool/reactor_test.go +++ b/tm2/pkg/bft/mempool/reactor_test.go @@ -13,7 +13,6 @@ import ( memcfg "github.com/gnolang/gno/tm2/pkg/bft/mempool/config" "github.com/gnolang/gno/tm2/pkg/bft/proxy" "github.com/gnolang/gno/tm2/pkg/bft/types" - "github.com/gnolang/gno/tm2/pkg/colors" "github.com/gnolang/gno/tm2/pkg/errors" "github.com/gnolang/gno/tm2/pkg/log" "github.com/gnolang/gno/tm2/pkg/p2p" @@ -30,43 +29,10 @@ func (ps peerState) GetHeight() int64 { return ps.height } -// mempoolLogger is a TestingLogger which uses a different -// color for each validator ("validator" key must exist). -func mempoolLogger() log.Logger { - return log.TestingLoggerWithColorFn(func(keyvals ...interface{}) colors.Color { - for i := 0; i < len(keyvals)-1; i += 2 { - if keyvals[i] == "validator" { - num := keyvals[i+1].(int) - switch num % 8 { - case 0: - return colors.Red - case 1: - return colors.Green - case 2: - return colors.Yellow - case 3: - return colors.Blue - case 4: - return colors.Magenta - case 5: - return colors.Cyan - case 6: - return colors.White - case 7: - return colors.Gray - default: - panic("should not happen") - } - } - } - return colors.None - }) -} - // connect N mempool reactors through N switches func makeAndConnectReactors(mconfig *memcfg.MempoolConfig, pconfig *p2pcfg.P2PConfig, n int) []*Reactor { reactors := make([]*Reactor, n) - logger := mempoolLogger() + logger := log.NewNoopLogger() for i := 0; i < n; i++ { app := kvstore.NewKVStoreApplication() cc := proxy.NewLocalClientCreator(app) diff --git a/tm2/pkg/bft/node/node.go b/tm2/pkg/bft/node/node.go index 9d6143e7af3..a6c67fa2485 100644 --- a/tm2/pkg/bft/node/node.go +++ b/tm2/pkg/bft/node/node.go @@ -11,6 +11,8 @@ import ( "strings" "time" + "golang.org/x/exp/slog" + "github.com/gnolang/gno/tm2/pkg/bft/state/eventstore/file" "github.com/rs/cors" @@ -36,7 +38,6 @@ import ( dbm "github.com/gnolang/gno/tm2/pkg/db" "github.com/gnolang/gno/tm2/pkg/errors" "github.com/gnolang/gno/tm2/pkg/events" - "github.com/gnolang/gno/tm2/pkg/log" "github.com/gnolang/gno/tm2/pkg/p2p" "github.com/gnolang/gno/tm2/pkg/service" verset "github.com/gnolang/gno/tm2/pkg/versionset" @@ -74,12 +75,12 @@ func DefaultGenesisDocProviderFunc(config *cfg.Config) GenesisDocProvider { } // NodeProvider takes a config and a logger and returns a ready to go Node. -type NodeProvider func(*cfg.Config, log.Logger) (*Node, error) +type NodeProvider func(*cfg.Config, *slog.Logger) (*Node, error) // DefaultNewNode returns a Tendermint node with default settings for the // PrivValidator, ClientCreator, GenesisDoc, and DBProvider. // It implements NodeProvider. -func DefaultNewNode(config *cfg.Config, logger log.Logger) (*Node, error) { +func DefaultNewNode(config *cfg.Config, logger *slog.Logger) (*Node, error) { // Generate node PrivKey nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile()) if err != nil { @@ -185,7 +186,7 @@ func initDBs(config *cfg.Config, dbProvider DBProvider) (blockStore *store.Block return } -func createAndStartProxyAppConns(clientCreator proxy.ClientCreator, logger log.Logger) (proxy.AppConns, error) { +func createAndStartProxyAppConns(clientCreator proxy.ClientCreator, logger *slog.Logger) (proxy.AppConns, error) { proxyApp := proxy.NewAppConns(clientCreator) proxyApp.SetLogger(logger.With("module", "proxy")) if err := proxyApp.Start(); err != nil { @@ -197,7 +198,7 @@ func createAndStartProxyAppConns(clientCreator proxy.ClientCreator, logger log.L func createAndStartEventStoreService( cfg *cfg.Config, evsw events.EventSwitch, - logger log.Logger, + logger *slog.Logger, ) (*eventstore.Service, eventstore.TxEventStore, error) { var ( err error @@ -227,7 +228,7 @@ func createAndStartEventStoreService( } func doHandshake(stateDB dbm.DB, state sm.State, blockStore sm.BlockStore, - genDoc *types.GenesisDoc, evsw events.EventSwitch, proxyApp proxy.AppConns, consensusLogger log.Logger, + genDoc *types.GenesisDoc, evsw events.EventSwitch, proxyApp proxy.AppConns, consensusLogger *slog.Logger, ) error { handshaker := cs.NewHandshaker(stateDB, state, blockStore, genDoc) handshaker.SetLogger(consensusLogger) @@ -238,7 +239,7 @@ func doHandshake(stateDB dbm.DB, state sm.State, blockStore sm.BlockStore, return nil } -func logNodeStartupInfo(state sm.State, pubKey crypto.PubKey, logger, consensusLogger log.Logger) { +func logNodeStartupInfo(state sm.State, pubKey crypto.PubKey, logger, consensusLogger *slog.Logger) { // Log the version info. logger.Info("Version info", "version", version.Version, @@ -262,7 +263,7 @@ func onlyValidatorIsUs(state sm.State, privVal types.PrivValidator) bool { } func createMempoolAndMempoolReactor(config *cfg.Config, proxyApp proxy.AppConns, - state sm.State, logger log.Logger, + state sm.State, logger *slog.Logger, ) (*mempl.Reactor, *mempl.CListMempool) { mempool := mempl.NewCListMempool( config.Mempool, @@ -286,7 +287,7 @@ func createBlockchainReactor(config *cfg.Config, blockExec *sm.BlockExecutor, blockStore *store.BlockStore, fastSync bool, - logger log.Logger, + logger *slog.Logger, ) (bcReactor p2p.Reactor, err error) { bcReactor = bc.NewBlockchainReactor(state.Copy(), blockExec, blockStore, fastSync) @@ -302,7 +303,7 @@ func createConsensusReactor(config *cfg.Config, privValidator types.PrivValidator, fastSync bool, evsw events.EventSwitch, - consensusLogger log.Logger, + consensusLogger *slog.Logger, ) (*cs.ConsensusReactor, *cs.ConsensusState) { consensusState := cs.NewConsensusState( config.Consensus, @@ -387,7 +388,7 @@ func createSwitch(config *cfg.Config, consensusReactor *cs.ConsensusReactor, nodeInfo p2p.NodeInfo, nodeKey *p2p.NodeKey, - p2pLogger log.Logger, + p2pLogger *slog.Logger, ) *p2p.Switch { sw := p2p.NewSwitch( config.P2P, @@ -413,7 +414,7 @@ func NewNode(config *cfg.Config, clientCreator proxy.ClientCreator, genesisDocProvider GenesisDocProvider, dbProvider DBProvider, - logger log.Logger, + logger *slog.Logger, options ...Option, ) (*Node, error) { blockStore, stateDB, err := initDBs(config, dbProvider) @@ -937,7 +938,7 @@ func saveGenesisDoc(db dbm.DB, genDoc *types.GenesisDoc) { func createAndStartPrivValidatorSocketClient( listenAddr string, - logger log.Logger, + logger *slog.Logger, ) (types.PrivValidator, error) { pve, err := privval.NewSignerListener(listenAddr, logger) if err != nil { diff --git a/tm2/pkg/bft/node/node_test.go b/tm2/pkg/bft/node/node_test.go index 2352df49762..d182b7fb0d5 100644 --- a/tm2/pkg/bft/node/node_test.go +++ b/tm2/pkg/bft/node/node_test.go @@ -33,7 +33,7 @@ func TestNodeStartStop(t *testing.T) { defer os.RemoveAll(config.RootDir) // create & start node - n, err := DefaultNewNode(config, log.TestingLogger()) + n, err := DefaultNewNode(config, log.NewNoopLogger()) require.NoError(t, err) err = n.Start() require.NoError(t, err) @@ -96,7 +96,7 @@ func TestNodeDelayedStart(t *testing.T) { now := tmtime.Now() // create & start node - n, err := DefaultNewNode(config, log.TestingLogger()) + n, err := DefaultNewNode(config, log.NewTestingLogger(t)) n.GenesisDoc().GenesisTime = now.Add(2 * time.Second) require.NoError(t, err) @@ -113,7 +113,7 @@ func TestNodeSetAppVersion(t *testing.T) { defer os.RemoveAll(config.RootDir) // create & start node - n, err := DefaultNewNode(config, log.TestingLogger()) + n, err := DefaultNewNode(config, log.NewTestingLogger(t)) require.NoError(t, err) // default config uses the kvstore app @@ -138,7 +138,7 @@ func TestNodeSetPrivValTCP(t *testing.T) { dialer := privval.DialTCPFn(addr, 100*time.Millisecond, ed25519.GenPrivKey()) dialerEndpoint := privval.NewSignerDialerEndpoint( - log.TestingLogger(), + log.NewTestingLogger(t), dialer, ) privval.SignerDialerEndpointTimeoutReadWrite(100 * time.Millisecond)(dialerEndpoint) @@ -157,7 +157,7 @@ func TestNodeSetPrivValTCP(t *testing.T) { }() defer signerServer.Stop() - n, err := DefaultNewNode(config, log.TestingLogger()) + n, err := DefaultNewNode(config, log.NewTestingLogger(t)) require.NoError(t, err) assert.IsType(t, &privval.SignerClient{}, n.PrivValidator()) } @@ -170,7 +170,7 @@ func TestPrivValidatorListenAddrNoProtocol(t *testing.T) { defer os.RemoveAll(config.RootDir) config.BaseConfig.PrivValidatorListenAddr = addrNoPrefix - _, err := DefaultNewNode(config, log.TestingLogger()) + _, err := DefaultNewNode(config, log.NewTestingLogger(t)) assert.Error(t, err) } @@ -184,7 +184,7 @@ func TestNodeSetPrivValIPC(t *testing.T) { dialer := privval.DialUnixFn(tmpfile) dialerEndpoint := privval.NewSignerDialerEndpoint( - log.TestingLogger(), + log.NewTestingLogger(t), dialer, ) privval.SignerDialerEndpointTimeoutReadWrite(100 * time.Millisecond)(dialerEndpoint) @@ -201,7 +201,7 @@ func TestNodeSetPrivValIPC(t *testing.T) { }() defer pvsc.Stop() - n, err := DefaultNewNode(config, log.TestingLogger()) + n, err := DefaultNewNode(config, log.NewTestingLogger(t)) require.NoError(t, err) assert.IsType(t, &privval.SignerClient{}, n.PrivValidator()) } @@ -228,7 +228,7 @@ func TestCreateProposalBlock(t *testing.T) { require.Nil(t, err) defer proxyApp.Stop() - logger := log.TestingLogger() + logger := log.NewTestingLogger(t) var height int64 = 1 state, stateDB := state(1, height) @@ -289,7 +289,7 @@ func TestNodeNewNodeCustomReactors(t *testing.T) { proxy.DefaultClientCreator(nil, config.ProxyApp, config.ABCI, config.DBDir()), DefaultGenesisDocProviderFunc(config), DefaultDBProvider, - log.TestingLogger(), + log.NewTestingLogger(t), CustomReactors(map[string]p2p.Reactor{"FOO": cr, "BLOCKCHAIN": customBlockchainReactor}), ) require.NoError(t, err) diff --git a/tm2/pkg/bft/privval/signer_dialer_endpoint.go b/tm2/pkg/bft/privval/signer_dialer_endpoint.go index 40a76b6cb9f..275c406919f 100644 --- a/tm2/pkg/bft/privval/signer_dialer_endpoint.go +++ b/tm2/pkg/bft/privval/signer_dialer_endpoint.go @@ -3,7 +3,8 @@ package privval import ( "time" - "github.com/gnolang/gno/tm2/pkg/log" + "golang.org/x/exp/slog" + "github.com/gnolang/gno/tm2/pkg/service" ) @@ -41,7 +42,7 @@ type SignerDialerEndpoint struct { // dialer and respond to any signature requests over the connection // using the given privVal. func NewSignerDialerEndpoint( - logger log.Logger, + logger *slog.Logger, dialer SocketDialer, ) *SignerDialerEndpoint { sd := &SignerDialerEndpoint{ diff --git a/tm2/pkg/bft/privval/signer_listener_endpoint.go b/tm2/pkg/bft/privval/signer_listener_endpoint.go index 30ed24268ca..7ce42534290 100644 --- a/tm2/pkg/bft/privval/signer_listener_endpoint.go +++ b/tm2/pkg/bft/privval/signer_listener_endpoint.go @@ -6,7 +6,8 @@ import ( "sync" "time" - "github.com/gnolang/gno/tm2/pkg/log" + "golang.org/x/exp/slog" + "github.com/gnolang/gno/tm2/pkg/service" ) @@ -30,7 +31,7 @@ type SignerListenerEndpoint struct { // NewSignerListenerEndpoint returns an instance of SignerListenerEndpoint. func NewSignerListenerEndpoint( - logger log.Logger, + logger *slog.Logger, listener net.Listener, ) *SignerListenerEndpoint { sc := &SignerListenerEndpoint{ diff --git a/tm2/pkg/bft/privval/signer_listener_endpoint_test.go b/tm2/pkg/bft/privval/signer_listener_endpoint_test.go index 16640583364..bb026cd9acc 100644 --- a/tm2/pkg/bft/privval/signer_listener_endpoint_test.go +++ b/tm2/pkg/bft/privval/signer_listener_endpoint_test.go @@ -5,6 +5,8 @@ import ( "testing" "time" + "golang.org/x/exp/slog" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -62,7 +64,7 @@ func TestSignerRemoteRetryTCPOnly(t *testing.T) { }(ln, attemptCh) dialerEndpoint := NewSignerDialerEndpoint( - log.TestingLogger(), + log.NewTestingLogger(t), DialTCPFn(ln.Addr().String(), testTimeoutReadWrite, ed25519.GenPrivKey()), ) SignerDialerEndpointTimeoutReadWrite(time.Millisecond)(dialerEndpoint) @@ -89,7 +91,7 @@ func TestRetryConnToRemoteSigner(t *testing.T) { for _, tc := range getDialerTestCases(t) { var ( - logger = log.TestingLogger() + logger = log.NewTestingLogger(t) chainID = random.RandStr(12) mockPV = types.NewMockPV() endpointIsOpenCh = make(chan struct{}) @@ -136,7 +138,7 @@ func TestRetryConnToRemoteSigner(t *testing.T) { // ----------- -func newSignerListenerEndpoint(logger log.Logger, ln net.Listener, timeoutReadWrite time.Duration) *SignerListenerEndpoint { +func newSignerListenerEndpoint(logger *slog.Logger, ln net.Listener, timeoutReadWrite time.Duration) *SignerListenerEndpoint { var listener net.Listener if ln.Addr().Network() == "unix" { @@ -172,7 +174,7 @@ func getMockEndpoints( t.Helper() var ( - logger = log.TestingLogger() + logger = log.NewTestingLogger(t) endpointIsOpenCh = make(chan struct{}) dialerEndpoint = NewSignerDialerEndpoint( diff --git a/tm2/pkg/bft/privval/socket_listeners_test.go b/tm2/pkg/bft/privval/socket_listeners_test.go index f43ec6e1636..3177aec71dc 100644 --- a/tm2/pkg/bft/privval/socket_listeners_test.go +++ b/tm2/pkg/bft/privval/socket_listeners_test.go @@ -104,8 +104,6 @@ func TestListenerTimeoutAccept(t *testing.T) { } func TestListenerTimeoutReadWrite(t *testing.T) { - t.Parallel() - const ( // This needs to be long enough s.t. the Accept will definitely succeed: timeoutAccept = time.Second diff --git a/tm2/pkg/bft/privval/utils.go b/tm2/pkg/bft/privval/utils.go index c190235ddf3..904474ba4f7 100644 --- a/tm2/pkg/bft/privval/utils.go +++ b/tm2/pkg/bft/privval/utils.go @@ -4,9 +4,10 @@ import ( "fmt" "net" + "golang.org/x/exp/slog" + "github.com/gnolang/gno/tm2/pkg/crypto/ed25519" "github.com/gnolang/gno/tm2/pkg/errors" - "github.com/gnolang/gno/tm2/pkg/log" osm "github.com/gnolang/gno/tm2/pkg/os" ) @@ -25,7 +26,7 @@ func IsConnTimeout(err error) bool { } // NewSignerListener creates a new SignerListenerEndpoint using the corresponding listen address -func NewSignerListener(listenAddr string, logger log.Logger) (*SignerListenerEndpoint, error) { +func NewSignerListener(listenAddr string, logger *slog.Logger) (*SignerListenerEndpoint, error) { var listener net.Listener protocol, address := osm.ProtocolAndAddress(listenAddr) diff --git a/tm2/pkg/bft/rpc/client/localclient.go b/tm2/pkg/bft/rpc/client/localclient.go index 20209f74071..15e2b916c71 100644 --- a/tm2/pkg/bft/rpc/client/localclient.go +++ b/tm2/pkg/bft/rpc/client/localclient.go @@ -1,6 +1,8 @@ package client import ( + "golang.org/x/exp/slog" + nm "github.com/gnolang/gno/tm2/pkg/bft/node" "github.com/gnolang/gno/tm2/pkg/bft/rpc/core" ctypes "github.com/gnolang/gno/tm2/pkg/bft/rpc/core/types" @@ -24,7 +26,7 @@ For real clients, you probably want to use client.HTTP. For more powerful control during testing, you probably want the "client/mock" package. */ type Local struct { - Logger log.Logger + Logger *slog.Logger ctx *rpctypes.Context } @@ -37,7 +39,7 @@ type Local struct { func NewLocal(node *nm.Node) *Local { node.ConfigureRPC() return &Local{ - Logger: log.NewNopLogger(), + Logger: log.NewNoopLogger(), ctx: &rpctypes.Context{}, } } @@ -45,7 +47,7 @@ func NewLocal(node *nm.Node) *Local { var _ Client = (*Local)(nil) // SetLogger allows to set a logger on the client. -func (c *Local) SetLogger(l log.Logger) { +func (c *Local) SetLogger(l *slog.Logger) { c.Logger = l } diff --git a/tm2/pkg/bft/rpc/core/net_test.go b/tm2/pkg/bft/rpc/core/net_test.go index c3a8830cb1b..3273837b6ce 100644 --- a/tm2/pkg/bft/rpc/core/net_test.go +++ b/tm2/pkg/bft/rpc/core/net_test.go @@ -21,7 +21,7 @@ func TestUnsafeDialSeeds(t *testing.T) { require.NoError(t, err) defer sw.Stop() - logger = log.TestingLogger() + logger = log.NewNoopLogger() p2pPeers = sw testCases := []struct { @@ -53,7 +53,7 @@ func TestUnsafeDialPeers(t *testing.T) { require.NoError(t, err) defer sw.Stop() - logger = log.TestingLogger() + logger = log.NewNoopLogger() p2pPeers = sw testCases := []struct { diff --git a/tm2/pkg/bft/rpc/core/pipe.go b/tm2/pkg/bft/rpc/core/pipe.go index abfdc300d31..977dfd54e1f 100644 --- a/tm2/pkg/bft/rpc/core/pipe.go +++ b/tm2/pkg/bft/rpc/core/pipe.go @@ -3,6 +3,8 @@ package core import ( "fmt" + "golang.org/x/exp/slog" + "github.com/gnolang/gno/tm2/pkg/bft/consensus" cnscfg "github.com/gnolang/gno/tm2/pkg/bft/consensus/config" cstypes "github.com/gnolang/gno/tm2/pkg/bft/consensus/types" @@ -14,7 +16,6 @@ import ( "github.com/gnolang/gno/tm2/pkg/crypto" dbm "github.com/gnolang/gno/tm2/pkg/db" "github.com/gnolang/gno/tm2/pkg/events" - "github.com/gnolang/gno/tm2/pkg/log" "github.com/gnolang/gno/tm2/pkg/p2p" ) @@ -72,7 +73,7 @@ var ( gTxDispatcher *txDispatcher mempool mempl.Mempool - logger log.Logger + logger *slog.Logger config cfg.RPCConfig ) @@ -117,7 +118,7 @@ func SetConsensusReactor(conR *consensus.ConsensusReactor) { consensusReactor = conR } -func SetLogger(l log.Logger) { +func SetLogger(l *slog.Logger) { logger = l } diff --git a/tm2/pkg/bft/rpc/lib/client/integration_test.go b/tm2/pkg/bft/rpc/lib/client/integration_test.go index f3c705ecf98..85b4c94594b 100644 --- a/tm2/pkg/bft/rpc/lib/client/integration_test.go +++ b/tm2/pkg/bft/rpc/lib/client/integration_test.go @@ -29,7 +29,7 @@ func TestWSClientReconnectWithJitter(t *testing.T) { errNotConnected := errors.New("not connected") clientMap := make(map[int]*WSClient) buf := new(bytes.Buffer) - logger := log.NewTMLogger(buf) + logger := log.NewNoopLogger() for i := 0; i < n; i++ { c := NewWSClient("tcp://foo", "/websocket") c.Dialer = func(string, string) (net.Conn, error) { diff --git a/tm2/pkg/bft/rpc/lib/client/ws_client_test.go b/tm2/pkg/bft/rpc/lib/client/ws_client_test.go index 47c3a50ee63..c902ee709e0 100644 --- a/tm2/pkg/bft/rpc/lib/client/ws_client_test.go +++ b/tm2/pkg/bft/rpc/lib/client/ws_client_test.go @@ -208,7 +208,7 @@ func startClient(t *testing.T, addr net.Addr) *WSClient { c := NewWSClient(addr.String(), "/websocket") err := c.Start() require.Nil(t, err) - c.SetLogger(log.TestingLogger()) + c.SetLogger(log.NewTestingLogger(t)) return c } diff --git a/tm2/pkg/bft/rpc/lib/rpc_test.go b/tm2/pkg/bft/rpc/lib/rpc_test.go index a299417187a..386e641cb53 100644 --- a/tm2/pkg/bft/rpc/lib/rpc_test.go +++ b/tm2/pkg/bft/rpc/lib/rpc_test.go @@ -15,7 +15,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/gnolang/gno/tm2/pkg/colors" "github.com/gnolang/gno/tm2/pkg/log" "github.com/gnolang/gno/tm2/pkg/random" @@ -88,22 +87,9 @@ func TestMain(m *testing.M) { os.Exit(code) } -var colorFn = func(keyvals ...interface{}) colors.Color { - for i := 0; i < len(keyvals)-1; i += 2 { - if keyvals[i] == "socket" { - if keyvals[i+1] == "tcp" { - return colors.Blue - } else if keyvals[i+1] == "unix" { - return colors.Cyan - } - } - } - return colors.None -} - // launch unix and tcp servers func setup() { - logger := log.NewTMLoggerWithColorFn(log.NewSyncWriter(os.Stdout), colorFn) + logger := log.NewNoopLogger() cmd := exec.Command("rm", "-f", unixSocket) err := cmd.Start() @@ -293,7 +279,7 @@ func TestServersAndClientsBasic(t *testing.T) { testWithHTTPClient(t, cl2) cl3 := client.NewWSClient(addr, websocketEndpoint) - cl3.SetLogger(log.TestingLogger()) + cl3.SetLogger(log.NewTestingLogger(t)) err := cl3.Start() require.Nil(t, err) fmt.Printf("=== testing server on %s using WS client", addr) @@ -336,7 +322,7 @@ func TestWSNewWSRPCFunc(t *testing.T) { t.Parallel() cl := client.NewWSClient(tcpAddr, websocketEndpoint) - cl.SetLogger(log.TestingLogger()) + cl.SetLogger(log.NewTestingLogger(t)) err := cl.Start() require.Nil(t, err) defer cl.Stop() @@ -363,7 +349,7 @@ func TestWSHandlesArrayParams(t *testing.T) { t.Parallel() cl := client.NewWSClient(tcpAddr, websocketEndpoint) - cl.SetLogger(log.TestingLogger()) + cl.SetLogger(log.NewTestingLogger(t)) err := cl.Start() require.Nil(t, err) defer cl.Stop() @@ -390,7 +376,7 @@ func TestWSClientPingPong(t *testing.T) { t.Parallel() cl := client.NewWSClient(tcpAddr, websocketEndpoint) - cl.SetLogger(log.TestingLogger()) + cl.SetLogger(log.NewTestingLogger(t)) err := cl.Start() require.Nil(t, err) defer cl.Stop() diff --git a/tm2/pkg/bft/rpc/lib/server/handlers.go b/tm2/pkg/bft/rpc/lib/server/handlers.go index 40543e5f465..1df5976f858 100644 --- a/tm2/pkg/bft/rpc/lib/server/handlers.go +++ b/tm2/pkg/bft/rpc/lib/server/handlers.go @@ -14,6 +14,8 @@ import ( "strings" "time" + "golang.org/x/exp/slog" + "github.com/gorilla/websocket" "github.com/gnolang/gno/tm2/pkg/amino" @@ -25,7 +27,7 @@ import ( // RegisterRPCFuncs adds a route for each function in the funcMap, as well as general jsonrpc and websocket handlers for all functions. // "result" is the interface on which the result objects are registered, and is populated with every RPCResponse -func RegisterRPCFuncs(mux *http.ServeMux, funcMap map[string]*RPCFunc, logger log.Logger) { +func RegisterRPCFuncs(mux *http.ServeMux, funcMap map[string]*RPCFunc, logger *slog.Logger) { // HTTP endpoints for funcName, rpcFunc := range funcMap { mux.HandleFunc("/"+funcName, makeHTTPHandler(rpcFunc, logger)) @@ -99,7 +101,7 @@ func funcReturnTypes(f interface{}) []reflect.Type { // rpc.json // jsonrpc calls grab the given method's function info and runs reflect.Call -func makeJSONRPCHandler(funcMap map[string]*RPCFunc, logger log.Logger) http.HandlerFunc { +func makeJSONRPCHandler(funcMap map[string]*RPCFunc, logger *slog.Logger) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { b, err := io.ReadAll(r.Body) if err != nil { @@ -256,7 +258,7 @@ func jsonParamsToArgs(rpcFunc *RPCFunc, raw []byte) ([]reflect.Value, error) { // rpc.http // convert from a function name to the http handler -func makeHTTPHandler(rpcFunc *RPCFunc, logger log.Logger) func(http.ResponseWriter, *http.Request) { +func makeHTTPHandler(rpcFunc *RPCFunc, logger *slog.Logger) func(http.ResponseWriter, *http.Request) { // Exception for websocket endpoints if rpcFunc.ws { return func(w http.ResponseWriter, r *http.Request) { @@ -758,7 +760,7 @@ type WebsocketManager struct { websocket.Upgrader funcMap map[string]*RPCFunc - logger log.Logger + logger *slog.Logger wsConnOptions []func(*wsConnection) } @@ -773,13 +775,13 @@ func NewWebsocketManager(funcMap map[string]*RPCFunc, wsConnOptions ...func(*wsC return true }, }, - logger: log.NewNopLogger(), + logger: log.NewNoopLogger(), wsConnOptions: wsConnOptions, } } // SetLogger sets the logger. -func (wm *WebsocketManager) SetLogger(l log.Logger) { +func (wm *WebsocketManager) SetLogger(l *slog.Logger) { wm.logger = l } diff --git a/tm2/pkg/bft/rpc/lib/server/handlers_test.go b/tm2/pkg/bft/rpc/lib/server/handlers_test.go index e09a8a7cf96..75c64151619 100644 --- a/tm2/pkg/bft/rpc/lib/server/handlers_test.go +++ b/tm2/pkg/bft/rpc/lib/server/handlers_test.go @@ -1,7 +1,6 @@ package rpcserver_test import ( - "bytes" "encoding/json" "io" "net/http" @@ -30,9 +29,8 @@ func testMux() *http.ServeMux { "c": rs.NewRPCFunc(func(ctx *types.Context, s string, i int) (string, error) { return "foo", nil }, "s,i"), } mux := http.NewServeMux() - buf := new(bytes.Buffer) - logger := log.NewTMLogger(buf) - rs.RegisterRPCFuncs(mux, funcMap, logger) + + rs.RegisterRPCFuncs(mux, funcMap, log.NewNoopLogger()) return mux } @@ -274,7 +272,7 @@ func newWSServer() *httptest.Server { "c": rs.NewWSRPCFunc(func(ctx *types.Context, s string, i int) (string, error) { return "foo", nil }, "s,i"), } wm := rs.NewWebsocketManager(funcMap) - wm.SetLogger(log.TestingLogger()) + wm.SetLogger(log.NewNoopLogger()) mux := http.NewServeMux() mux.HandleFunc("/websocket", wm.WebsocketHandler) diff --git a/tm2/pkg/bft/rpc/lib/server/http_server.go b/tm2/pkg/bft/rpc/lib/server/http_server.go index feaba1ba938..102a8203ac5 100644 --- a/tm2/pkg/bft/rpc/lib/server/http_server.go +++ b/tm2/pkg/bft/rpc/lib/server/http_server.go @@ -11,11 +11,12 @@ import ( "strings" "time" + "golang.org/x/exp/slog" + "golang.org/x/net/netutil" types "github.com/gnolang/gno/tm2/pkg/bft/rpc/lib/types" "github.com/gnolang/gno/tm2/pkg/errors" - "github.com/gnolang/gno/tm2/pkg/log" ) // Config is a RPC server configuration. @@ -47,7 +48,7 @@ func DefaultConfig() *Config { // StartHTTPServer takes a listener and starts an HTTP server with the given handler. // It wraps handler with RecoverAndLogHandler. // NOTE: This function blocks - you may want to call it in a go-routine. -func StartHTTPServer(listener net.Listener, handler http.Handler, logger log.Logger, config *Config) error { +func StartHTTPServer(listener net.Listener, handler http.Handler, logger *slog.Logger, config *Config) error { logger.Info(fmt.Sprintf("Starting RPC HTTP server on %s", listener.Addr())) s := &http.Server{ Handler: RecoverAndLogHandler(maxBytesHandler{h: handler, n: config.MaxBodyBytes}, logger), @@ -68,7 +69,7 @@ func StartHTTPAndTLSServer( listener net.Listener, handler http.Handler, certFile, keyFile string, - logger log.Logger, + logger *slog.Logger, config *Config, ) error { logger.Info(fmt.Sprintf("Starting RPC HTTPS server on %s (cert: %q, key: %q)", @@ -134,12 +135,12 @@ func WriteRPCResponseArrayHTTP(w http.ResponseWriter, res []types.RPCResponse) { } } -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // RecoverAndLogHandler wraps an HTTP handler, adding error logging. // If the inner function panics, the outer function recovers, logs, sends an // HTTP 500 error response. -func RecoverAndLogHandler(handler http.Handler, logger log.Logger) http.Handler { +func RecoverAndLogHandler(handler http.Handler, logger *slog.Logger) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Wrap the ResponseWriter to remember the status rww := &ResponseWriterWrapper{-1, w} diff --git a/tm2/pkg/bft/rpc/lib/server/http_server_test.go b/tm2/pkg/bft/rpc/lib/server/http_server_test.go index 5ab8d2890ae..6c6d9ad14d6 100644 --- a/tm2/pkg/bft/rpc/lib/server/http_server_test.go +++ b/tm2/pkg/bft/rpc/lib/server/http_server_test.go @@ -1,7 +1,6 @@ package rpcserver import ( - "bytes" "crypto/tls" "fmt" "io" @@ -41,7 +40,7 @@ func TestMaxOpenConnections(t *testing.T) { l, err := Listen("tcp://127.0.0.1:0", config) require.NoError(t, err) defer l.Close() - go StartHTTPServer(l, mux, log.TestingLogger(), config) + go StartHTTPServer(l, mux, log.NewTestingLogger(t), config) // Make N GET calls to the server. attempts := max * 2 @@ -83,7 +82,7 @@ func TestStartHTTPAndTLSServer(t *testing.T) { fmt.Fprint(w, "some body") }) - go StartHTTPAndTLSServer(ln, mux, "test.crt", "test.key", log.TestingLogger(), DefaultConfig()) + go StartHTTPAndTLSServer(ln, mux, "test.crt", "test.key", log.NewTestingLogger(t), DefaultConfig()) tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, @@ -161,11 +160,6 @@ func TestRecoverAndLogHandler(t *testing.T) { } }`, }, - { - name: "panic with nil", - panicArg: nil, - expectedResponse: ``, - }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -174,7 +168,7 @@ func TestRecoverAndLogHandler(t *testing.T) { var ( req, _ = http.NewRequest(http.MethodGet, "", nil) resp = httptest.NewRecorder() - logger = log.NewTMLogger(&bytes.Buffer{}) + logger = log.NewNoopLogger() // Create a handler that will always panic with argument tt.panicArg handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { panic(tt.panicArg) diff --git a/tm2/pkg/bft/rpc/lib/test/main.go b/tm2/pkg/bft/rpc/lib/test/main.go index fe7fc49c65e..3fd8ea0bf61 100644 --- a/tm2/pkg/bft/rpc/lib/test/main.go +++ b/tm2/pkg/bft/rpc/lib/test/main.go @@ -3,7 +3,6 @@ package main import ( "fmt" "net/http" - "os" "github.com/gnolang/gno/tm2/pkg/log" osm "github.com/gnolang/gno/tm2/pkg/os" @@ -27,7 +26,7 @@ type Result struct { func main() { var ( mux = http.NewServeMux() - logger = log.NewTMLogger(log.NewSyncWriter(os.Stdout)) + logger = log.NewNoopLogger() ) // Stop upon receiving SIGTERM or CTRL-C. diff --git a/tm2/pkg/bft/rpc/test/helpers.go b/tm2/pkg/bft/rpc/test/helpers.go index d8e1a498600..0b6d39c6839 100644 --- a/tm2/pkg/bft/rpc/test/helpers.go +++ b/tm2/pkg/bft/rpc/test/helpers.go @@ -28,7 +28,6 @@ type Options struct { var ( globalConfig *cfg.Config defaultOptions = Options{ - suppressStdout: false, recreateConfig: false, } ) @@ -114,13 +113,7 @@ func StopTendermint(node *nm.Node) { func NewTendermint(app abci.Application, opts *Options) *nm.Node { // Create & start node config := GetConfig(opts.recreateConfig) - var logger log.Logger - if opts.suppressStdout { - logger = log.NewNopLogger() - } else { - logger = log.NewTMLogger(log.NewSyncWriter(os.Stdout)) - logger.SetLevel(log.LevelError) - } + pvKeyFile := config.PrivValidatorKeyFile() pvKeyStateFile := config.PrivValidatorStateFile() pv := privval.LoadOrGenFilePV(pvKeyFile, pvKeyStateFile) @@ -132,7 +125,7 @@ func NewTendermint(app abci.Application, opts *Options) *nm.Node { node, err := nm.NewNode(config, pv, nodeKey, papp, nm.DefaultGenesisDocProviderFunc(config), nm.DefaultDBProvider, - logger) + log.NewNoopLogger()) if err != nil { panic(err) } diff --git a/tm2/pkg/bft/state/execution.go b/tm2/pkg/bft/state/execution.go index e7920459172..d831fc3678e 100644 --- a/tm2/pkg/bft/state/execution.go +++ b/tm2/pkg/bft/state/execution.go @@ -3,6 +3,8 @@ package state import ( "fmt" + "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/fail" @@ -14,10 +16,9 @@ import ( "github.com/gnolang/gno/tm2/pkg/crypto" dbm "github.com/gnolang/gno/tm2/pkg/db" "github.com/gnolang/gno/tm2/pkg/events" - "github.com/gnolang/gno/tm2/pkg/log" ) -//----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // BlockExecutor handles block execution and state updates. // It exposes ApplyBlock(), which validates & executes the block, updates state w/ ABCI responses, // then commits and updates the mempool atomically, then saves state. @@ -37,14 +38,14 @@ type BlockExecutor struct { // and update both with block results after commit. mempool mempl.Mempool - logger log.Logger + logger *slog.Logger } type BlockExecutorOption func(executor *BlockExecutor) // NewBlockExecutor returns a new BlockExecutor with a NopEventBus. // Call SetEventBus to provide one. -func NewBlockExecutor(db dbm.DB, logger log.Logger, proxyApp proxy.AppConnConsensus, mempool mempl.Mempool, options ...BlockExecutorOption) *BlockExecutor { +func NewBlockExecutor(db dbm.DB, logger *slog.Logger, proxyApp proxy.AppConnConsensus, mempool mempl.Mempool, options ...BlockExecutorOption) *BlockExecutor { res := &BlockExecutor{ db: db, proxyApp: proxyApp, @@ -143,7 +144,7 @@ func (blockExec *BlockExecutor) ApplyBlock(state State, blockID types.BlockID, b // Events are fired after everything else. // NOTE: if we crash between Commit and Save, events wont be fired during replay - fireEvents(blockExec.logger, blockExec.evsw, block, abciResponses) + fireEvents(blockExec.evsw, block, abciResponses) return state, nil } @@ -200,13 +201,13 @@ func (blockExec *BlockExecutor) Commit( return res.Data, err } -//--------------------------------------------------------- +// --------------------------------------------------------- // Helper functions for executing blocks and updating state // Executes block's transactions on proxyAppConn. // Returns a list of transaction results and updates to the validator set func execBlockOnProxyApp( - logger log.Logger, + logger *slog.Logger, proxyAppConn proxy.AppConnConsensus, block *types.Block, stateDB dbm.DB, @@ -398,7 +399,7 @@ func updateState( // Fire NewBlock, NewBlockHeader. // Fire TxEvent for every tx. // NOTE: if Tendermint crashes before commit, some or all of these events may be published again. -func fireEvents(logger log.Logger, evsw events.EventSwitch, block *types.Block, abciResponses *ABCIResponses) { +func fireEvents(evsw events.EventSwitch, block *types.Block, abciResponses *ABCIResponses) { evsw.FireEvent(types.EventNewBlock{ Block: block, ResultBeginBlock: abciResponses.BeginBlock, @@ -425,7 +426,7 @@ func fireEvents(logger log.Logger, evsw events.EventSwitch, block *types.Block, } } -//---------------------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------------------- // Execute block without state. TODO: eliminate // ExecCommitBlock executes and commits a block on the proxyApp without validating or mutating the state. @@ -433,7 +434,7 @@ func fireEvents(logger log.Logger, evsw events.EventSwitch, block *types.Block, func ExecCommitBlock( appConnConsensus proxy.AppConnConsensus, block *types.Block, - logger log.Logger, + logger *slog.Logger, stateDB dbm.DB, ) ([]byte, error) { _, err := execBlockOnProxyApp(logger, appConnConsensus, block, stateDB) diff --git a/tm2/pkg/bft/state/execution_test.go b/tm2/pkg/bft/state/execution_test.go index 25217ffccbe..18dd8746840 100644 --- a/tm2/pkg/bft/state/execution_test.go +++ b/tm2/pkg/bft/state/execution_test.go @@ -39,7 +39,7 @@ func TestApplyBlock(t *testing.T) { state, stateDB, _ := makeState(1, 1) - blockExec := sm.NewBlockExecutor(stateDB, log.TestingLogger(), proxyApp.Consensus(), mock.Mempool{}) + blockExec := sm.NewBlockExecutor(stateDB, log.NewTestingLogger(t), proxyApp.Consensus(), mock.Mempool{}) evsw := events.NewEventSwitch() blockExec.SetEventSwitch(evsw) @@ -90,7 +90,7 @@ func TestBeginBlockValidators(t *testing.T) { // block for height 2 block, _ := state.MakeBlock(2, makeTxs(2), lastCommit, state.Validators.GetProposer().Address) - _, err = sm.ExecCommitBlock(proxyApp.Consensus(), block, log.TestingLogger(), stateDB) + _, err = sm.ExecCommitBlock(proxyApp.Consensus(), block, log.NewTestingLogger(t), stateDB) require.Nil(t, err, tc.desc) // -> app receives a list of validators with a bool indicating if they signed @@ -273,7 +273,7 @@ func TestEndBlockValidatorUpdates(t *testing.T) { state, stateDB, _ := makeState(1, 1) - blockExec := sm.NewBlockExecutor(stateDB, log.TestingLogger(), proxyApp.Consensus(), mock.Mempool{}) + blockExec := sm.NewBlockExecutor(stateDB, log.NewTestingLogger(t), proxyApp.Consensus(), mock.Mempool{}) evsw := events.NewEventSwitch() err = evsw.Start() @@ -340,7 +340,7 @@ func TestEndBlockValidatorUpdatesResultingInEmptySet(t *testing.T) { defer proxyApp.Stop() state, stateDB, _ := makeState(1, 1) - blockExec := sm.NewBlockExecutor(stateDB, log.TestingLogger(), proxyApp.Consensus(), mock.Mempool{}) + blockExec := sm.NewBlockExecutor(stateDB, log.NewTestingLogger(t), proxyApp.Consensus(), mock.Mempool{}) block := makeBlock(state, 1) blockID := types.BlockID{Hash: block.Hash(), PartsHeader: block.MakePartSet(testPartSize).Header()} diff --git a/tm2/pkg/bft/state/validation_test.go b/tm2/pkg/bft/state/validation_test.go index c1941381de7..7ab9d1035ee 100644 --- a/tm2/pkg/bft/state/validation_test.go +++ b/tm2/pkg/bft/state/validation_test.go @@ -26,7 +26,7 @@ func TestValidateBlockHeader(t *testing.T) { defer proxyApp.Stop() state, stateDB, privVals := makeState(3, 1) - blockExec := sm.NewBlockExecutor(stateDB, log.TestingLogger(), proxyApp.Consensus(), mock.Mempool{}) + blockExec := sm.NewBlockExecutor(stateDB, log.NewTestingLogger(t), proxyApp.Consensus(), mock.Mempool{}) lastCommit := types.NewCommit(types.BlockID{}, nil) // some bad values @@ -89,7 +89,7 @@ func TestValidateBlockCommit(t *testing.T) { defer proxyApp.Stop() state, stateDB, privVals := makeState(1, 1) - blockExec := sm.NewBlockExecutor(stateDB, log.TestingLogger(), proxyApp.Consensus(), mock.Mempool{}) + blockExec := sm.NewBlockExecutor(stateDB, log.NewTestingLogger(t), proxyApp.Consensus(), mock.Mempool{}) lastCommit := types.NewCommit(types.BlockID{}, nil) wrongPrecommitsCommit := types.NewCommit(types.BlockID{}, nil) badPrivVal := types.NewMockPV() diff --git a/tm2/pkg/bft/store/store_test.go b/tm2/pkg/bft/store/store_test.go index fce566903c3..6b5dd8a96bb 100644 --- a/tm2/pkg/bft/store/store_test.go +++ b/tm2/pkg/bft/store/store_test.go @@ -1,7 +1,6 @@ package store import ( - "bytes" "fmt" "os" "runtime/debug" @@ -9,6 +8,8 @@ import ( "testing" "time" + "golang.org/x/exp/slog" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -44,7 +45,7 @@ func makeBlock(height int64, state sm.State, lastCommit *types.Commit) *types.Bl return block } -func makeStateAndBlockStore(logger log.Logger) (sm.State, *BlockStore, cleanupFunc) { +func makeStateAndBlockStore(logger *slog.Logger) (sm.State, *BlockStore, cleanupFunc) { config := cfg.ResetTestRoot("blockchain_reactor_test") // blockDB := dbm.NewDebugDB("blockDB", dbm.NewMemDB()) // stateDB := dbm.NewDebugDB("stateDB", dbm.NewMemDB()) @@ -119,7 +120,8 @@ var ( func TestMain(m *testing.M) { var cleanup cleanupFunc - state, _, cleanup = makeStateAndBlockStore(log.NewTMLogger(new(bytes.Buffer))) + + state, _, cleanup = makeStateAndBlockStore(log.NewNoopLogger()) block = makeBlock(1, state, new(types.Commit)) partSet = block.MakePartSet(2) part1 = partSet.GetPart(0) @@ -135,7 +137,7 @@ func TestMain(m *testing.M) { func TestBlockStoreSaveLoadBlock(t *testing.T) { t.Parallel() - state, bs, cleanup := makeStateAndBlockStore(log.NewTMLogger(new(bytes.Buffer))) + state, bs, cleanup := makeStateAndBlockStore(log.NewNoopLogger()) defer cleanup() require.Equal(t, bs.Height(), int64(0), "initially the height should be zero") @@ -396,7 +398,7 @@ func TestLoadBlockMeta(t *testing.T) { func TestBlockFetchAtHeight(t *testing.T) { t.Parallel() - state, bs, cleanup := makeStateAndBlockStore(log.NewTMLogger(new(bytes.Buffer))) + state, bs, cleanup := makeStateAndBlockStore(log.NewNoopLogger()) defer cleanup() require.Equal(t, bs.Height(), int64(0), "initially the height should be zero") block := makeBlock(bs.Height()+1, state, new(types.Commit)) diff --git a/tm2/pkg/bft/wal/wal.go b/tm2/pkg/bft/wal/wal.go index a4a14d638dd..26f3deeb49c 100644 --- a/tm2/pkg/bft/wal/wal.go +++ b/tm2/pkg/bft/wal/wal.go @@ -11,11 +11,12 @@ import ( "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" "github.com/gnolang/gno/tm2/pkg/errors" - "github.com/gnolang/gno/tm2/pkg/log" osm "github.com/gnolang/gno/tm2/pkg/os" "github.com/gnolang/gno/tm2/pkg/service" ) @@ -59,7 +60,7 @@ type MetaMessage struct { // WAL is an interface for any write-ahead logger. type WAL interface { // config methods - SetLogger(l log.Logger) + SetLogger(l *slog.Logger) // write methods Write(WALMessage) error @@ -128,7 +129,7 @@ func (wal *baseWAL) Group() *auto.Group { return wal.group } -func (wal *baseWAL) SetLogger(l log.Logger) { +func (wal *baseWAL) SetLogger(l *slog.Logger) { wal.BaseService.Logger = l wal.group.SetLogger(l) } @@ -644,7 +645,7 @@ type NopWAL struct{} var _ WAL = NopWAL{} -func (NopWAL) SetLogger(l log.Logger) {} +func (NopWAL) SetLogger(l *slog.Logger) {} func (NopWAL) Write(m WALMessage) error { return nil } func (NopWAL) WriteSync(m WALMessage) error { return nil } func (NopWAL) WriteMetaSync(m MetaMessage) error { return nil } diff --git a/tm2/pkg/bft/wal/wal_test.go b/tm2/pkg/bft/wal/wal_test.go index 322ee82bc2b..57386a701e1 100644 --- a/tm2/pkg/bft/wal/wal_test.go +++ b/tm2/pkg/bft/wal/wal_test.go @@ -180,7 +180,7 @@ func TestWALPeriodicSync(t *testing.T) { // Is this needed? wal.SetFlushInterval(walTestFlushInterval) - wal.SetLogger(log.TestingLogger()) + wal.SetLogger(log.NewNoopLogger()) // Take snapshot of starting state. startInfo := wal.Group().ReadGroupInfo() diff --git a/tm2/pkg/log/logger.go b/tm2/pkg/log/logger.go deleted file mode 100644 index 8c34c994833..00000000000 --- a/tm2/pkg/log/logger.go +++ /dev/null @@ -1,48 +0,0 @@ -package log - -import ( - "io" - "sync" -) - -type LogLevel int - -const ( - LevelDebug LogLevel = iota - LevelInfo - LevelError -) - -type Logger interface { - Debug(msg string, keyvals ...interface{}) - Info(msg string, keyvals ...interface{}) - Error(msg string, keyvals ...interface{}) - - With(keyvals ...interface{}) Logger - - SetLevel(LogLevel) -} - -//---------------------------------------- - -// NewSyncWriter returns a new writer that is safe for concurrent use by -// multiple goroutines. Writes to the returned writer are passed on to w. If -// another write is already in progress, the calling goroutine blocks until -// the writer is available. -func NewSyncWriter(w io.Writer) io.Writer { - return &syncWriter{Writer: w} -} - -// syncWriter synchronizes concurrent writes to an io.Writer. -type syncWriter struct { - sync.Mutex - io.Writer -} - -// Write writes p to the underlying io.Writer. If another write is already in -// progress, the calling goroutine blocks until the syncWriter is available. -func (w *syncWriter) Write(p []byte) (n int, err error) { - w.Lock() - defer w.Unlock() - return w.Writer.Write(p) -} diff --git a/tm2/pkg/log/noop.go b/tm2/pkg/log/noop.go new file mode 100644 index 00000000000..b7c465ede0f --- /dev/null +++ b/tm2/pkg/log/noop.go @@ -0,0 +1,34 @@ +package log + +import ( + "context" + + "golang.org/x/exp/slog" +) + +// NewNoopLogger returns a new no-op logger +func NewNoopLogger() *slog.Logger { + return slog.New(newNoopHandler()) +} + +type noopHandler struct{} + +func newNoopHandler() *noopHandler { + return &noopHandler{} +} + +func (n *noopHandler) Enabled(_ context.Context, _ slog.Level) bool { + return false +} + +func (n *noopHandler) Handle(_ context.Context, _ slog.Record) error { + return nil +} + +func (n *noopHandler) WithAttrs(_ []slog.Attr) slog.Handler { + return n +} + +func (n *noopHandler) WithGroup(_ string) slog.Handler { + return n +} diff --git a/tm2/pkg/log/nop_logger.go b/tm2/pkg/log/nop_logger.go deleted file mode 100644 index 5a12b088082..00000000000 --- a/tm2/pkg/log/nop_logger.go +++ /dev/null @@ -1,19 +0,0 @@ -package log - -type nopLogger struct{} - -// Interface assertions -var _ Logger = (*nopLogger)(nil) - -// NewNopLogger returns a logger that doesn't do anything. -func NewNopLogger() Logger { return &nopLogger{} } - -func (nopLogger) Info(string, ...interface{}) {} -func (nopLogger) Debug(string, ...interface{}) {} -func (nopLogger) Error(string, ...interface{}) {} - -func (l *nopLogger) With(...interface{}) Logger { - return l -} - -func (l *nopLogger) SetLevel(LogLevel) {} diff --git a/tm2/pkg/log/testing.go b/tm2/pkg/log/testing.go new file mode 100644 index 00000000000..be610ee38d2 --- /dev/null +++ b/tm2/pkg/log/testing.go @@ -0,0 +1,75 @@ +package log + +import ( + "fmt" + "os" + "path/filepath" + "strings" + "testing" + "time" + + "github.com/jaekwon/testify/require" + "golang.org/x/exp/slog" +) + +// NewTestingLogger returns a new testing logger +func NewTestingLogger(t *testing.T) *slog.Logger { + t.Helper() + + // Parse the environment vars + envLevel := os.Getenv("LOG_LEVEL") + envPath := os.Getenv("LOG_PATH_DIR") + + if !testing.Verbose() && envLevel == "" && envPath == "" { + return NewNoopLogger() + } + + // Default logger config + logLevel := slog.LevelError + logOutput := os.Stdout + + // Set the logger level, if any + switch strings.ToLower(envLevel) { + case "info": + logLevel = slog.LevelInfo + case "debug": + logLevel = slog.LevelDebug + case "warn": + logLevel = slog.LevelWarn + } + + // Check if the log output needs to be a file + if envPath != "" { + // Create the top-level log directory + if err := os.Mkdir(envPath, 0o755); err != nil && !os.IsExist(err) { + t.Fatalf("Failed to create log directory: %v", err) + } + + logName := fmt.Sprintf( + "%s-%d.log", + strings.ReplaceAll(t.Name(), "/", "_"), // unique test name + time.Now().Unix(), // unique test timestamp + ) + logPath := filepath.Join(envPath, logName) + + logFile, err := os.Create(logPath) + require.NoError(t, err) + + t.Cleanup(func() { + _ = logFile.Close() + }) + + logOutput = logFile + } + + // Create the log handler + logHandler := slog.NewTextHandler( + logOutput, + &slog.HandlerOptions{ + AddSource: true, + Level: logLevel, + }, + ) + + return slog.New(logHandler) +} diff --git a/tm2/pkg/log/testing_logger.go b/tm2/pkg/log/testing_logger.go deleted file mode 100644 index 05e91b54a7d..00000000000 --- a/tm2/pkg/log/testing_logger.go +++ /dev/null @@ -1,58 +0,0 @@ -package log - -import ( - "io" - "os" - "testing" - - "github.com/gnolang/gno/tm2/pkg/colors" -) - -// reuse the same logger across all tests -var _testingLogger Logger - -// TestingLogger returns a TMLogger which writes to STDOUT if testing being run -// with the verbose (-v) flag, NopLogger otherwise. -// -// Note that the call to TestingLogger() must be made -// inside a test (not in the init func) because -// verbose flag only set at the time of testing. -func TestingLogger() Logger { - return TestingLoggerWithOutput(os.Stdout) -} - -// TestingLoggerWOutput returns a TMLogger which writes to (w io.Writer) if testing being run -// with the verbose (-v) flag, NopLogger otherwise. -// -// Note that the call to TestingLoggerWithOutput(w io.Writer) must be made -// inside a test (not in the init func) because -// verbose flag only set at the time of testing. -func TestingLoggerWithOutput(w io.Writer) Logger { - if _testingLogger != nil { - return _testingLogger - } - - if testing.Verbose() { - _testingLogger = NewTMLogger(NewSyncWriter(w)) - } else { - _testingLogger = NewNopLogger() - } - - return _testingLogger -} - -// TestingLoggerWithColorFn allow you to provide your own color function. See -// TestingLogger for documentation. -func TestingLoggerWithColorFn(colorFn func(keyvals ...interface{}) colors.Color) Logger { - if _testingLogger != nil { - return _testingLogger - } - - if testing.Verbose() { - _testingLogger = NewTMLoggerWithColorFn(NewSyncWriter(os.Stdout), colorFn) - } else { - _testingLogger = NewNopLogger() - } - - return _testingLogger -} diff --git a/tm2/pkg/log/tm_logger.go b/tm2/pkg/log/tm_logger.go deleted file mode 100644 index 555ece714cd..00000000000 --- a/tm2/pkg/log/tm_logger.go +++ /dev/null @@ -1,136 +0,0 @@ -package log - -import ( - "fmt" - "io" - - "github.com/gnolang/gno/tm2/pkg/colors" -) - -const ( - logKeyLevel = ".level" - logKeyMsg = ".msg" -) - -type tmLogger struct { - level LogLevel - colorFn func(keyvals ...interface{}) colors.Color - writer io.Writer -} - -var _ Logger = (*tmLogger)(nil) - -func NewTMLogger(w io.Writer) *tmLogger { - // Color by level value - colorFn := func(keyvals ...interface{}) colors.Color { - if keyvals[0] != logKeyLevel { - panic(fmt.Sprintf("expected level key to be first, got %v", keyvals[0])) - } - switch keyvals[1].(LogLevel) { - case LevelDebug: - return colors.Gray - case LevelError: - return colors.Red - default: - return colors.None - } - } - return &tmLogger{ - level: LevelDebug, - colorFn: colorFn, - writer: w, - } -} - -// NewTMLoggerWithColorFn allows you to provide your own color function. -func NewTMLoggerWithColorFn(w io.Writer, colorFn func(keyvals ...interface{}) colors.Color) *tmLogger { - return &tmLogger{ - level: LevelDebug, - colorFn: colorFn, - writer: w, - } -} - -func (l *tmLogger) SetLevel(lvl LogLevel) { - l.level = lvl -} - -// Debug logs a message at level Debug. -func (l *tmLogger) Debug(msg string, keyvals ...interface{}) { - if l.level <= LevelDebug { - writeLog(l.writer, LevelDebug, l.colorFn, msg, keyvals...) - } -} - -// Info logs a message at level Info. -func (l *tmLogger) Info(msg string, keyvals ...interface{}) { - if l.level <= LevelInfo { - writeLog(l.writer, LevelInfo, l.colorFn, msg, keyvals...) - } -} - -// Error logs a message at level Error. -func (l *tmLogger) Error(msg string, keyvals ...interface{}) { - if l.level <= LevelError { - writeLog(l.writer, LevelError, l.colorFn, msg, keyvals...) - } -} - -// With returns a new contextual logger with keyvals prepended to those passed -// to calls to Info, Debug or Error. -func (l *tmLogger) With(keyvals ...interface{}) Logger { - return newWithLogger(l, keyvals) -} - -//---------------------------------------- - -type withLogger struct { - base Logger - keyvals []interface{} -} - -var _ Logger = (*withLogger)(nil) - -func newWithLogger(base Logger, keyvals []interface{}) *withLogger { - return &withLogger{ - base: base, - keyvals: keyvals, - } -} - -func (l *withLogger) Debug(msg string, keyvals ...interface{}) { - keyvals = append(keyvals, l.keyvals) - l.base.Debug(msg, keyvals) -} - -func (l *withLogger) Info(msg string, keyvals ...interface{}) { - keyvals = append(keyvals, l.keyvals) - l.base.Info(msg, keyvals) -} - -func (l *withLogger) Error(msg string, keyvals ...interface{}) { - keyvals = append(keyvals, l.keyvals) - l.base.Error(msg, keyvals) -} - -func (l *withLogger) With(keyvals ...interface{}) Logger { - return newWithLogger(l, keyvals) -} - -func (l *withLogger) SetLevel(LogLevel) { - panic("SetLevel not supported on derived WithLogger") -} - -//---------------------------------------- - -func writeLog(w io.Writer, level LogLevel, colorFn func(keyvals ...interface{}) colors.Color, msg string, keyvals ...interface{}) { - keyvals = append([]interface{}{ - logKeyLevel, level, - logKeyMsg, msg, - }, keyvals...) - color := colorFn(keyvals...) - str := fmt.Sprintln(keyvals...) - str = str[:len(str)-1] - str = color(str) - fmt.Fprintln(w, str) -} diff --git a/tm2/pkg/log/tm_logger_test.go b/tm2/pkg/log/tm_logger_test.go deleted file mode 100644 index 43ca98eb0f9..00000000000 --- a/tm2/pkg/log/tm_logger_test.go +++ /dev/null @@ -1,47 +0,0 @@ -package log_test - -import ( - "bytes" - "io" - "strings" - "testing" - - "github.com/gnolang/gno/tm2/pkg/log" -) - -func TestLoggerLogsItsErrors(t *testing.T) { - t.Parallel() - - var buf bytes.Buffer - - logger := log.NewTMLogger(&buf) - logger.Info("foo", "baz baz", "bar") - msg := strings.TrimSpace(buf.String()) - if !strings.Contains(msg, "foo") { - t.Errorf("Expected logger msg to contain foo, got %s", msg) - } -} - -func BenchmarkTMLoggerSimple(b *testing.B) { - benchmarkRunner(b, log.NewTMLogger(io.Discard), baseInfoMessage) -} - -func BenchmarkTMLoggerContextual(b *testing.B) { - benchmarkRunner(b, log.NewTMLogger(io.Discard), withInfoMessage) -} - -func benchmarkRunner(b *testing.B, logger log.Logger, f func(log.Logger)) { - b.Helper() - - lc := logger.With("common_key", "common_value") - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - f(lc) - } -} - -var ( - baseInfoMessage = func(logger log.Logger) { logger.Info("foo_message", "foo_key", "foo_value") } - withInfoMessage = func(logger log.Logger) { logger.With("a", "b").Info("c", "d", "f") } -) diff --git a/tm2/pkg/p2p/conn/connection.go b/tm2/pkg/p2p/conn/connection.go index 1f726410aaf..7f0cf39fe5f 100644 --- a/tm2/pkg/p2p/conn/connection.go +++ b/tm2/pkg/p2p/conn/connection.go @@ -13,10 +13,11 @@ 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" - "github.com/gnolang/gno/tm2/pkg/log" "github.com/gnolang/gno/tm2/pkg/maths" "github.com/gnolang/gno/tm2/pkg/service" "github.com/gnolang/gno/tm2/pkg/timer" @@ -197,7 +198,7 @@ func NewMConnectionWithConfig(conn net.Conn, chDescs []*ChannelDescriptor, onRec return mconn } -func (c *MConnection) SetLogger(l log.Logger) { +func (c *MConnection) SetLogger(l *slog.Logger) { c.BaseService.SetLogger(l) for _, ch := range c.channels { ch.SetLogger(l) @@ -732,7 +733,7 @@ type Channel struct { maxPacketMsgPayloadSize int - Logger log.Logger + Logger *slog.Logger } func newChannel(conn *MConnection, desc ChannelDescriptor) *Channel { @@ -749,7 +750,7 @@ func newChannel(conn *MConnection, desc ChannelDescriptor) *Channel { } } -func (ch *Channel) SetLogger(l log.Logger) { +func (ch *Channel) SetLogger(l *slog.Logger) { ch.Logger = l } diff --git a/tm2/pkg/p2p/conn/connection_test.go b/tm2/pkg/p2p/conn/connection_test.go index 68f7fbc0841..7bbe88ded22 100644 --- a/tm2/pkg/p2p/conn/connection_test.go +++ b/tm2/pkg/p2p/conn/connection_test.go @@ -16,23 +16,32 @@ import ( const maxPingPongPacketSize = 1024 // bytes -func createTestMConnection(conn net.Conn) *MConnection { +func createTestMConnection(t *testing.T, conn net.Conn) *MConnection { + t.Helper() + onReceive := func(chID byte, msgBytes []byte) { } onError := func(r interface{}) { } - c := createMConnectionWithCallbacks(conn, onReceive, onError) - c.SetLogger(log.TestingLogger()) + c := createMConnectionWithCallbacks(t, conn, onReceive, onError) + c.SetLogger(log.NewTestingLogger(t)) return c } -func createMConnectionWithCallbacks(conn net.Conn, onReceive func(chID byte, msgBytes []byte), onError func(r interface{})) *MConnection { +func createMConnectionWithCallbacks( + t *testing.T, + conn net.Conn, + onReceive func(chID byte, msgBytes []byte), + onError func(r interface{}), +) *MConnection { + t.Helper() + cfg := DefaultMConnConfig() cfg.PingInterval = 90 * time.Millisecond cfg.PongTimeout = 45 * time.Millisecond chDescs := []*ChannelDescriptor{{ID: 0x01, Priority: 1, SendQueueCapacity: 1}} c := NewMConnectionWithConfig(conn, chDescs, onReceive, onError, cfg) - c.SetLogger(log.TestingLogger()) + c.SetLogger(log.NewTestingLogger(t)) return c } @@ -43,7 +52,7 @@ func TestMConnectionSendFlushStop(t *testing.T) { defer server.Close() //nolint: errcheck defer client.Close() //nolint: errcheck - clientConn := createTestMConnection(client) + clientConn := createTestMConnection(t, client) err := clientConn.Start() require.Nil(t, err) defer clientConn.Stop() @@ -90,7 +99,7 @@ func TestMConnectionSend(t *testing.T) { defer server.Close() //nolint: errcheck defer client.Close() //nolint: errcheck - mconn := createTestMConnection(client) + mconn := createTestMConnection(t, client) err := mconn.Start() require.Nil(t, err) defer mconn.Stop() @@ -131,12 +140,12 @@ func TestMConnectionReceive(t *testing.T) { onError := func(r interface{}) { errorsCh <- r } - mconn1 := createMConnectionWithCallbacks(client, onReceive, onError) + mconn1 := createMConnectionWithCallbacks(t, client, onReceive, onError) err := mconn1.Start() require.Nil(t, err) defer mconn1.Stop() - mconn2 := createTestMConnection(server) + mconn2 := createTestMConnection(t, server) err = mconn2.Start() require.Nil(t, err) defer mconn2.Stop() @@ -161,7 +170,7 @@ func TestMConnectionStatus(t *testing.T) { defer server.Close() //nolint: errcheck defer client.Close() //nolint: errcheck - mconn := createTestMConnection(client) + mconn := createTestMConnection(t, client) err := mconn.Start() require.Nil(t, err) defer mconn.Stop() @@ -186,7 +195,7 @@ func TestMConnectionPongTimeoutResultsInError(t *testing.T) { onError := func(r interface{}) { errorsCh <- r } - mconn := createMConnectionWithCallbacks(client, onReceive, onError) + mconn := createMConnectionWithCallbacks(t, client, onReceive, onError) err := mconn.Start() require.Nil(t, err) defer mconn.Stop() @@ -227,7 +236,7 @@ func TestMConnectionMultiplePongsInTheBeginning(t *testing.T) { onError := func(r interface{}) { errorsCh <- r } - mconn := createMConnectionWithCallbacks(client, onReceive, onError) + mconn := createMConnectionWithCallbacks(t, client, onReceive, onError) err := mconn.Start() require.Nil(t, err) defer mconn.Stop() @@ -282,7 +291,7 @@ func TestMConnectionMultiplePings(t *testing.T) { onError := func(r interface{}) { errorsCh <- r } - mconn := createMConnectionWithCallbacks(client, onReceive, onError) + mconn := createMConnectionWithCallbacks(t, client, onReceive, onError) err := mconn.Start() require.Nil(t, err) defer mconn.Stop() @@ -325,7 +334,7 @@ func TestMConnectionPingPongs(t *testing.T) { onError := func(r interface{}) { errorsCh <- r } - mconn := createMConnectionWithCallbacks(client, onReceive, onError) + mconn := createMConnectionWithCallbacks(t, client, onReceive, onError) err := mconn.Start() require.Nil(t, err) defer mconn.Stop() @@ -378,7 +387,7 @@ func TestMConnectionStopsAndReturnsError(t *testing.T) { onError := func(r interface{}) { errorsCh <- r } - mconn := createMConnectionWithCallbacks(client, onReceive, onError) + mconn := createMConnectionWithCallbacks(t, client, onReceive, onError) err := mconn.Start() require.Nil(t, err) defer mconn.Stop() @@ -412,17 +421,17 @@ func newClientAndServerConnsForReadErrors(t *testing.T, chOnErr chan struct{}) ( {ID: 0x02, Priority: 1, SendQueueCapacity: 1}, } mconnClient := NewMConnection(client, chDescs, onReceive, onError) - mconnClient.SetLogger(log.TestingLogger().With("module", "client")) + mconnClient.SetLogger(log.NewNoopLogger().With("module", "client")) err := mconnClient.Start() require.Nil(t, err) // create server conn with 1 channel // it fires on chOnErr when there's an error - serverLogger := log.TestingLogger().With("module", "server") + serverLogger := log.NewNoopLogger().With("module", "server") onError = func(r interface{}) { chOnErr <- struct{}{} } - mconnServer := createMConnectionWithCallbacks(server, onReceive, onError) + mconnServer := createMConnectionWithCallbacks(t, server, onReceive, onError) mconnServer.SetLogger(serverLogger) err = mconnServer.Start() require.Nil(t, err) @@ -545,7 +554,7 @@ func TestMConnectionTrySend(t *testing.T) { defer server.Close() defer client.Close() - mconn := createTestMConnection(client) + mconn := createTestMConnection(t, client) err := mconn.Start() require.Nil(t, err) defer mconn.Stop() diff --git a/tm2/pkg/p2p/mock/reactor.go b/tm2/pkg/p2p/mock/reactor.go index 335366920db..fe123fdc0b2 100644 --- a/tm2/pkg/p2p/mock/reactor.go +++ b/tm2/pkg/p2p/mock/reactor.go @@ -13,7 +13,7 @@ type Reactor struct { func NewReactor() *Reactor { r := &Reactor{} r.BaseReactor = *p2p.NewBaseReactor("Reactor", r) - r.SetLogger(log.TestingLogger()) + r.SetLogger(log.NewNoopLogger()) return r } diff --git a/tm2/pkg/p2p/peer.go b/tm2/pkg/p2p/peer.go index c9eea1eca65..11814b585c1 100644 --- a/tm2/pkg/p2p/peer.go +++ b/tm2/pkg/p2p/peer.go @@ -4,8 +4,9 @@ import ( "fmt" "net" + "golang.org/x/exp/slog" + "github.com/gnolang/gno/tm2/pkg/cmap" - "github.com/gnolang/gno/tm2/pkg/log" connm "github.com/gnolang/gno/tm2/pkg/p2p/conn" "github.com/gnolang/gno/tm2/pkg/service" ) @@ -156,7 +157,7 @@ func (p *peer) String() string { // Implements service.Service // SetLogger implements BaseService. -func (p *peer) SetLogger(l log.Logger) { +func (p *peer) SetLogger(l *slog.Logger) { p.Logger = l p.mconn.SetLogger(l) } diff --git a/tm2/pkg/p2p/peer_test.go b/tm2/pkg/p2p/peer_test.go index 8841e34cc83..28217c4486e 100644 --- a/tm2/pkg/p2p/peer_test.go +++ b/tm2/pkg/p2p/peer_test.go @@ -28,7 +28,7 @@ func TestPeerBasic(t *testing.T) { rp.Start() defer rp.Stop() - p, err := createOutboundPeerAndPerformHandshake(rp.Addr(), cfg, conn.DefaultMConnConfig()) + p, err := createOutboundPeerAndPerformHandshake(t, rp.Addr(), cfg, conn.DefaultMConnConfig()) require.Nil(err) err = p.Start() @@ -56,7 +56,7 @@ func TestPeerSend(t *testing.T) { rp.Start() defer rp.Stop() - p, err := createOutboundPeerAndPerformHandshake(rp.Addr(), config, conn.DefaultMConnConfig()) + p, err := createOutboundPeerAndPerformHandshake(t, rp.Addr(), config, conn.DefaultMConnConfig()) require.Nil(err) err = p.Start() @@ -69,10 +69,13 @@ func TestPeerSend(t *testing.T) { } func createOutboundPeerAndPerformHandshake( + t *testing.T, addr *NetAddress, config *config.P2PConfig, mConfig conn.MConnConfig, ) (*peer, error) { + t.Helper() + chDescs := []*conn.ChannelDescriptor{ {ID: testCh, Priority: 1}, } @@ -90,7 +93,7 @@ func createOutboundPeerAndPerformHandshake( } p := newPeer(pc, mConfig, peerNodeInfo, reactorsByCh, chDescs, func(p Peer, r interface{}) {}) - p.SetLogger(log.TestingLogger().With("peer", addr)) + p.SetLogger(log.NewTestingLogger(t).With("peer", addr)) return p, nil } diff --git a/tm2/pkg/p2p/switch_test.go b/tm2/pkg/p2p/switch_test.go index 9e82e20bca1..a7033b466fe 100644 --- a/tm2/pkg/p2p/switch_test.go +++ b/tm2/pkg/p2p/switch_test.go @@ -52,7 +52,7 @@ func NewTestReactor(channels []*conn.ChannelDescriptor, logMessages bool) *TestR msgsReceived: make(map[byte][]PeerMessage), } tr.BaseReactor = *NewBaseReactor("TestReactor", tr) - tr.SetLogger(log.TestingLogger()) + tr.SetLogger(log.NewNoopLogger()) return tr } diff --git a/tm2/pkg/p2p/test_util.go b/tm2/pkg/p2p/test_util.go index 7ac46a07266..3e7abbc6c6f 100644 --- a/tm2/pkg/p2p/test_util.go +++ b/tm2/pkg/p2p/test_util.go @@ -17,7 +17,7 @@ import ( const testCh = 0x01 -//------------------------------------------------ +// ------------------------------------------------ func AddPeerToSwitchPeerSet(sw *Switch, peer Peer) { sw.peers.Add(peer) @@ -33,7 +33,7 @@ func CreateRandomPeer(outbound bool) *peer { nodeInfo: NodeInfo{NetAddress: netAddr}, mconn: &conn.MConnection{}, } - p.SetLogger(log.TestingLogger().With("peer", addr)) + p.SetLogger(log.NewNoopLogger().With("peer", addr)) return p } @@ -53,7 +53,7 @@ func CreateRoutableAddr() (addr string, netAddr *NetAddress) { return } -//------------------------------------------------------------------ +// ------------------------------------------------------------------ // Connects switches via arbitrary net.Conn. Used for testing. const TEST_HOST = "localhost" @@ -175,7 +175,7 @@ func MakeSwitch( // TODO: let the config be passed in? sw := initSwitch(i, NewSwitch(cfg, t, opts...)) - sw.SetLogger(log.TestingLogger().With("switch", i)) + sw.SetLogger(log.NewNoopLogger().With("switch", i)) sw.SetNodeKey(&nodeKey) for ch := range sw.reactorsByCh { @@ -223,7 +223,7 @@ func testPeerConn( return newPeerConn(outbound, persistent, conn, socketAddr), nil } -//---------------------------------------------------------------- +// ---------------------------------------------------------------- // rand node info func testNodeInfo(id ID, name string) NodeInfo { diff --git a/tm2/pkg/p2p/upnp/probe.go b/tm2/pkg/p2p/upnp/probe.go index 6a2c1d8bf7d..29498124aa7 100644 --- a/tm2/pkg/p2p/upnp/probe.go +++ b/tm2/pkg/p2p/upnp/probe.go @@ -5,7 +5,7 @@ import ( "net" "time" - "github.com/gnolang/gno/tm2/pkg/log" + "golang.org/x/exp/slog" ) type UPNPCapabilities struct { @@ -13,7 +13,7 @@ type UPNPCapabilities struct { Hairpin bool } -func makeUPNPListener(intPort int, extPort int, logger log.Logger) (NAT, net.Listener, net.IP, error) { +func makeUPNPListener(intPort int, extPort int, logger *slog.Logger) (NAT, net.Listener, net.IP, error) { nat, err := Discover() if err != nil { return nil, nil, nil, fmt.Errorf("NAT upnp could not be discovered: %w", err) @@ -40,7 +40,7 @@ func makeUPNPListener(intPort int, extPort int, logger log.Logger) (NAT, net.Lis return nat, listener, ext, nil } -func testHairpin(listener net.Listener, extAddr string, logger log.Logger) (supportsHairpin bool) { +func testHairpin(listener net.Listener, extAddr string, logger *slog.Logger) (supportsHairpin bool) { // Listener go func() { inConn, err := listener.Accept() @@ -81,7 +81,7 @@ func testHairpin(listener net.Listener, extAddr string, logger log.Logger) (supp return supportsHairpin } -func Probe(logger log.Logger) (caps UPNPCapabilities, err error) { +func Probe(logger *slog.Logger) (caps UPNPCapabilities, err error) { logger.Info("Probing for UPnP!") intPort, extPort := 8001, 8001 diff --git a/tm2/pkg/sdk/auth/keeper.go b/tm2/pkg/sdk/auth/keeper.go index c814eb21d9f..405256c6877 100644 --- a/tm2/pkg/sdk/auth/keeper.go +++ b/tm2/pkg/sdk/auth/keeper.go @@ -3,9 +3,10 @@ package auth import ( "fmt" + "golang.org/x/exp/slog" + "github.com/gnolang/gno/tm2/pkg/amino" "github.com/gnolang/gno/tm2/pkg/crypto" - "github.com/gnolang/gno/tm2/pkg/log" "github.com/gnolang/gno/tm2/pkg/sdk" "github.com/gnolang/gno/tm2/pkg/std" "github.com/gnolang/gno/tm2/pkg/store" @@ -32,7 +33,7 @@ func NewAccountKeeper( } // Logger returns a module-specific logger. -func (ak AccountKeeper) Logger(ctx sdk.Context) log.Logger { +func (ak AccountKeeper) Logger(ctx sdk.Context) *slog.Logger { return ctx.Logger().With("module", fmt.Sprintf("auth")) } diff --git a/tm2/pkg/sdk/auth/test_common.go b/tm2/pkg/sdk/auth/test_common.go index ee4153184a4..13b2ee5c55a 100644 --- a/tm2/pkg/sdk/auth/test_common.go +++ b/tm2/pkg/sdk/auth/test_common.go @@ -31,7 +31,7 @@ func setupTestEnv() testEnv { acck := NewAccountKeeper(authCapKey, std.ProtoBaseAccount) bank := NewDummyBankKeeper(acck) - ctx := sdk.NewContext(sdk.RunTxModeDeliver, ms, &bft.Header{Height: 1, ChainID: "test-chain-id"}, log.NewNopLogger()) + ctx := sdk.NewContext(sdk.RunTxModeDeliver, ms, &bft.Header{Height: 1, ChainID: "test-chain-id"}, log.NewNoopLogger()) ctx = ctx.WithValue(AuthParamsContextKey{}, DefaultParams()) ctx = ctx.WithConsensusParams(&abci.ConsensusParams{ Block: &abci.BlockParams{ diff --git a/tm2/pkg/sdk/bank/common_test.go b/tm2/pkg/sdk/bank/common_test.go index b78ae702cbb..fcbd5d2cb94 100644 --- a/tm2/pkg/sdk/bank/common_test.go +++ b/tm2/pkg/sdk/bank/common_test.go @@ -29,7 +29,7 @@ func setupTestEnv() testEnv { ms.MountStoreWithDB(authCapKey, iavl.StoreConstructor, db) ms.LoadLatestVersion() - ctx := sdk.NewContext(sdk.RunTxModeDeliver, ms, &bft.Header{ChainID: "test-chain-id"}, log.NewNopLogger()) + ctx := sdk.NewContext(sdk.RunTxModeDeliver, ms, &bft.Header{ChainID: "test-chain-id"}, log.NewNoopLogger()) acck := auth.NewAccountKeeper( authCapKey, std.ProtoBaseAccount, ) diff --git a/tm2/pkg/sdk/bank/keeper.go b/tm2/pkg/sdk/bank/keeper.go index dfbef78f016..87791258108 100644 --- a/tm2/pkg/sdk/bank/keeper.go +++ b/tm2/pkg/sdk/bank/keeper.go @@ -3,8 +3,9 @@ package bank import ( "fmt" + "golang.org/x/exp/slog" + "github.com/gnolang/gno/tm2/pkg/crypto" - "github.com/gnolang/gno/tm2/pkg/log" "github.com/gnolang/gno/tm2/pkg/sdk" "github.com/gnolang/gno/tm2/pkg/sdk/auth" "github.com/gnolang/gno/tm2/pkg/std" @@ -178,7 +179,7 @@ func (bank BankKeeper) SetCoins(ctx sdk.Context, addr crypto.Address, amt std.Co return nil } -//---------------------------------------- +// ---------------------------------------- // ViewKeeper // ViewKeeperI defines a module interface that facilitates read only access to @@ -201,7 +202,7 @@ func NewViewKeeper(acck auth.AccountKeeper) ViewKeeper { } // Logger returns a module-specific logger. -func (view ViewKeeper) Logger(ctx sdk.Context) log.Logger { +func (view ViewKeeper) Logger(ctx sdk.Context) *slog.Logger { return ctx.Logger().With("module", fmt.Sprintf("x/%s", ModuleName)) } diff --git a/tm2/pkg/sdk/baseapp.go b/tm2/pkg/sdk/baseapp.go index 1d356f7ad65..e564435456a 100644 --- a/tm2/pkg/sdk/baseapp.go +++ b/tm2/pkg/sdk/baseapp.go @@ -8,12 +8,13 @@ import ( "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" dbm "github.com/gnolang/gno/tm2/pkg/db" "github.com/gnolang/gno/tm2/pkg/errors" - "github.com/gnolang/gno/tm2/pkg/log" "github.com/gnolang/gno/tm2/pkg/std" "github.com/gnolang/gno/tm2/pkg/store" ) @@ -27,7 +28,7 @@ var ( // BaseApp reflects the ABCI application implementation. type BaseApp struct { // initialized on creation - logger log.Logger + logger *slog.Logger name string // application name from abci.Info db dbm.DB // common DB backend cms store.CommitMultiStore // Main (uncached) state @@ -80,7 +81,12 @@ var _ abci.Application = (*BaseApp)(nil) // // NOTE: The db is used to store the version number for now. func NewBaseApp( - name string, logger log.Logger, db dbm.DB, baseKey store.StoreKey, mainKey store.StoreKey, options ...func(*BaseApp), + name string, + logger *slog.Logger, + db dbm.DB, + baseKey store.StoreKey, + mainKey store.StoreKey, + options ...func(*BaseApp), ) *BaseApp { app := &BaseApp{ logger: logger, @@ -109,7 +115,7 @@ func (app *BaseApp) AppVersion() string { } // Logger returns the logger of the BaseApp. -func (app *BaseApp) Logger() log.Logger { +func (app *BaseApp) Logger() *slog.Logger { return app.logger } diff --git a/tm2/pkg/sdk/baseapp_test.go b/tm2/pkg/sdk/baseapp_test.go index f6c2038569a..1d8e73acc8d 100644 --- a/tm2/pkg/sdk/baseapp_test.go +++ b/tm2/pkg/sdk/baseapp_test.go @@ -8,6 +8,8 @@ import ( "reflect" "testing" + "golang.org/x/exp/slog" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -15,7 +17,6 @@ import ( abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" bft "github.com/gnolang/gno/tm2/pkg/bft/types" dbm "github.com/gnolang/gno/tm2/pkg/db" - "github.com/gnolang/gno/tm2/pkg/log" "github.com/gnolang/gno/tm2/pkg/sdk/testutils" "github.com/gnolang/gno/tm2/pkg/std" "github.com/gnolang/gno/tm2/pkg/store/dbadapter" @@ -55,8 +56,10 @@ func newTxCounter(txInt int64, msgInts ...int64) std.Tx { return tx } -func defaultLogger() log.Logger { - return log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "sdk/app") +func defaultLogger() *slog.Logger { + logger := slog.New(slog.NewTextHandler(os.Stdout, nil)) + + return logger.With("module", "sdk/app") } func newBaseApp(name string, db dbm.DB, options ...func(*BaseApp)) *BaseApp { diff --git a/tm2/pkg/sdk/context.go b/tm2/pkg/sdk/context.go index 6e33cb1f419..c208a3e2e75 100644 --- a/tm2/pkg/sdk/context.go +++ b/tm2/pkg/sdk/context.go @@ -4,9 +4,10 @@ import ( "context" "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/log" "github.com/gnolang/gno/tm2/pkg/store" "github.com/gnolang/gno/tm2/pkg/store/gas" ) @@ -26,7 +27,7 @@ type Context struct { header abci.Header chainID string txBytes []byte - logger log.Logger + logger *slog.Logger voteInfo []abci.VoteInfo gasMeter store.GasMeter // XXX make passthroughGasMeter w/ blockGasMeter? blockGasMeter store.GasMeter @@ -46,7 +47,7 @@ func (c Context) BlockHeight() int64 { return c.header.GetHeight() } func (c Context) BlockTime() time.Time { return c.header.GetTime() } func (c Context) ChainID() string { return c.chainID } func (c Context) TxBytes() []byte { return c.txBytes } -func (c Context) Logger() log.Logger { return c.logger } +func (c Context) Logger() *slog.Logger { return c.logger } func (c Context) VoteInfos() []abci.VoteInfo { return c.voteInfo } func (c Context) GasMeter() store.GasMeter { return c.gasMeter } func (c Context) BlockGasMeter() store.GasMeter { return c.blockGasMeter } @@ -65,7 +66,7 @@ func (c Context) ConsensusParams() *abci.ConsensusParams { } // create a new context -func NewContext(mode RunTxMode, ms store.MultiStore, header abci.Header, logger log.Logger) Context { +func NewContext(mode RunTxMode, ms store.MultiStore, header abci.Header, logger *slog.Logger) Context { if header.GetChainID() == "" { panic("header chain id cannot be empty") } @@ -112,7 +113,7 @@ func (c Context) WithTxBytes(txBytes []byte) Context { return c } -func (c Context) WithLogger(logger log.Logger) Context { +func (c Context) WithLogger(logger *slog.Logger) Context { c.logger = logger return c } diff --git a/tm2/pkg/service/service.go b/tm2/pkg/service/service.go index e1e9189e044..2a9fa0c3bfc 100644 --- a/tm2/pkg/service/service.go +++ b/tm2/pkg/service/service.go @@ -5,6 +5,8 @@ import ( "fmt" "sync/atomic" + "golang.org/x/exp/slog" + "github.com/gnolang/gno/tm2/pkg/log" ) @@ -49,7 +51,7 @@ type Service interface { String() string // SetLogger sets a logger. - SetLogger(log.Logger) + SetLogger(*slog.Logger) } /* @@ -95,7 +97,7 @@ Typical usage: } */ type BaseService struct { - Logger log.Logger + Logger *slog.Logger name string started uint32 // atomic stopped uint32 // atomic @@ -106,9 +108,9 @@ type BaseService struct { } // NewBaseService creates a new BaseService. -func NewBaseService(logger log.Logger, name string, impl Service) *BaseService { +func NewBaseService(logger *slog.Logger, name string, impl Service) *BaseService { if logger == nil { - logger = log.NewNopLogger() + logger = log.NewNoopLogger() } return &BaseService{ @@ -120,7 +122,7 @@ func NewBaseService(logger log.Logger, name string, impl Service) *BaseService { } // SetLogger implements Service by setting a logger. -func (bs *BaseService) SetLogger(l log.Logger) { +func (bs *BaseService) SetLogger(l *slog.Logger) { bs.Logger = l }