diff --git a/.dockerignore b/.dockerignore index a45b7bafa98..3536640b4d7 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,7 +1,9 @@ .dockerignore build/ Dockerfile -misc/ +misc/* +!misc/loop/ +!misc/autocounterd/ docker-compose.yml tests/docker-integration/ diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS deleted file mode 100644 index 3870ff30539..00000000000 --- a/.github/CODEOWNERS +++ /dev/null @@ -1,97 +0,0 @@ -# CODEOWNERS: https://help.github.com/articles/about-codeowners/ - -# Primary repo maintainers. -* @gnolang/tech-staff - -# Tendermint2. -/tm2/ @jaekwon @moul @piux2 @zivkovicmilos -/tm2/pkg/crypto/ @jaekwon @moul @gnolang/security -/tm2/pkg/crypto/keys/client/ @jaekwon @gnolang/security -/tm2/pkg/db/ @ajnavarro -# TODO: add per package exceptions -# ... - -# Docs & Content. -/docs/ @moul -/docs/**.md @gnolang/devrels -/docs/**.gif @gnolang/devrels -/docs/Makefile @gnolang/devrels -/README.md @moul @gnolang/devrels -/**/README.md @gnolang/devrels -/.gitpod.yml @gnolang/devrels - -# Gno examples and default contracts. -/examples/ @gnolang/tech-staff @gnolang/devrels -/examples/gno.land/p/demo/ @gnolang/tech-staff @gnolang/devrels -/examples/gno.land/p/demo/avl/ @jaekwon -/examples/gno.land/p/demo/bf/ @moul -/examples/gno.land/p/demo/blog/ @gnolang/devrels -/examples/gno.land/p/demo/boardsv2/ @ilgooz @jeronimoalbi @moul -/examples/gno.land/p/demo/cford32/ @thehowl -/examples/gno.land/p/demo/memeland/ @leohhhn -/examples/gno.land/p/demo/seqid/ @thehowl -/examples/gno.land/p/demo/ownable/ @leohhhn -/examples/gno.land/p/demo/pausable/ @leohhhn -/examples/gno.land/p/demo/svg/ @moul -/examples/gno.land/p/demo/tamagotchi/ @moul -/examples/gno.land/p/demo/ui/ @moul -/examples/gno.land/r/demo/ @gnolang/tech-staff @gnolang/devrels -/examples/gno.land/r/demo/art/ @moul -/examples/gno.land/r/demo/boardsv2/ @ilgooz @jeronimoalbi @moul -/examples/gno.land/r/demo/memeland/ @leohhhn -/examples/gno.land/r/demo/tamagotchi/ @moul -/examples/gno.land/r/demo/userbook/ @leohhhn -/examples/gno.land/r/gnoland/ @moul -/examples/gno.land/r/sys/ @moul -/examples/gno.land/r/jaekwon/ @jaekwon -/examples/gno.land/r/manfred/ @moul - -# Gno.land. -/gno.land/ @moul @zivkovicmilos -/gno.land/cmd/genesis/ @zivkovicmilos -/gno.land/cmd/gnokey/ @jaekwon @moul @gfanton -/gno.land/cmd/gnoland/ @zivkovicmilos @gnolang/devops -/gno.land/cmd/gnoweb/ @gfanton @thehowl -/gno.land/pkg/gnoclient/ @zivkovicmilos @leohhhn @gfanton -/gno.land/pkg/gnoland/ @zivkovicmilos @gfanton -/gno.land/pkg/keyscli/ @jaekwon @moul @gfanton -/gno.land/pkg/log/ @zivkovicmilos @gfanton -/gno.land/pkg/sdk/vm/ @moul @gfanton @thehowl -/gno.land/pkg/integration/ @gfanton -/gno.land/genesis/ @moul -#... - -# GnoVM/Gnolang. -/gnovm/ @jaekwon @moul @piux2 @thehowl -/gnovm/stdlibs/ @thehowl -/gnovm/tests/ @jaekwon @deelawn @thehowl @mvertes -/gnovm/cmd/gno/ @moul @thehowl -/gnovm/pkg/gnolang/ @jaekwon @moul @piux2 @deelawn -/gnovm/pkg/doc/ @thehowl -/gnovm/pkg/repl/ @mvertes @ajnavarro -/gnovm/pkg/gnomod/ @thehowl -/gnovm/pkg/gnoenv/ @gfanton -/gnovm/pkg/transpiler/ @thehowl -/gnovm/pkg/integration/ @gfanton - -# Contribs -/contribs/ @gnolang/tech-staff -/contribs/gnodev/ @gfanton -/contribs/gnokeykc/ @moul -/contribs/gnomd/ @moul - -# Misc -/misc/ @gnolang/tech-staff -/misc/loop/ @moul @gnolang/devops -/misc/deployments/ @moul @gnolang/devops -/misc/genstd/ @thehowl - -# Special files. -/PLAN.md @jaekwon @moul -/PHILOSOPHY.md @jaekwon -/CONTRIBUTING.md @jaekwon @moul @gnolang/tech-staff -/LICENSE.md @jaekwon -/.github/ @moul @gnolang/tech-staff -/.github/workflows @ajnavarro @moul -/.github/CODEOWNERS @jaekwon @moul -/go.mod @gnolang/tech-staff # no unnecessary dependencies diff --git a/.github/codecov.yml b/.github/codecov.yml index ea1c701d946..d1ecba7ade3 100644 --- a/.github/codecov.yml +++ b/.github/codecov.yml @@ -39,3 +39,8 @@ flag_management: - type: patch target: auto # Let's decrease this later. threshold: 10 + +ignore: + - "gnovm/stdlibs/generated.go" + - "gnovm/tests/stdlibs/generated.go" + - "**/*.pb.go" diff --git a/.github/golangci.yml b/.github/golangci.yml index e78d09a582e..43cea27a791 100644 --- a/.github/golangci.yml +++ b/.github/golangci.yml @@ -28,6 +28,7 @@ linters: - misspell # Misspelled English words in comments - makezero # Finds slice declarations with non-zero initial length - importas # Enforces consistent import aliases + - govet # same as 'go vet' - gosec # Security problems - gofmt # Whether the code was gofmt-ed - goimports # Unused imports diff --git a/.github/goreleaser-master.yaml b/.github/goreleaser-master.yaml deleted file mode 100644 index bca52615db8..00000000000 --- a/.github/goreleaser-master.yaml +++ /dev/null @@ -1,503 +0,0 @@ -project_name: gno - -before: - hooks: - - go mod tidy - -builds: - - id: gno - main: ./gnovm/cmd/gno - binary: gno - env: - - CGO_ENABLED=0 - goos: - - linux - - darwin - goarch: - - amd64 - - arm64 - - arm - goarm: - - 6 - - 7 - - id: gnoland - main: ./gno.land/cmd/gnoland - binary: gnoland - env: - - CGO_ENABLED=0 - goos: - - linux - - darwin - goarch: - - amd64 - - arm64 - - arm - goarm: - - 6 - - 7 - - id: gnokey - main: ./gno.land/cmd/gnokey - binary: gnokey - env: - - CGO_ENABLED=0 - goos: - - linux - - darwin - goarch: - - amd64 - - arm64 - - arm - goarm: - - 6 - - 7 - - id: gnoweb - main: ./gno.land/cmd/gnoweb - binary: gnoweb - env: - - CGO_ENABLED=0 - goos: - - linux - - darwin - goarch: - - amd64 - - arm64 - - arm - goarm: - - 6 - - 7 -gomod: - proxy: true - -archives: - # https://goreleaser.com/customization/archive/ - - files: - # Standard Release Files - - LICENSE.md - - README.md - -signs: - - cmd: cosign - env: - - COSIGN_EXPERIMENTAL=1 - certificate: "${artifact}.pem" - args: - - sign-blob - - "--output-certificate=${certificate}" - - "--output-signature=${signature}" - - "${artifact}" - - "--yes" # needed on cosign 2.0.0+ - artifacts: checksum - output: true - -dockers: - # https://goreleaser.com/customization/docker/ - - # gno - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: amd64 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-amd64" - - "ghcr.io/gnolang/{{ .ProjectName }}:master-amd64" - build_flag_templates: - - "--target=gno" - - "--platform=linux/amd64" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gno - extra_files: - - examples - - gnovm/stdlibs - - gnovm/tests/stdlibs - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm64 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-arm64v8" - - "ghcr.io/gnolang/{{ .ProjectName }}:master-arm64v8" - build_flag_templates: - - "--target=gno" - - "--platform=linux/arm64/v8" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gno - extra_files: - - examples - - gnovm/stdlibs - - gnovm/tests/stdlibs - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm - goarm: 6 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-armv6" - - "ghcr.io/gnolang/{{ .ProjectName }}:master-armv6" - build_flag_templates: - - "--target=gno" - - "--platform=linux/arm/v6" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gno - extra_files: - - examples - - gnovm/stdlibs - - gnovm/tests/stdlibs - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm - goarm: 7 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-armv7" - - "ghcr.io/gnolang/{{ .ProjectName }}:master-armv7" - build_flag_templates: - - "--target=gno" - - "--platform=linux/arm/v7" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gno - extra_files: - - examples - - gnovm/stdlibs - - gnovm/tests/stdlibs - - # gnoland - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: amd64 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-amd64" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:master-amd64" - build_flag_templates: - - "--target=gnoland" - - "--platform=linux/amd64" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoland" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnoland - extra_files: - - gno.land/genesis/genesis_balances.txt - - gno.land/genesis/genesis_txs.jsonl - - examples - - gnovm/stdlibs - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm64 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-arm64v8" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:master-arm64v8" - build_flag_templates: - - "--target=gnoland" - - "--platform=linux/arm64/v8" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoland" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnoland - extra_files: - - gno.land/genesis/genesis_balances.txt - - gno.land/genesis/genesis_txs.jsonl - - examples - - gnovm/stdlibs - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm - goarm: 6 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-armv6" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:master-armv6" - build_flag_templates: - - "--target=gnoland" - - "--platform=linux/arm/v6" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoland" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnoland - extra_files: - - gno.land/genesis/genesis_balances.txt - - gno.land/genesis/genesis_txs.jsonl - - examples - - gnovm/stdlibs - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm - goarm: 7 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-armv7" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:master-armv7" - build_flag_templates: - - "--target=gnoland" - - "--platform=linux/arm/v7" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoland" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnoland - extra_files: - - gno.land/genesis/genesis_balances.txt - - gno.land/genesis/genesis_txs.jsonl - - examples - - gnovm/stdlibs - # gnokey - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: amd64 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-amd64" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:master-amd64" - build_flag_templates: - - "--target=gnokey" - - "--platform=linux/amd64" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnokey" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnokey - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm64 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-arm64v8" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:master-arm64v8" - build_flag_templates: - - "--target=gnokey" - - "--platform=linux/arm64/v8" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnokey" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnokey - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm - goarm: 6 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-armv6" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:master-armv6" - build_flag_templates: - - "--target=gnokey" - - "--platform=linux/arm/v6" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnokey" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnokey - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm - goarm: 7 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-armv7" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:master-armv7" - build_flag_templates: - - "--target=gnokey" - - "--platform=linux/arm/v7" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnokey" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnokey - - # gnoweb - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: amd64 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-amd64" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:master-amd64" - build_flag_templates: - - "--target=gnoweb" - - "--platform=linux/amd64" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoweb" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnoweb - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm64 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-arm64v8" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:master-arm64v8" - build_flag_templates: - - "--target=gnoweb" - - "--platform=linux/arm64/v8" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoweb" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnoweb - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm - goarm: 6 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-armv6" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:master-armv6" - build_flag_templates: - - "--target=gnoweb" - - "--platform=linux/arm/v6" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoweb" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnoweb - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm - goarm: 7 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-armv7" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:master-armv7" - build_flag_templates: - - "--target=gnoweb" - - "--platform=linux/arm/v7" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoweb" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnoweb - -docker_manifests: - # https://goreleaser.com/customization/docker_manifest/ - - # gno - - name_template: ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }} - image_templates: - - ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-amd64 - - ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-arm64v8 - - ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-armv6 - - ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-armv7 - - name_template: ghcr.io/gnolang/{{ .ProjectName }}:master - image_templates: - - ghcr.io/gnolang/{{ .ProjectName }}:master-amd64 - - ghcr.io/gnolang/{{ .ProjectName }}:master-arm64v8 - - ghcr.io/gnolang/{{ .ProjectName }}:master-armv6 - - ghcr.io/gnolang/{{ .ProjectName }}:master-armv7 - - # gnoland - - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }} - image_templates: - - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-amd64 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-arm64v8 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-armv6 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-armv7 - - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnoland:master - image_templates: - - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:master-amd64 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:master-arm64v8 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:master-armv6 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:master-armv7 - - # gnokey - - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }} - image_templates: - - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-amd64 - - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-arm64v8 - - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-armv6 - - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-armv7 - - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnokey:master - image_templates: - - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:master-amd64 - - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:master-arm64v8 - - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:master-armv6 - - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:master-armv7 - - # gnoweb - - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }} - image_templates: - - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-amd64 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-arm64v8 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-armv6 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-armv7 - - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:master - image_templates: - - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:master-amd64 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:master-arm64v8 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:master-armv6 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:master-armv7 - -docker_signs: - - cmd: cosign - env: - - COSIGN_EXPERIMENTAL=1 - artifacts: images - output: true - args: - - "sign" - - "${artifact}" - - "--yes" # needed on cosign 2.0.0+ - -checksum: - name_template: "checksums.txt" - -changelog: - sort: asc - -source: - enabled: true - -sboms: - - artifacts: archive - - id: source # Two different sbom configurations need two different IDs - artifacts: source - -release: - draft: true - replace_existing_draft: true - prerelease: auto - make_latest: false - mode: append - footer: | - ### Container Images - - You can find all docker images at: - - https://github.com/orgs/gnolang/packages?repo_name={{ .ProjectName }} - -nightly: - tag_name: master - publish_release: true - keep_single_release: true - name_template: "{{ incpatch .Version }}-{{ .ShortCommit }}-master" \ No newline at end of file diff --git a/.github/goreleaser-nightly.yaml b/.github/goreleaser-nightly.yaml deleted file mode 100644 index 3dac915b7cd..00000000000 --- a/.github/goreleaser-nightly.yaml +++ /dev/null @@ -1,502 +0,0 @@ -project_name: gno - -before: - hooks: - - go mod tidy - -builds: - - id: gno - main: ./gnovm/cmd/gno - binary: gno - env: - - CGO_ENABLED=0 - goos: - - linux - - darwin - goarch: - - amd64 - - arm64 - - arm - goarm: - - 6 - - 7 - - id: gnoland - main: ./gno.land/cmd/gnoland - binary: gnoland - env: - - CGO_ENABLED=0 - goos: - - linux - - darwin - goarch: - - amd64 - - arm64 - - arm - goarm: - - 6 - - 7 - - id: gnokey - main: ./gno.land/cmd/gnokey - binary: gnokey - env: - - CGO_ENABLED=0 - goos: - - linux - - darwin - goarch: - - amd64 - - arm64 - - arm - goarm: - - 6 - - 7 - - id: gnoweb - main: ./gno.land/cmd/gnoweb - binary: gnoweb - env: - - CGO_ENABLED=0 - goos: - - linux - - darwin - goarch: - - amd64 - - arm64 - - arm - goarm: - - 6 - - 7 -gomod: - proxy: true - -archives: - # https://goreleaser.com/customization/archive/ - - files: - # Standard Release Files - - LICENSE.md - - README.md - -signs: - - cmd: cosign - env: - - COSIGN_EXPERIMENTAL=1 - certificate: "${artifact}.pem" - args: - - sign-blob - - "--output-certificate=${certificate}" - - "--output-signature=${signature}" - - "${artifact}" - - "--yes" # needed on cosign 2.0.0+ - artifacts: checksum - output: true - -dockers: - # https://goreleaser.com/customization/docker/ - - # gno - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: amd64 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-amd64" - - "ghcr.io/gnolang/{{ .ProjectName }}:nightly-amd64" - build_flag_templates: - - "--target=gno" - - "--platform=linux/amd64" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gno - extra_files: - - examples - - gnovm/stdlibs - - gnovm/tests/stdlibs - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm64 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-arm64v8" - - "ghcr.io/gnolang/{{ .ProjectName }}:nightly-arm64v8" - build_flag_templates: - - "--target=gno" - - "--platform=linux/arm64/v8" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gno - extra_files: - - examples - - gnovm/stdlibs - - gnovm/tests/stdlibs - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm - goarm: 6 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-armv6" - - "ghcr.io/gnolang/{{ .ProjectName }}:nightly-armv6" - build_flag_templates: - - "--target=gno" - - "--platform=linux/arm/v6" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gno - extra_files: - - examples - - gnovm/stdlibs - - gnovm/tests/stdlibs - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm - goarm: 7 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-armv7" - - "ghcr.io/gnolang/{{ .ProjectName }}:nightly-armv7" - build_flag_templates: - - "--target=gno" - - "--platform=linux/arm/v7" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gno - extra_files: - - examples - - gnovm/stdlibs - - gnovm/tests/stdlibs - - # gnoland - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: amd64 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-amd64" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:nightly-amd64" - build_flag_templates: - - "--target=gnoland" - - "--platform=linux/amd64" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoland" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnoland - extra_files: - - gno.land/genesis/genesis_balances.txt - - gno.land/genesis/genesis_txs.jsonl - - examples - - gnovm/stdlibs - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm64 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-arm64v8" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:nightly-arm64v8" - build_flag_templates: - - "--target=gnoland" - - "--platform=linux/arm64/v8" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoland" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnoland - extra_files: - - gno.land/genesis/genesis_balances.txt - - gno.land/genesis/genesis_txs.jsonl - - examples - - gnovm/stdlibs - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm - goarm: 6 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-armv6" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:nightly-armv6" - build_flag_templates: - - "--target=gnoland" - - "--platform=linux/arm/v6" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoland" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnoland - extra_files: - - gno.land/genesis/genesis_balances.txt - - gno.land/genesis/genesis_txs.jsonl - - examples - - gnovm/stdlibs - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm - goarm: 7 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-armv7" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoland:nightly-armv7" - build_flag_templates: - - "--target=gnoland" - - "--platform=linux/arm/v7" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoland" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnoland - extra_files: - - gno.land/genesis/genesis_balances.txt - - gno.land/genesis/genesis_txs.jsonl - - examples - - gnovm/stdlibs - # gnokey - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: amd64 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-amd64" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:nightly-amd64" - build_flag_templates: - - "--target=gnokey" - - "--platform=linux/amd64" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnokey" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnokey - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm64 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-arm64v8" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:nightly-arm64v8" - build_flag_templates: - - "--target=gnokey" - - "--platform=linux/arm64/v8" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnokey" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnokey - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm - goarm: 6 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-armv6" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:nightly-armv6" - build_flag_templates: - - "--target=gnokey" - - "--platform=linux/arm/v6" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnokey" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnokey - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm - goarm: 7 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-armv7" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnokey:nightly-armv7" - build_flag_templates: - - "--target=gnokey" - - "--platform=linux/arm/v7" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnokey" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnokey - - # gnoweb - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: amd64 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-amd64" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:nightly-amd64" - build_flag_templates: - - "--target=gnoweb" - - "--platform=linux/amd64" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoweb" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnoweb - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm64 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-arm64v8" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:nightly-arm64v8" - build_flag_templates: - - "--target=gnoweb" - - "--platform=linux/arm64/v8" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoweb" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnoweb - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm - goarm: 6 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-armv6" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:nightly-armv6" - build_flag_templates: - - "--target=gnoweb" - - "--platform=linux/arm/v6" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoweb" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnoweb - - use: buildx - dockerfile: Dockerfile.release - goos: linux - goarch: arm - goarm: 7 - image_templates: - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-armv7" - - "ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:nightly-armv7" - build_flag_templates: - - "--target=gnoweb" - - "--platform=linux/arm/v7" - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title={{.ProjectName}}/gnoweb" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - ids: - - gnoweb - -docker_manifests: - # https://goreleaser.com/customization/docker_manifest/ - - # gno - - name_template: ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }} - image_templates: - - ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-amd64 - - ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-arm64v8 - - ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-armv6 - - ghcr.io/gnolang/{{ .ProjectName }}:{{ .Version }}-armv7 - - name_template: ghcr.io/gnolang/{{ .ProjectName }}:nightly - image_templates: - - ghcr.io/gnolang/{{ .ProjectName }}:nightly-amd64 - - ghcr.io/gnolang/{{ .ProjectName }}:nightly-arm64v8 - - ghcr.io/gnolang/{{ .ProjectName }}:nightly-armv6 - - ghcr.io/gnolang/{{ .ProjectName }}:nightly-armv7 - - # gnoland - - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }} - image_templates: - - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-amd64 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-arm64v8 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-armv6 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:{{ .Version }}-armv7 - - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnoland:nightly - image_templates: - - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:nightly-amd64 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:nightly-arm64v8 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:nightly-armv6 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoland:nightly-armv7 - - # gnokey - - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }} - image_templates: - - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-amd64 - - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-arm64v8 - - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-armv6 - - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Version }}-armv7 - - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnokey:nightly - image_templates: - - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:nightly-amd64 - - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:nightly-arm64v8 - - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:nightly-armv6 - - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:nightly-armv7 - - # gnoweb - - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }} - image_templates: - - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-amd64 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-arm64v8 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-armv6 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }}-armv7 - - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:nightly - image_templates: - - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:nightly-amd64 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:nightly-arm64v8 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:nightly-armv6 - - ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:nightly-armv7 - -docker_signs: - - cmd: cosign - env: - - COSIGN_EXPERIMENTAL=1 - artifacts: images - output: true - args: - - "sign" - - "${artifact}" - - "--yes" # needed on cosign 2.0.0+ - -checksum: - name_template: "checksums.txt" - -changelog: - sort: asc - -source: - enabled: true - -sboms: - - artifacts: archive - - id: source # Two different sbom configurations need two different IDs - artifacts: source - -release: - draft: true - replace_existing_draft: true - prerelease: auto - mode: append - footer: | - ### Container Images - - You can find all docker images at: - - https://github.com/orgs/gnolang/packages?repo_name={{ .ProjectName }} - -nightly: - tag_name: nightly - publish_release: true - keep_single_release: true - name_template: "{{ incpatch .Version }}-{{ .ShortCommit }}-nightly" \ No newline at end of file diff --git a/.github/goreleaser.yaml b/.github/goreleaser.yaml index cd3c62c2ae6..b5fb07d0578 100644 --- a/.github/goreleaser.yaml +++ b/.github/goreleaser.yaml @@ -24,8 +24,8 @@ builds: - arm64 - arm goarm: - - 6 - - 7 + - "6" + - "7" - id: gnoland main: ./gno.land/cmd/gnoland binary: gnoland @@ -39,8 +39,8 @@ builds: - arm64 - arm goarm: - - 6 - - 7 + - "6" + - "7" - id: gnokey main: ./gno.land/cmd/gnokey binary: gnokey @@ -54,8 +54,8 @@ builds: - arm64 - arm goarm: - - 6 - - 7 + - "6" + - "7" - id: gnoweb main: ./gno.land/cmd/gnoweb binary: gnoweb @@ -69,8 +69,8 @@ builds: - arm64 - arm goarm: - - 6 - - 7 + - "6" + - "7" - id: gnofaucet dir: ./contribs/gnofaucet binary: gnofaucet @@ -84,8 +84,8 @@ builds: - arm64 - arm goarm: - - 6 - - 7 + - "6" + - "7" - id: gnobro dir: ./contribs/gnodev/cmd/gnobro binary: gnobro @@ -99,8 +99,8 @@ builds: - arm64 - arm goarm: - - 6 - - 7 + - "6" + - "7" gomod: proxy: true @@ -616,7 +616,7 @@ docker_manifests: - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Env.TAG_VERSION }}-arm64v8 - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Env.TAG_VERSION }}-armv6 - ghcr.io/gnolang/{{ .ProjectName }}/gnokey:{{ .Env.TAG_VERSION }}-armv7 - + # gnoweb - name_template: ghcr.io/gnolang/{{ .ProjectName }}/gnoweb:{{ .Version }} image_templates: @@ -703,4 +703,8 @@ nightly: tag_name: nightly publish_release: true keep_single_release: true - name_template: "{{ incpatch .Version }}-{{ .ShortCommit }}-{{ .Env.TAG_VERSION }}" + version_template: "{{ incpatch .Version }}-{{ .ShortCommit }}-{{ .Env.TAG_VERSION }}" + +git: + ignore_tag_prefixes: + - "chain/" diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index d76f68cba5d..12e07a9cde6 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -8,5 +8,4 @@ - [ ] No breaking changes were made, or a `BREAKING CHANGE: xxx` message was included in the description - [ ] Added references to related issues and PRs - [ ] Provided any useful hints for running manual tests -- [ ] Added new benchmarks to [generated graphs](https://gnoland.github.io/benchmarks), if any. More info [here](https://github.com/gnolang/gno/blob/master/.benchmarks/README.md). diff --git a/.github/workflows/autocounterd.yml b/.github/workflows/autocounterd.yml index 66aced0d89c..63799960df5 100644 --- a/.github/workflows/autocounterd.yml +++ b/.github/workflows/autocounterd.yml @@ -1,6 +1,9 @@ name: autocounterd on: + pull_request: + branches: + - master push: paths: - misc/autocounterd @@ -41,7 +44,6 @@ jobs: - name: Build and push uses: docker/build-push-action@v6 with: - context: ./misc/autocounterd push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} diff --git a/.github/workflows/benchmark-master-push.yml b/.github/workflows/benchmark-master-push.yml index ba8c11b2007..bde6e623a88 100644 --- a/.github/workflows/benchmark-master-push.yml +++ b/.github/workflows/benchmark-master-push.yml @@ -4,6 +4,11 @@ on: push: branches: - master + paths: + - contribs/** + - gno.land/** + - gnovm/** + - tm2/** permissions: # deployments permission to deploy GitHub pages website @@ -29,9 +34,12 @@ jobs: go-version: "1.22.x" - name: Run benchmark + # add more benchmarks by adding additional lines for different packages; + # or modify the -bench regexp. run: | - go test -benchmem -bench=. ./... -run=^$ \ - -cpu 1,2 -timeout 50m | tee benchmarks.txt + set -xeuo pipefail && ( + go test ./gnovm/pkg/gnolang -bench='BenchmarkBenchdata' -benchmem -run='^$' -v -cpu=1,2 + ) | tee benchmarks.txt - name: Download previous benchmark data uses: actions/cache@v4 @@ -49,7 +57,7 @@ jobs: max-items-in-chart: 100 # Show alert with commit comment on detecting possible performance regression alert-threshold: "120%" - fail-on-alert: true + fail-on-alert: false comment-on-alert: true alert-comment-cc-users: "@ajnavarro,@thehowl,@zivkovicmilos" # Enable Job Summary for PRs diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 5b3c3c1fbf1..7c4bb35526f 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -47,7 +47,7 @@ jobs: 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 -v ./examples/... + - run: go run ./gnovm/cmd/gno test -v -print-runtime-metrics -print-events ./examples/... lint: strategy: fail-fast: false diff --git a/.github/workflows/misc.yml b/.github/workflows/misc.yml index b824235ca2b..859e1429983 100644 --- a/.github/workflows/misc.yml +++ b/.github/workflows/misc.yml @@ -22,7 +22,6 @@ jobs: - genproto - genstd - goscan - - logos - loop name: Run Main uses: ./.github/workflows/main_template.yml diff --git a/.github/workflows/mod-tidy.yml b/.github/workflows/mod-tidy.yml new file mode 100644 index 00000000000..24eab553d19 --- /dev/null +++ b/.github/workflows/mod-tidy.yml @@ -0,0 +1,26 @@ +name: Ensure go.mods are tidied + +on: + push: + branches: + - master + workflow_dispatch: + pull_request: + +jobs: + main: + name: Ensure go.mods are tidied + runs-on: ubuntu-latest + steps: + - name: Install Go + uses: actions/setup-go@v5 + with: + go-version: ${{ inputs.go-version }} + + - name: Checkout code + uses: actions/checkout@v4 + + - name: Check go.mod files are up to date + working-directory: ${{ inputs.modulepath }} + run: | + make tidy VERIFY_MOD_SUMS=true diff --git a/.github/workflows/portal-loop.yml b/.github/workflows/portal-loop.yml index b81957b22db..01135b164ac 100644 --- a/.github/workflows/portal-loop.yml +++ b/.github/workflows/portal-loop.yml @@ -45,7 +45,6 @@ jobs: - name: Build and push uses: docker/build-push-action@v6 with: - context: ./misc/loop target: portalloopd push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.meta.outputs.tags }} diff --git a/.github/workflows/releaser-master.yml b/.github/workflows/releaser-master.yml index 7eda0536532..7f81ef1ad1a 100644 --- a/.github/workflows/releaser-master.yml +++ b/.github/workflows/releaser-master.yml @@ -18,14 +18,16 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 0 + - name: Create a dummy tag to avoid goreleaser failure + run: git tag v0.0.0 master - uses: actions/setup-go@v5 with: go-version: "1.22.x" cache: true - - uses: sigstore/cosign-installer@v3.6.0 - - uses: anchore/sbom-action/download-syft@v0.17.2 + - uses: sigstore/cosign-installer@v3.7.0 + - uses: anchore/sbom-action/download-syft@v0.17.5 - uses: docker/login-action@v3 with: diff --git a/.github/workflows/nightlies.yml b/.github/workflows/releaser-nightly.yml similarity index 81% rename from .github/workflows/nightlies.yml rename to .github/workflows/releaser-nightly.yml index e8f3fe4ca5c..fd4eaa86b0e 100644 --- a/.github/workflows/nightlies.yml +++ b/.github/workflows/releaser-nightly.yml @@ -2,7 +2,7 @@ name: Trigger nightly build on: schedule: - - cron: '0 0 * * 2-6' + - cron: "0 0 * * 2-6" workflow_dispatch: permissions: @@ -23,8 +23,8 @@ jobs: go-version: "1.22.x" cache: true - - uses: sigstore/cosign-installer@v3.6.0 - - uses: anchore/sbom-action/download-syft@v0.17.2 + - uses: sigstore/cosign-installer@v3.7.0 + - uses: anchore/sbom-action/download-syft@v0.17.5 - uses: docker/login-action@v3 with: @@ -34,12 +34,12 @@ jobs: - name: Set up QEMU uses: docker/setup-qemu-action@v3 - + - uses: goreleaser/goreleaser-action@v6 with: distribution: goreleaser-pro version: ~> v2 - args: release --clean --nightly --config ./.github/goreleaser.yaml + args: release --clean --nightly --snapshot --config ./.github/goreleaser.yaml env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }} diff --git a/.github/workflows/releaser.yml b/.github/workflows/releaser.yml index 5433582cace..8bbc9323cad 100644 --- a/.github/workflows/releaser.yml +++ b/.github/workflows/releaser.yml @@ -23,8 +23,8 @@ jobs: go-version: "1.22.x" cache: true - - uses: sigstore/cosign-installer@v3.6.0 - - uses: anchore/sbom-action/download-syft@v0.17.2 + - uses: sigstore/cosign-installer@v3.7.0 + - uses: anchore/sbom-action/download-syft@v0.17.5 - uses: docker/login-action@v3 with: @@ -34,7 +34,7 @@ jobs: - name: Set up QEMU uses: docker/setup-qemu-action@v3 - + - uses: goreleaser/goreleaser-action@v6 with: distribution: goreleaser-pro diff --git a/.github/workflows/test_template.yml b/.github/workflows/test_template.yml index 18911415087..38fa10e096b 100644 --- a/.github/workflows/test_template.yml +++ b/.github/workflows/test_template.yml @@ -42,7 +42,7 @@ jobs: # confusing and meticulous. There will be some improvements in Go # 1.23 regarding coverage, so we can use this as a workaround until # then. - go test -covermode=atomic -timeout ${{ inputs.tests-timeout }} -v ./... -test.gocoverdir=$GOCOVERDIR + go test -covermode=atomic -timeout ${{ inputs.tests-timeout }} ./... -test.gocoverdir=$GOCOVERDIR # Print results (set +x; echo 'go coverage results:') diff --git a/Dockerfile b/Dockerfile index fa5a9e47270..b858589640f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,11 +10,20 @@ RUN --mount=type=cache,target=/root/.cache/go-build go build -o ./ RUN --mount=type=cache,target=/root/.cache/go-build go build -o ./build/gnoweb ./gno.land/cmd/gnoweb RUN --mount=type=cache,target=/root/.cache/go-build go build -o ./build/gno ./gnovm/cmd/gno +# build misc binaries +FROM golang:1.22-alpine AS build-misc +RUN go env -w GOMODCACHE=/root/.cache/go-build +WORKDIR /gnoroot +ENV GNOROOT="/gnoroot" +COPY . ./ +RUN --mount=type=cache,target=/root/.cache/go-build go build -C ./misc/loop -o /gnoroot/build/portalloopd ./cmd +RUN --mount=type=cache,target=/root/.cache/go-build go build -C ./misc/autocounterd -o /gnoroot/build/autocounterd ./cmd + # Base image FROM alpine:3.17 AS base WORKDIR /gnoroot ENV GNOROOT="/gnoroot" -RUN apk add ca-certificates +RUN apk add --no-cache ca-certificates CMD [ "" ] # alpine images @@ -47,6 +56,21 @@ COPY --from=build-gno /opt/gno/src/gno.land/cmd/gnoweb /opt/gno/src/gnowe EXPOSE 8888 ENTRYPOINT ["/usr/bin/gnoweb"] +# misc/loop +FROM docker AS portalloopd +WORKDIR /gnoroot +ENV GNOROOT="/gnoroot" +RUN apk add --no-cache ca-certificates bash curl jq +COPY --from=build-misc /gnoroot/build/portalloopd /usr/bin/portalloopd +ENTRYPOINT ["/usr/bin/portalloopd"] +CMD ["serve"] + +# misc/autocounterd +FROM base AS autocounterd +COPY --from=build-misc /gnoroot/build/autocounterd /usr/bin/autocounterd +ENTRYPOINT ["/usr/bin/autocounterd"] +CMD ["start"] + # all, contains everything. FROM base AS all COPY --from=build-gno /gnoroot/build/* /usr/bin/ diff --git a/Dockerfile.release b/Dockerfile.release index 4887857b5c2..481100c85c3 100644 --- a/Dockerfile.release +++ b/Dockerfile.release @@ -1,3 +1,6 @@ +# This file is similar to Dockerfile, but assumes that the binaries have +# already been created, and as such doesn't `go build` them. + FROM alpine AS base ENV GNOROOT="/gnoroot/" diff --git a/Makefile b/Makefile index fe862d52893..2bfbe4e05e2 100644 --- a/Makefile +++ b/Makefile @@ -46,6 +46,7 @@ install.gnodev: $(MAKE) --no-print-directory -C ./contribs/gnodev install @printf "\033[0;32m[+] 'gnodev' has been installed. Read more in ./contribs/gnodev/\033[0m\n" + # old aliases .PHONY: install_gnokey install_gnokey: install.gnokey diff --git a/contribs/gnodev/cmd/gnodev/setup_node.go b/contribs/gnodev/cmd/gnodev/setup_node.go index 578cf525751..4b3619b4a7d 100644 --- a/contribs/gnodev/cmd/gnodev/setup_node.go +++ b/contribs/gnodev/cmd/gnodev/setup_node.go @@ -23,7 +23,7 @@ func setupDevNode( if devCfg.txsFile != "" { // Load txs files var err error - nodeConfig.InitialTxs, err = parseTxs(devCfg.txsFile) + nodeConfig.InitialTxs, err = gnoland.ReadGenesisTxs(ctx, devCfg.txsFile) if err != nil { return nil, fmt.Errorf("unable to load transactions: %w", err) } @@ -35,7 +35,13 @@ func setupDevNode( // Override balances and txs nodeConfig.BalancesList = state.Balances - nodeConfig.InitialTxs = state.Txs + + stateTxs := state.Txs + nodeConfig.InitialTxs = make([]gnoland.TxWithMetadata, len(stateTxs)) + + for index, nodeTx := range stateTxs { + nodeConfig.InitialTxs[index] = nodeTx + } logger.Info("genesis file loaded", "path", devCfg.genesisFile, "txs", len(nodeConfig.InitialTxs)) } diff --git a/contribs/gnodev/cmd/gnodev/txs.go b/contribs/gnodev/cmd/gnodev/txs.go deleted file mode 100644 index 0be33b68702..00000000000 --- a/contribs/gnodev/cmd/gnodev/txs.go +++ /dev/null @@ -1,23 +0,0 @@ -package main - -import ( - "context" - "fmt" - "os" - - "github.com/gnolang/gno/tm2/pkg/std" -) - -func parseTxs(txFile string) ([]std.Tx, error) { - if txFile == "" { - return nil, nil - } - - file, loadErr := os.Open(txFile) - if loadErr != nil { - return nil, fmt.Errorf("unable to open tx file %s: %w", txFile, loadErr) - } - defer file.Close() - - return std.ParseTxs(context.Background(), file) -} diff --git a/contribs/gnodev/go.mod b/contribs/gnodev/go.mod index f4859889a16..a315d88591c 100644 --- a/contribs/gnodev/go.mod +++ b/contribs/gnodev/go.mod @@ -1,6 +1,6 @@ module github.com/gnolang/gno/contribs/gnodev -go 1.22 +go 1.22.0 replace github.com/gnolang/gno => ../.. @@ -107,6 +107,6 @@ require ( google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd // indirect google.golang.org/grpc v1.65.0 // indirect - google.golang.org/protobuf v1.34.2 // indirect + google.golang.org/protobuf v1.35.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/contribs/gnodev/go.sum b/contribs/gnodev/go.sum index af57f320257..e38c3621483 100644 --- a/contribs/gnodev/go.sum +++ b/contribs/gnodev/go.sum @@ -326,8 +326,8 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/contribs/gnodev/pkg/dev/node.go b/contribs/gnodev/pkg/dev/node.go index c3e70366fb2..54baa2ea774 100644 --- a/contribs/gnodev/pkg/dev/node.go +++ b/contribs/gnodev/pkg/dev/node.go @@ -35,7 +35,7 @@ type NodeConfig struct { BalancesList []gnoland.Balance PackagesPathList []PackagePath Emitter emitter.Emitter - InitialTxs []std.Tx + InitialTxs []gnoland.TxWithMetadata TMConfig *tmcfg.Config SkipFailingGenesisTxs bool NoReplay bool @@ -84,7 +84,7 @@ type Node struct { loadedPackages int // state - initialState, state []std.Tx + initialState, state []gnoland.TxWithMetadata currentStateIndex int } @@ -154,7 +154,7 @@ func (n *Node) GetRemoteAddress() string { // GetBlockTransactions returns the transactions contained // within the specified block, if any -func (n *Node) GetBlockTransactions(blockNum uint64) ([]std.Tx, error) { +func (n *Node) GetBlockTransactions(blockNum uint64) ([]gnoland.TxWithMetadata, error) { n.muNode.RLock() defer n.muNode.RUnlock() @@ -163,21 +163,26 @@ func (n *Node) GetBlockTransactions(blockNum uint64) ([]std.Tx, error) { // GetBlockTransactions returns the transactions contained // within the specified block, if any -func (n *Node) getBlockTransactions(blockNum uint64) ([]std.Tx, error) { +func (n *Node) getBlockTransactions(blockNum uint64) ([]gnoland.TxWithMetadata, error) { int64BlockNum := int64(blockNum) b, err := n.client.Block(&int64BlockNum) if err != nil { - return []std.Tx{}, fmt.Errorf("unable to load block at height %d: %w", blockNum, err) // nothing to see here + return []gnoland.TxWithMetadata{}, fmt.Errorf("unable to load block at height %d: %w", blockNum, err) // nothing to see here } - txs := make([]std.Tx, len(b.Block.Data.Txs)) + txs := make([]gnoland.TxWithMetadata, len(b.Block.Data.Txs)) for i, encodedTx := range b.Block.Data.Txs { var tx std.Tx if unmarshalErr := amino.Unmarshal(encodedTx, &tx); unmarshalErr != nil { return nil, fmt.Errorf("unable to unmarshal amino tx, %w", unmarshalErr) } - txs[i] = tx + txs[i] = gnoland.TxWithMetadata{ + Tx: tx, + Metadata: &gnoland.GnoTxMetadata{ + Timestamp: b.BlockMeta.Header.Time.Unix(), + }, + } } return txs, nil @@ -347,11 +352,14 @@ func (n *Node) SendTransaction(tx *std.Tx) error { return nil } -func (n *Node) getBlockStoreState(ctx context.Context) ([]std.Tx, error) { +func (n *Node) getBlockStoreState(ctx context.Context) ([]gnoland.TxWithMetadata, error) { // get current genesis state genesis := n.GenesisDoc().AppState.(gnoland.GnoGenesisState) - state := genesis.Txs[n.loadedPackages:] // ignore previously loaded packages + initialTxs := genesis.Txs[n.loadedPackages:] // ignore previously loaded packages + + state := append([]gnoland.TxWithMetadata{}, initialTxs...) + lastBlock := n.getLatestBlockNumber() var blocnum uint64 = 1 for ; blocnum <= lastBlock; blocnum++ { @@ -565,9 +573,8 @@ func newNodeConfig(tmc *tmcfg.Config, chainid string, appstate gnoland.GnoGenesi } return &gnoland.InMemoryNodeConfig{ - PrivValidator: pv, - TMConfig: tmc, - Genesis: genesis, - GenesisMaxVMCycles: 100_000_000, + PrivValidator: pv, + TMConfig: tmc, + Genesis: genesis, } } diff --git a/contribs/gnodev/pkg/dev/node_state.go b/contribs/gnodev/pkg/dev/node_state.go index 846c4857784..7504580b333 100644 --- a/contribs/gnodev/pkg/dev/node_state.go +++ b/contribs/gnodev/pkg/dev/node_state.go @@ -8,7 +8,6 @@ import ( "github.com/gnolang/gno/contribs/gnodev/pkg/events" "github.com/gnolang/gno/gno.land/pkg/gnoland" bft "github.com/gnolang/gno/tm2/pkg/bft/types" - "github.com/gnolang/gno/tm2/pkg/std" ) var ErrEmptyState = errors.New("empty state") @@ -29,7 +28,7 @@ func (n *Node) SaveCurrentState(ctx context.Context) error { } // Export the current state as list of txs -func (n *Node) ExportCurrentState(ctx context.Context) ([]std.Tx, error) { +func (n *Node) ExportCurrentState(ctx context.Context) ([]gnoland.TxWithMetadata, error) { n.muNode.RLock() defer n.muNode.RUnlock() @@ -42,7 +41,7 @@ func (n *Node) ExportCurrentState(ctx context.Context) ([]std.Tx, error) { return state[:n.currentStateIndex], nil } -func (n *Node) getState(ctx context.Context) ([]std.Tx, error) { +func (n *Node) getState(ctx context.Context) ([]gnoland.TxWithMetadata, error) { if n.state == nil { var err error n.state, err = n.getBlockStoreState(ctx) diff --git a/contribs/gnodev/pkg/dev/packages.go b/contribs/gnodev/pkg/dev/packages.go index 7b560c21e09..7ee628ce39e 100644 --- a/contribs/gnodev/pkg/dev/packages.go +++ b/contribs/gnodev/pkg/dev/packages.go @@ -7,6 +7,7 @@ import ( "path/filepath" "github.com/gnolang/gno/contribs/gnodev/pkg/address" + "github.com/gnolang/gno/gno.land/pkg/gnoland" vmm "github.com/gnolang/gno/gno.land/pkg/sdk/vm" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" "github.com/gnolang/gno/gnovm/pkg/gnomod" @@ -118,7 +119,7 @@ func (pm PackagesMap) toList() gnomod.PkgList { return list } -func (pm PackagesMap) Load(fee std.Fee) ([]std.Tx, error) { +func (pm PackagesMap) Load(fee std.Fee) ([]gnoland.TxWithMetadata, error) { pkgs := pm.toList() sorted, err := pkgs.Sort() @@ -127,7 +128,8 @@ func (pm PackagesMap) Load(fee std.Fee) ([]std.Tx, error) { } nonDraft := sorted.GetNonDraftPkgs() - txs := []std.Tx{} + txs := make([]gnoland.TxWithMetadata, 0, len(nonDraft)) + for _, modPkg := range nonDraft { pkg := pm[modPkg.Dir] if pkg.Creator.IsZero() { @@ -141,18 +143,20 @@ func (pm PackagesMap) Load(fee std.Fee) ([]std.Tx, error) { } // Create transaction - tx := std.Tx{ - Fee: fee, - Msgs: []std.Msg{ - vmm.MsgAddPackage{ - Creator: pkg.Creator, - Deposit: pkg.Deposit, - Package: memPkg, + tx := gnoland.TxWithMetadata{ + Tx: std.Tx{ + Fee: fee, + Msgs: []std.Msg{ + vmm.MsgAddPackage{ + Creator: pkg.Creator, + Deposit: pkg.Deposit, + Package: memPkg, + }, }, }, } - tx.Signatures = make([]std.Signature, len(tx.GetSigners())) + tx.Tx.Signatures = make([]std.Signature, len(tx.Tx.GetSigners())) txs = append(txs, tx) } diff --git a/contribs/gnofaucet/go.mod b/contribs/gnofaucet/go.mod index c56c0b7d425..c5bb1ad0d81 100644 --- a/contribs/gnofaucet/go.mod +++ b/contribs/gnofaucet/go.mod @@ -6,15 +6,17 @@ toolchain go1.22.4 require ( github.com/gnolang/faucet v0.3.2 - github.com/gnolang/gno v0.1.1 + github.com/gnolang/gno v0.1.0-nightly.20240627 github.com/stretchr/testify v1.9.0 go.uber.org/zap v1.27.0 golang.org/x/time v0.5.0 ) +replace github.com/gnolang/gno => ../.. + require ( - github.com/btcsuite/btcd/btcec/v2 v2.3.3 // indirect - github.com/btcsuite/btcd/btcutil v1.1.5 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/btcsuite/btcd/btcutil v1.1.6 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect @@ -23,34 +25,34 @@ require ( github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/gorilla/websocket v1.5.1 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect + github.com/gorilla/websocket v1.5.3 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/peterbourgon/ff/v3 v3.4.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/rs/cors v1.11.0 // indirect - github.com/rs/xid v1.5.0 // indirect - go.opentelemetry.io/otel v1.28.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.28.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.28.0 // indirect - go.opentelemetry.io/otel/metric v1.28.0 // indirect - go.opentelemetry.io/otel/sdk v1.28.0 // indirect - go.opentelemetry.io/otel/sdk/metric v1.28.0 // indirect - go.opentelemetry.io/otel/trace v1.28.0 // indirect + github.com/rs/cors v1.11.1 // indirect + github.com/rs/xid v1.6.0 // indirect + go.opentelemetry.io/otel v1.29.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.29.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.29.0 // indirect + go.opentelemetry.io/otel/metric v1.29.0 // indirect + go.opentelemetry.io/otel/sdk v1.29.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.29.0 // indirect + go.opentelemetry.io/otel/trace v1.29.0 // indirect go.opentelemetry.io/proto/otlp v1.3.1 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap/exp v0.2.0 // indirect - golang.org/x/crypto v0.25.0 // indirect + golang.org/x/crypto v0.26.0 // indirect golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 // indirect - golang.org/x/mod v0.19.0 // indirect - golang.org/x/net v0.27.0 // indirect - golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.22.0 // indirect - golang.org/x/term v0.22.0 // indirect - golang.org/x/text v0.16.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect + golang.org/x/mod v0.20.0 // indirect + golang.org/x/net v0.28.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.24.0 // indirect + golang.org/x/term v0.23.0 // indirect + golang.org/x/text v0.17.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd // indirect google.golang.org/grpc v1.65.0 // indirect - google.golang.org/protobuf v1.34.2 // indirect + google.golang.org/protobuf v1.35.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/contribs/gnofaucet/go.sum b/contribs/gnofaucet/go.sum index 1508cdae1e6..f4bdc65d7ec 100644 --- a/contribs/gnofaucet/go.sum +++ b/contribs/gnofaucet/go.sum @@ -1,18 +1,20 @@ -dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= -dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= +dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= 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.5-0.20231215221805-96c9fd8078fd h1:js1gPwhcFflTZ7Nzl7WHaOTlTr5hIrR4n1NM4v9n4Kw= github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= +github.com/btcsuite/btcd v0.24.2 h1:aLmxPguqxza+4ag8R1I2nnJjSu2iFn/kqtHTIImswcY= +github.com/btcsuite/btcd v0.24.2/go.mod h1:5C8ChTkl5ejr3WHj8tkQSCmydiMEPB0ZhQhehpq7Dgg= github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= -github.com/btcsuite/btcd/btcec/v2 v2.3.3 h1:6+iXlDKE8RMtKsvK0gshlXIuPbyWM/h84Ensb7o3sC0= -github.com/btcsuite/btcd/btcec/v2 v2.3.3/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= -github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8= github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= +github.com/btcsuite/btcd/btcutil v1.1.6 h1:zFL2+c3Lb9gEgqKNzowKUPQNb8jV7v5Oaodi/AYFd6c= +github.com/btcsuite/btcd/btcutil v1.1.6/go.mod h1:9dFymx8HpuLqBnsPELrImQeTQfKBQqzqGbbV3jK55aE= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= @@ -47,8 +49,6 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/gnolang/faucet v0.3.2 h1:3QBrdmnQszRaAZbxgO5xDDm3czNa0L/RFmhnCkbxy5I= github.com/gnolang/faucet v0.3.2/go.mod h1:/wbw9h4ooMzzyNBuM0X+ol7CiPH2OFjAFF3bYAXqA7U= -github.com/gnolang/gno v0.1.1 h1:t41S0SWIUa3syI7XpRAuCneCgRc8gOJ2g8DkUedF72U= -github.com/gnolang/gno v0.1.1/go.mod h1:BTaBNeaoY/W95NN6QA4RCoQ6Z7mi8M+Zb1I1wMWGg2w= github.com/gnolang/overflow v0.0.0-20170615021017-4d914c927216 h1:GKvsK3oLWG9B1GL7WP/VqwM6C92j5tIvB844oggL9Lk= github.com/gnolang/overflow v0.0.0-20170615021017-4d914c927216/go.mod h1:xJhtEL7ahjM1WJipt89gel8tHzfIl/LyMY+lCYh38d8= github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw= @@ -77,10 +77,10 @@ github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 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= @@ -109,32 +109,37 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= -github.com/rs/cors v1.11.0 h1:0B9GE/r9Bc2UxRMMtymBkHTenPkHDv0CW4Y98GBY+po= -github.com/rs/cors v1.11.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= -github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc= -github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= +github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU= +github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= -go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI= -go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE= -go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= -go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.28.0 h1:U2guen0GhqH8o/G2un8f/aG/y++OuW6MyCo6hT9prXk= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.28.0/go.mod h1:yeGZANgEcpdx/WK0IvvRFC+2oLiMS2u4L/0Rj2M2Qr0= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.28.0 h1:aLmmtjRke7LPDQ3lvpFz+kNEH43faFhzW7v8BFIEydg= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.28.0/go.mod h1:TC1pyCt6G9Sjb4bQpShH+P5R53pO6ZuGnHuuln9xMeE= -go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= -go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= -go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= -go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= -go.opentelemetry.io/otel/sdk/metric v1.28.0 h1:OkuaKgKrgAbYrrY0t92c+cC+2F6hsFNnCQArXCKlg08= -go.opentelemetry.io/otel/sdk/metric v1.28.0/go.mod h1:cWPjykihLAPvXKi4iZc1dpER3Jdq2Z0YLse3moQUCpg= -go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= -go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= +go.etcd.io/bbolt v1.3.11 h1:yGEzV1wPz2yVCLsD8ZAiGHhHVlczyC9d1rP43/VCRJ0= +go.etcd.io/bbolt v1.3.11/go.mod h1:dksAq7YMXoljX0xu6VF5DMZGbhYYoLUalEiSySYAS4I= +go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw= +go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.29.0 h1:k6fQVDQexDE+3jG2SfCQjnHS7OamcP73YMoxEVq5B6k= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.29.0/go.mod h1:t4BrYLHU450Zo9fnydWlIuswB1bm7rM8havDpWOJeDo= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.29.0 h1:xvhQxJ/C9+RTnAj5DpTg7LSM1vbbMTiXt7e9hsfqHNw= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.29.0/go.mod h1:Fcvs2Bz1jkDM+Wf5/ozBGmi3tQ/c9zPKLnsipnfhGAo= +go.opentelemetry.io/otel/metric v1.29.0 h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc= +go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8= +go.opentelemetry.io/otel/sdk v1.29.0 h1:vkqKjk7gwhS8VaWb0POZKmIEDimRCMsopNYnriHyryo= +go.opentelemetry.io/otel/sdk v1.29.0/go.mod h1:pM8Dx5WKnvxLCb+8lG1PRNIDxu9g9b9g59Qr7hfAAok= +go.opentelemetry.io/otel/sdk/metric v1.29.0 h1:K2CfmJohnRgvZ9UAj2/FhIf/okdWcNdBwe1m8xFXiSY= +go.opentelemetry.io/otel/sdk/metric v1.29.0/go.mod h1:6zZLdCl2fkauYoZIOn/soQIDSWFmNSRcICarHfuhNJQ= +go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt39JTi4= +go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ= go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -148,22 +153,22 @@ 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-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= -golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= +golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= +golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY= golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI= -golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= -golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -173,24 +178,24 @@ golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= -golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= +golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= +golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= +golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0= -google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094/go.mod h1:fJ/e3If/Q67Mj99hin0hMhiNyCRmt6BQ2aWIJshUSJw= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= +google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd h1:BBOTEWLuuEGQy9n1y9MhVJ9Qt0BDu21X8qZs71/uPZo= +google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:fO8wJzT2zbQbAjbIoos1285VfEIYKDDY+Dt+WpTkh6g= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd h1:6TEm2ZxXoQmFWFlt1vNxvVOa1Q0dXFQD1m/rYjXmS0E= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -199,8 +204,8 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/contribs/gnogenesis/Makefile b/contribs/gnogenesis/Makefile new file mode 100644 index 00000000000..20f234e7e36 --- /dev/null +++ b/contribs/gnogenesis/Makefile @@ -0,0 +1,18 @@ +rundep := go run -modfile ../../misc/devdeps/go.mod +golangci_lint := $(rundep) github.com/golangci/golangci-lint/cmd/golangci-lint + + +.PHONY: install +install: + go install . + +.PHONY: build +build: + go build -o build/gnogenesis . + +lint: + $(golangci_lint) --config ../../.github/golangci.yml run ./... + +test: + go test $(GOTEST_FLAGS) -v ./... + diff --git a/contribs/gnogenesis/README.md b/contribs/gnogenesis/README.md new file mode 100644 index 00000000000..32cf3e6bb94 --- /dev/null +++ b/contribs/gnogenesis/README.md @@ -0,0 +1,181 @@ +## Overview + +`gnogenesis` is a CLI tool for managing the Gnoland blockchain's `genesis.json` file. It provides +subcommands for setting up and manipulating the genesis file, from generating a new genesis configuration to managing +initial validators, balances, and transactions. + +Refer to specific command help options (`--help`) for further customization options. + +## Installation + +To install gnogenesis, clone the repository and build the tool: + +```shell +git clone https://github.com/gnoland/gno.git +cd gno/contribs/gnogenesis +make install +``` + +This will compile and install `gnogenesis` to your system path, allowing you to run commands directly. + +## Features + +### Generate a `genesis.json` + +To create a new genesis.json, use the `generate` subcommand. You can specify parameters such as chain ID, block limits, +and more: + +```shell +gnogenesis generate --chain-id gno-dev --block-max-gas 100000000 --output-path ./genesis.json +``` + +This command generates a genesis.json file with custom parameters, defining the chain’s identity, block limits, and +more. By default, the genesis-time is set to the current timestamp, or you can specify a future time for scheduled chain +launches. + +Keep in mind the `genesis.json` is generated with an empty validator set, and you will need to manually add the initial +validators. + +### Manage initial validators + +The `validator` subcommands allow you to add or remove validators directly in the genesis file. + +#### Add a validator + +To add a validator, specify their `address`, `name`, and `pub-key`: + +```shell +gnogenesis validator add --address g1rzuwh5frve732k4futyw45y78rzuty4626zy6h --name validator1 --pub-key gpub1pggj7ard9eg82cjtv4u52epjx56nzwgjyg9zplmcmggxyxyrch0zcyg684yxmerullv3l6hmau58sk4eyxskmny9h7lsnz +``` + +This command will add the validator with the specified details in the genesis file. + +The `address` and `pub-key` values need to be in bech32 format. They can be fetched using `gnoland secrets get`. + +#### Remove a validator + +If you need to remove a validator, specify their address: + +```shell +gnogenesis validator remove --address g1rzuwh5frve732k4futyw45y78rzuty4626zy6h +``` + +This will remove the specified validator from the validator set in `genesis.json`, if it is present. + +### Verify the `genesis.json` + +The `verify` subcommand is helpful to confirm the integrity of a `genesis.json` file: + +```shell +gnogenesis verify --genesis-path ./genesis.json +``` + +This validation checks for proper structure, account balance totals, and ensures validators are correctly configured, +preventing common genesis setup issues. It is advised to always run this verification step when dealing with an external +`genesis.json`. + +### Manage account balances + +Balances can be added or removed through the balances subcommand, either individually or using a balance sheet file. + +The format for individual balance entries is `
=ugnot`. + +#### Add Account Balances + +Add a single balance directly: + +```shell +gnogenesis balances add --single g1rzuwh5frve732k4futyw45y78rzuty4626zy6h=100ugnot +``` + +Alternatively, load multiple accounts with a balance sheet file: + +```shell +gnogenesis balances add --balance-sheet ./balances.txt +``` + +The format of the balance sheet file is the same as with individual entries, for example: + +```text +# Test accounts. +g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5=10000000000000ugnot # test1 +g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj=10000000000000ugnot # test2 + +# Faucet accounts. +g1f4v282mwyhu29afke4vq5r2xzcm6z3ftnugcnv=1000000000000ugnot # faucet0 (jae) +g127jydsh6cms3lrtdenydxsckh23a8d6emqcvfa=1000000000000ugnot # faucet1 (moul) +g1q6jrp203fq0239pv38sdq3y3urvd6vt5azacpv=1000000000000ugnot # faucet2 (devx) +g13d7jc32adhc39erm5me38w5v7ej7lpvlnqjk73=1000000000000ugnot # faucet3 (devx) +g18l9us6trqaljw39j94wzf5ftxmd9qqkvrxghd2=1000000000000ugnot # faucet4 (adena) +``` + +This will update `genesis.json` with the provided accounts and balances. + +#### Remove account balances + +To remove an account’s balance from `genesis.json`, use: + +```shell +gnogenesis balances remove --address g1rzuwh5frve732k4futyw45y78rzuty4626zy6h +``` + +This deletes the balance entry for the specified address, if present. + +### Handle genesis transactions + +The `txs` subcommand allows you to manage initial transactions. + +It is a bit more robust than the `balances` command suite, in the sense that it supports: + +- adding transactions from transaction sheets +- generating and adding deploy transactions from a directory (ex. like `examples`) + +The format for transactions in the transaction sheet is the following: + +- Transaction (`std.Tx`) is encoded in Amino JSON +- Transactions are saved single-line, 1 line 1 tx +- File format of the transaction sheet file is `jsonl` + +#### Add genesis transactions + +To add genesis transactions from a file: + +```shell +gnogenesis txs add sheets ./txs.json +``` + +This outputs the initial transaction count. + +An example transaction sheet: + +```json lines +{"msg":[{"@type":"/vm.m_call","caller":"g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq","send":"","pkg_path":"gno.land/r/demo/users","func":"Invite","args":["g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj:10\ng1589c8cekvmjfmy0qrd4f3z52r7fn7rgk02667s:1\ng13sm84nuqed3fuank8huh7x9mupgw22uft3lcl8:1\ng1m6732pkrngu9vrt0g7056lvr9kcqc4mv83xl5q:1\ng1wg88rhzlwxjd2z4j5de5v5xq30dcf6rjq3dhsj:1\ng18pmaskasz7mxj6rmgrl3al58xu45a7w0l5nmc0:1\ng19wwhkmqlns70604ksp6rkuuu42qhtvyh05lffz:1\ng187982000zsc493znqt828s90cmp6hcp2erhu6m:1\ng1ndpsnrspdnauckytvkfv8s823t3gmpqmtky8pl:1\ng16ja66d65emkr0zxd2tu7xjvm7utthyhpej0037:1\ng1ds24jj9kqjcskd0gzu24r9e4n62ggye230zuv5:1\ng1trkzq75ntamsnw9xnrav2v7gy2lt5g6p29yhdr:1\ng1rrf8s5mrmu00sx04fzfsvc399fklpeg2x0a7mz:1\ng19p5ntfvpt4lwq4jqsmnxsnelhf3tff9scy3w8w:1\ng1tue8l73d6rq4vhqdsp2sr3zhuzpure3k2rnwpz:1\ng14hhsss4ngx5kq77je5g0tl4vftg8qp45ceadk3:1\ng1768hvkh7anhd40ch4h7jdh6j3mpcs7hrat4gl0:1\ng15fa8kyjhu88t9dr8zzua8fwdvkngv5n8yqsm0n:1\ng1xhccdjcscuhgmt3quww6qdy3j3czqt3urc2eac:1\ng1z629z04f85k4t5gnkk5egpxw9tqxeec435esap:1\ng1pfldkplz9puq0v82lu9vqcve9nwrxuq9qe5ttv:1\ng152pn0g5qfgxr7yx8zlwjq48hytkafd8x7egsfv:1\ng1cf2ye686ke38vjyqakreprljum4xu6rwf5jskq:1\ng1c5shztyaj4gjrc5zlwmh9xhex5w7l4asffs2w6:1\ng1lhpx2ktk0ha3qw42raxq4m24a4c4xqxyrgv54q:1\ng1026p54q0j902059sm2zsv37krf0ghcl7gmhyv7:1\ng1n4yvwnv77frq2ccuw27dmtjkd7u4p4jg0pgm7k:1\ng13m7f2e6r3lh3ykxupacdt9sem2tlvmaamwjhll:1\ng19uxluuecjlsqvwmwu8sp6pxaaqfhk972q975xd:1\ng1j80fpcsumfkxypvydvtwtz3j4sdwr8c2u0lr64:1\ng1tjdpptuk9eysq6z38nscqyycr998xjyx3w8jvw:1\ng19t3n89slfemgd3mwuat4lajwcp0yxrkadgeg7a:1\ng1yqndt8xx92l9h494jfruz2w79swzjes3n4wqjc:1\ng13278z0a5ufeg80ffqxpda9dlp599t7ekregcy6:1\ng1ht236wjd83x96uqwh9rh3fq6pylyn78mtwq9v6:1\ng1fj9jccm3zjnqspq7lp2g7lj4czyfq0s35600g9:1\ng1wwppuzdns5u6c6jqpkzua24zh6ppsus6399cea:1\ng1k8pjnguyu36pkc8hy0ufzgpzfmj2jl78la7ek3:1\ng1e8umkzumtxgs8399lw0us4rclea3xl5gxy9spp:1\ng14qekdkj2nmmwea4ufg9n002a3pud23y8k7ugs5:1\ng19w2488ntfgpduzqq3sk4j5x387zynwknqdvjqf:1\ng1495y3z7zrej4rendysnw5kaeu4g3d7x7w0734g:1\ng1hygx8ga9qakhkczyrzs9drm8j8tu4qds9y5e3r:1\ng1f977l6wxdh3qu60kzl75vx2wmzswu68l03r8su:1\ng1644qje5rx6jsdqfkzmgnfcegx4dxkjh6rwqd69:1\ng1mzjajymvmtksdwh3wkrndwj6zls2awl9q83dh6:1\ng14da4n9hcynyzz83q607uu8keuh9hwlv42ra6fa:10\ng14vhcdsyf83ngsrrqc92kmw8q9xakqjm0v8448t:5\n"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AmG6kzznyo1uNqWPAYU6wDpsmzQKDaEOrVRaZ08vOyX0"},"signature":"S8iMMzlOMK8dmox78R9Z8+pSsS8YaTCXrIcaHDpiOgkOy7gqoQJ0oftM0zf8zAz4xpezK8Lzg8Q0fCdXJxV76w=="}],"memo":""} +{"msg":[{"@type":"/vm.m_call","caller":"g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq","send":"","pkg_path":"gno.land/r/demo/users","func":"Invite","args":["g1thlf3yct7n7ex70k0p62user0kn6mj6d3s0cg3\ng1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5\n"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AmG6kzznyo1uNqWPAYU6wDpsmzQKDaEOrVRaZ08vOyX0"},"signature":"njczE6xYdp01+CaUU/8/v0YC/NuZD06+qLind+ZZEEMNaRe/4Ln+4z7dG6HYlaWUMsyI1KCoB6NIehoE0PZ44Q=="}],"memo":""} +{"msg":[{"@type":"/vm.m_call","caller":"g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq","send":"","pkg_path":"gno.land/r/demo/users","func":"Invite","args":["g1589c8cekvmjfmy0qrd4f3z52r7fn7rgk02667s\ng13sm84nuqed3fuank8huh7x9mupgw22uft3lcl8\ng1m6732pkrngu9vrt0g7056lvr9kcqc4mv83xl5q\ng1wg88rhzlwxjd2z4j5de5v5xq30dcf6rjq3dhsj\ng18pmaskasz7mxj6rmgrl3al58xu45a7w0l5nmc0\ng19wwhkmqlns70604ksp6rkuuu42qhtvyh05lffz\ng187982000zsc493znqt828s90cmp6hcp2erhu6m\ng1ndpsnrspdnauckytvkfv8s823t3gmpqmtky8pl\ng16ja66d65emkr0zxd2tu7xjvm7utthyhpej0037\ng1ds24jj9kqjcskd0gzu24r9e4n62ggye230zuv5\ng1trkzq75ntamsnw9xnrav2v7gy2lt5g6p29yhdr\ng1rrf8s5mrmu00sx04fzfsvc399fklpeg2x0a7mz\ng19p5ntfvpt4lwq4jqsmnxsnelhf3tff9scy3w8w\ng1tue8l73d6rq4vhqdsp2sr3zhuzpure3k2rnwpz\ng14hhsss4ngx5kq77je5g0tl4vftg8qp45ceadk3\ng1768hvkh7anhd40ch4h7jdh6j3mpcs7hrat4gl0\ng15fa8kyjhu88t9dr8zzua8fwdvkngv5n8yqsm0n\ng1xhccdjcscuhgmt3quww6qdy3j3czqt3urc2eac\ng1z629z04f85k4t5gnkk5egpxw9tqxeec435esap\ng1pfldkplz9puq0v82lu9vqcve9nwrxuq9qe5ttv\ng152pn0g5qfgxr7yx8zlwjq48hytkafd8x7egsfv\ng1cf2ye686ke38vjyqakreprljum4xu6rwf5jskq\ng1c5shztyaj4gjrc5zlwmh9xhex5w7l4asffs2w6\ng1lhpx2ktk0ha3qw42raxq4m24a4c4xqxyrgv54q\ng1026p54q0j902059sm2zsv37krf0ghcl7gmhyv7\ng1n4yvwnv77frq2ccuw27dmtjkd7u4p4jg0pgm7k\ng13m7f2e6r3lh3ykxupacdt9sem2tlvmaamwjhll\ng19uxluuecjlsqvwmwu8sp6pxaaqfhk972q975xd\ng1j80fpcsumfkxypvydvtwtz3j4sdwr8c2u0lr64\ng1tjdpptuk9eysq6z38nscqyycr998xjyx3w8jvw\ng19t3n89slfemgd3mwuat4lajwcp0yxrkadgeg7a\ng1yqndt8xx92l9h494jfruz2w79swzjes3n4wqjc\ng13278z0a5ufeg80ffqxpda9dlp599t7ekregcy6\ng1ht236wjd83x96uqwh9rh3fq6pylyn78mtwq9v6\ng1fj9jccm3zjnqspq7lp2g7lj4czyfq0s35600g9\ng1wwppuzdns5u6c6jqpkzua24zh6ppsus6399cea\ng1k8pjnguyu36pkc8hy0ufzgpzfmj2jl78la7ek3\ng1e8umkzumtxgs8399lw0us4rclea3xl5gxy9spp\ng14qekdkj2nmmwea4ufg9n002a3pud23y8k7ugs5\ng19w2488ntfgpduzqq3sk4j5x387zynwknqdvjqf\ng1495y3z7zrej4rendysnw5kaeu4g3d7x7w0734g\ng1hygx8ga9qakhkczyrzs9drm8j8tu4qds9y5e3r\ng1f977l6wxdh3qu60kzl75vx2wmzswu68l03r8su\ng1644qje5rx6jsdqfkzmgnfcegx4dxkjh6rwqd69\ng1mzjajymvmtksdwh3wkrndwj6zls2awl9q83dh6\ng1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq\ng14da4n9hcynyzz83q607uu8keuh9hwlv42ra6fa\ng14vhcdsyf83ngsrrqc92kmw8q9xakqjm0v8448t\n"]}],"fee":{"gas_wanted":"4000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AmG6kzznyo1uNqWPAYU6wDpsmzQKDaEOrVRaZ08vOyX0"},"signature":"7AmlhZhsVkxCUl0bbpvpPMnIKihwtG7A5IFR6Tg4xStWLgaUr05XmWRKlO2xjstTtwbVKQT5mFL4h5wyX4SQzw=="}],"memo":""} +``` + +To add genesis (deploy) transactions from a directory: + +```shell +gnogenesis txs add packages ./examples +``` + +This will generate `MsgAddPkg` transactions, and add them to the given `genesis.json`. + +#### Remove genesis transactions + +To clear specific transactions, use the transaction hash: + +```shell +gnogenesis txs remove "5HuU9LN8WUa2NsjiNxp8Xii9n0zlSGXc9UqzLHB+DPs=" +``` + +The transaction hash is the base64 encoding of the Amino-Binary encoded `std.Tx` transaction hash. + +The steps to get this sort of hash are: + +- get the `std.Tx` +- marshal it using `amino.Marshal` +- cast the result to `types.Tx` (`bft`) +- call `Hash` on the `types.Tx` +- encode the result into base64 diff --git a/contribs/gnogenesis/genesis.go b/contribs/gnogenesis/genesis.go new file mode 100644 index 00000000000..839e5fbe653 --- /dev/null +++ b/contribs/gnogenesis/genesis.go @@ -0,0 +1,32 @@ +package main + +import ( + "github.com/gnolang/contribs/gnogenesis/internal/balances" + "github.com/gnolang/contribs/gnogenesis/internal/generate" + "github.com/gnolang/contribs/gnogenesis/internal/txs" + "github.com/gnolang/contribs/gnogenesis/internal/validator" + "github.com/gnolang/contribs/gnogenesis/internal/verify" + "github.com/gnolang/gno/tm2/pkg/commands" +) + +func newGenesisCmd(io commands.IO) *commands.Command { + cmd := commands.NewCommand( + commands.Metadata{ + ShortUsage: " [flags] [...]", + ShortHelp: "gno genesis manipulation suite", + LongHelp: "Gno genesis.json manipulation suite, for managing genesis parameters", + }, + commands.NewEmptyConfig(), + commands.HelpExec, + ) + + cmd.AddSubCommands( + generate.NewGenerateCmd(io), + validator.NewValidatorCmd(io), + verify.NewVerifyCmd(io), + balances.NewBalancesCmd(io), + txs.NewTxsCmd(io), + ) + + return cmd +} diff --git a/contribs/gnogenesis/go.mod b/contribs/gnogenesis/go.mod new file mode 100644 index 00000000000..393fed0725d --- /dev/null +++ b/contribs/gnogenesis/go.mod @@ -0,0 +1,62 @@ +module github.com/gnolang/contribs/gnogenesis + +go 1.22 + +require ( + github.com/gnolang/gno v0.0.0-00010101000000-000000000000 + github.com/stretchr/testify v1.9.0 +) + +replace github.com/gnolang/gno => ../.. + +require ( + dario.cat/mergo v1.0.1 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/btcsuite/btcd/btcutil v1.1.6 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cockroachdb/apd/v3 v3.2.1 // indirect + github.com/cosmos/ledger-cosmos-go v0.13.3 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect + github.com/gnolang/overflow v0.0.0-20170615021017-4d914c927216 // indirect + github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/websocket v1.5.3 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect + github.com/libp2p/go-buffer-pool v0.1.0 // indirect + 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.11.1 // indirect + github.com/rs/xid v1.6.0 // indirect + github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect + github.com/zondax/hid v0.9.2 // indirect + github.com/zondax/ledger-go v0.14.3 // indirect + go.etcd.io/bbolt v1.3.11 // indirect + go.opentelemetry.io/otel v1.29.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.29.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.29.0 // indirect + go.opentelemetry.io/otel/metric v1.29.0 // indirect + go.opentelemetry.io/otel/sdk v1.29.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.29.0 // indirect + go.opentelemetry.io/otel/trace v1.29.0 // indirect + go.opentelemetry.io/proto/otlp v1.3.1 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/crypto v0.26.0 // indirect + golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 // indirect + golang.org/x/mod v0.20.0 // indirect + golang.org/x/net v0.28.0 // indirect + golang.org/x/sys v0.24.0 // indirect + golang.org/x/term v0.23.0 // indirect + golang.org/x/text v0.17.0 // indirect + golang.org/x/tools v0.24.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd // indirect + google.golang.org/grpc v1.65.0 // indirect + google.golang.org/protobuf v1.35.1 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/contribs/gnogenesis/go.sum b/contribs/gnogenesis/go.sum new file mode 100644 index 00000000000..f3161e47bad --- /dev/null +++ b/contribs/gnogenesis/go.sum @@ -0,0 +1,230 @@ +dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= +dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +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.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= +github.com/btcsuite/btcd v0.24.2 h1:aLmxPguqxza+4ag8R1I2nnJjSu2iFn/kqtHTIImswcY= +github.com/btcsuite/btcd v0.24.2/go.mod h1:5C8ChTkl5ejr3WHj8tkQSCmydiMEPB0ZhQhehpq7Dgg= +github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= +github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= +github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= +github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= +github.com/btcsuite/btcd/btcutil v1.1.6 h1:zFL2+c3Lb9gEgqKNzowKUPQNb8jV7v5Oaodi/AYFd6c= +github.com/btcsuite/btcd/btcutil v1.1.6/go.mod h1:9dFymx8HpuLqBnsPELrImQeTQfKBQqzqGbbV3jK55aE= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cockroachdb/apd/v3 v3.2.1 h1:U+8j7t0axsIgvQUqthuNm82HIrYXodOV2iWLWtEaIwg= +github.com/cockroachdb/apd/v3 v3.2.1/go.mod h1:klXJcjp+FffLTHlhIG69tezTDvdP065naDsHzKhYSqc= +github.com/cosmos/ledger-cosmos-go v0.13.3 h1:7ehuBGuyIytsXbd4MP43mLeoN2LTOEnk5nvue4rK+yM= +github.com/cosmos/ledger-cosmos-go v0.13.3/go.mod h1:HENcEP+VtahZFw38HZ3+LS3Iv5XV6svsnkk9vdJtLr8= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/gnolang/overflow v0.0.0-20170615021017-4d914c927216 h1:GKvsK3oLWG9B1GL7WP/VqwM6C92j5tIvB844oggL9Lk= +github.com/gnolang/overflow v0.0.0-20170615021017-4d914c927216/go.mod h1:xJhtEL7ahjM1WJipt89gel8tHzfIl/LyMY+lCYh38d8= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +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/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= +github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= +github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= +github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= +github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= +github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/peterbourgon/ff/v3 v3.4.0 h1:QBvM/rizZM1cB0p0lGMdmR7HxZeI/ZrBWB4DqLkMUBc= +github.com/peterbourgon/ff/v3 v3.4.0/go.mod h1:zjJVUhx+twciwfDl0zBcFzl4dW8axCRyXE/eKY9RztQ= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= +github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU= +github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= +github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= +github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw= +github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI= +go.etcd.io/bbolt v1.3.11 h1:yGEzV1wPz2yVCLsD8ZAiGHhHVlczyC9d1rP43/VCRJ0= +go.etcd.io/bbolt v1.3.11/go.mod h1:dksAq7YMXoljX0xu6VF5DMZGbhYYoLUalEiSySYAS4I= +go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw= +go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.29.0 h1:k6fQVDQexDE+3jG2SfCQjnHS7OamcP73YMoxEVq5B6k= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.29.0/go.mod h1:t4BrYLHU450Zo9fnydWlIuswB1bm7rM8havDpWOJeDo= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.29.0 h1:xvhQxJ/C9+RTnAj5DpTg7LSM1vbbMTiXt7e9hsfqHNw= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.29.0/go.mod h1:Fcvs2Bz1jkDM+Wf5/ozBGmi3tQ/c9zPKLnsipnfhGAo= +go.opentelemetry.io/otel/metric v1.29.0 h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc= +go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8= +go.opentelemetry.io/otel/sdk v1.29.0 h1:vkqKjk7gwhS8VaWb0POZKmIEDimRCMsopNYnriHyryo= +go.opentelemetry.io/otel/sdk v1.29.0/go.mod h1:pM8Dx5WKnvxLCb+8lG1PRNIDxu9g9b9g59Qr7hfAAok= +go.opentelemetry.io/otel/sdk/metric v1.29.0 h1:K2CfmJohnRgvZ9UAj2/FhIf/okdWcNdBwe1m8xFXiSY= +go.opentelemetry.io/otel/sdk/metric v1.29.0/go.mod h1:6zZLdCl2fkauYoZIOn/soQIDSWFmNSRcICarHfuhNJQ= +go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt39JTi4= +go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= +golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= +golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY= +golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= +golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= +golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd h1:BBOTEWLuuEGQy9n1y9MhVJ9Qt0BDu21X8qZs71/uPZo= +google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:fO8wJzT2zbQbAjbIoos1285VfEIYKDDY+Dt+WpTkh6g= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd h1:6TEm2ZxXoQmFWFlt1vNxvVOa1Q0dXFQD1m/rYjXmS0E= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= +google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/gno.land/cmd/gnoland/genesis_balances.go b/contribs/gnogenesis/internal/balances/balances.go similarity index 68% rename from gno.land/cmd/gnoland/genesis_balances.go rename to contribs/gnogenesis/internal/balances/balances.go index c8cd1c539f5..bdfa5aa38d0 100644 --- a/gno.land/cmd/gnoland/genesis_balances.go +++ b/contribs/gnogenesis/internal/balances/balances.go @@ -1,23 +1,24 @@ -package main +package balances import ( "flag" + "github.com/gnolang/contribs/gnogenesis/internal/common" "github.com/gnolang/gno/tm2/pkg/commands" ) type balancesCfg struct { - commonCfg + common.Cfg } -// newBalancesCmd creates the genesis balances subcommand -func newBalancesCmd(io commands.IO) *commands.Command { +// NewBalancesCmd creates the genesis balances subcommand +func NewBalancesCmd(io commands.IO) *commands.Command { cfg := &balancesCfg{} cmd := commands.NewCommand( commands.Metadata{ Name: "balances", - ShortUsage: "balances [flags]", + ShortUsage: " [flags]", ShortHelp: "manages genesis.json account balances", LongHelp: "Manipulates the initial genesis.json account balances (pre-mines)", }, @@ -35,5 +36,5 @@ func newBalancesCmd(io commands.IO) *commands.Command { } func (c *balancesCfg) RegisterFlags(fs *flag.FlagSet) { - c.commonCfg.RegisterFlags(fs) + c.Cfg.RegisterFlags(fs) } diff --git a/gno.land/cmd/gnoland/genesis_balances_add.go b/contribs/gnogenesis/internal/balances/balances_add.go similarity index 98% rename from gno.land/cmd/gnoland/genesis_balances_add.go rename to contribs/gnogenesis/internal/balances/balances_add.go index f9a898715c8..a17a13f8bc8 100644 --- a/gno.land/cmd/gnoland/genesis_balances_add.go +++ b/contribs/gnogenesis/internal/balances/balances_add.go @@ -1,4 +1,4 @@ -package main +package balances import ( "bufio" @@ -77,7 +77,7 @@ func (c *balancesAddCfg) RegisterFlags(fs *flag.FlagSet) { func execBalancesAdd(ctx context.Context, cfg *balancesAddCfg, io commands.IO) error { // Load the genesis - genesis, loadErr := types.GenesisDocFromFile(cfg.rootCfg.genesisPath) + genesis, loadErr := types.GenesisDocFromFile(cfg.rootCfg.GenesisPath) if loadErr != nil { return fmt.Errorf("unable to load genesis, %w", loadErr) } @@ -156,7 +156,7 @@ func execBalancesAdd(ctx context.Context, cfg *balancesAddCfg, io commands.IO) e genesis.AppState = state // Save the updated genesis - if err := genesis.SaveAs(cfg.rootCfg.genesisPath); err != nil { + if err := genesis.SaveAs(cfg.rootCfg.GenesisPath); err != nil { return fmt.Errorf("unable to save genesis.json, %w", err) } diff --git a/gno.land/cmd/gnoland/genesis_balances_add_test.go b/contribs/gnogenesis/internal/balances/balances_add_test.go similarity index 92% rename from gno.land/cmd/gnoland/genesis_balances_add_test.go rename to contribs/gnogenesis/internal/balances/balances_add_test.go index 8f2879f9c57..29ffe19d95a 100644 --- a/gno.land/cmd/gnoland/genesis_balances_add_test.go +++ b/contribs/gnogenesis/internal/balances/balances_add_test.go @@ -1,4 +1,4 @@ -package main +package balances import ( "bytes" @@ -7,6 +7,7 @@ import ( "strings" "testing" + "github.com/gnolang/contribs/gnogenesis/internal/common" "github.com/gnolang/gno/gno.land/pkg/gnoland" "github.com/gnolang/gno/gno.land/pkg/gnoland/ugnot" "github.com/gnolang/gno/tm2/pkg/amino" @@ -24,10 +25,8 @@ func TestGenesis_Balances_Add(t *testing.T) { t.Run("invalid genesis", func(t *testing.T) { // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewBalancesCmd(commands.NewTestIO()) args := []string{ - "genesis", - "balances", "add", "--genesis-path", "dummy-path", @@ -35,7 +34,7 @@ func TestGenesis_Balances_Add(t *testing.T) { // Run the command cmdErr := cmd.ParseAndRun(context.Background(), args) - require.ErrorContains(t, cmdErr, errUnableToLoadGenesis.Error()) + require.ErrorContains(t, cmdErr, common.ErrUnableToLoadGenesis.Error()) }) t.Run("no sources selected", func(t *testing.T) { @@ -44,14 +43,12 @@ func TestGenesis_Balances_Add(t *testing.T) { tempGenesis, cleanup := testutils.NewTestFile(t) t.Cleanup(cleanup) - genesis := getDefaultGenesis() + genesis := common.GetDefaultGenesis() require.NoError(t, genesis.SaveAs(tempGenesis.Name())) // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewBalancesCmd(commands.NewTestIO()) args := []string{ - "genesis", - "balances", "add", "--genesis-path", tempGenesis.Name(), @@ -66,10 +63,8 @@ func TestGenesis_Balances_Add(t *testing.T) { t.Parallel() // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewBalancesCmd(commands.NewTestIO()) args := []string{ - "genesis", - "balances", "add", "--genesis-path", "dummy-path", @@ -77,25 +72,23 @@ func TestGenesis_Balances_Add(t *testing.T) { // Run the command cmdErr := cmd.ParseAndRun(context.Background(), args) - assert.ErrorContains(t, cmdErr, errUnableToLoadGenesis.Error()) + assert.ErrorContains(t, cmdErr, common.ErrUnableToLoadGenesis.Error()) }) t.Run("balances from entries", func(t *testing.T) { t.Parallel() - dummyKeys := getDummyKeys(t, 2) + dummyKeys := common.GetDummyKeys(t, 2) tempGenesis, cleanup := testutils.NewTestFile(t) t.Cleanup(cleanup) - genesis := getDefaultGenesis() + genesis := common.GetDefaultGenesis() require.NoError(t, genesis.SaveAs(tempGenesis.Name())) // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewBalancesCmd(commands.NewTestIO()) args := []string{ - "genesis", - "balances", "add", "--genesis-path", tempGenesis.Name(), @@ -155,10 +148,10 @@ func TestGenesis_Balances_Add(t *testing.T) { tempGenesis, cleanup := testutils.NewTestFile(t) t.Cleanup(cleanup) - genesis := getDefaultGenesis() + genesis := common.GetDefaultGenesis() require.NoError(t, genesis.SaveAs(tempGenesis.Name())) - dummyKeys := getDummyKeys(t, 10) + dummyKeys := common.GetDummyKeys(t, 10) amount := std.NewCoins(std.NewCoin(ugnot.Denom, 10)) balances := make([]string, len(dummyKeys)) @@ -182,10 +175,8 @@ func TestGenesis_Balances_Add(t *testing.T) { require.NoError(t, err) // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewBalancesCmd(commands.NewTestIO()) args := []string{ - "genesis", - "balances", "add", "--genesis-path", tempGenesis.Name(), @@ -233,11 +224,11 @@ func TestGenesis_Balances_Add(t *testing.T) { tempGenesis, cleanup := testutils.NewTestFile(t) t.Cleanup(cleanup) - genesis := getDefaultGenesis() + genesis := common.GetDefaultGenesis() require.NoError(t, genesis.SaveAs(tempGenesis.Name())) var ( - dummyKeys = getDummyKeys(t, 10) + dummyKeys = common.GetDummyKeys(t, 10) amount = std.NewCoins(std.NewCoin(ugnot.Denom, 10)) amountCoins = std.NewCoins(std.NewCoin(ugnot.Denom, 10)) gasFee = std.NewCoin(ugnot.Denom, 1000000) @@ -282,10 +273,8 @@ func TestGenesis_Balances_Add(t *testing.T) { require.NoError(t, err) // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewBalancesCmd(commands.NewTestIO()) args := []string{ - "genesis", - "balances", "add", "--genesis-path", tempGenesis.Name(), @@ -337,12 +326,12 @@ func TestGenesis_Balances_Add(t *testing.T) { t.Run("balances overwrite", func(t *testing.T) { t.Parallel() - dummyKeys := getDummyKeys(t, 10) + dummyKeys := common.GetDummyKeys(t, 10) tempGenesis, cleanup := testutils.NewTestFile(t) t.Cleanup(cleanup) - genesis := getDefaultGenesis() + genesis := common.GetDefaultGenesis() state := gnoland.GnoGenesisState{ // Set an initial balance value Balances: []gnoland.Balance{ @@ -356,10 +345,8 @@ func TestGenesis_Balances_Add(t *testing.T) { require.NoError(t, genesis.SaveAs(tempGenesis.Name())) // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewBalancesCmd(commands.NewTestIO()) args := []string{ - "genesis", - "balances", "add", "--genesis-path", tempGenesis.Name(), @@ -421,7 +408,7 @@ func TestBalances_GetBalancesFromTransactions(t *testing.T) { t.Parallel() var ( - dummyKeys = getDummyKeys(t, 10) + dummyKeys = common.GetDummyKeys(t, 10) amount = std.NewCoins(std.NewCoin(ugnot.Denom, 10)) amountCoins = std.NewCoins(std.NewCoin(ugnot.Denom, 10)) gasFee = std.NewCoin(ugnot.Denom, 1000000) @@ -479,7 +466,7 @@ func TestBalances_GetBalancesFromTransactions(t *testing.T) { t.Parallel() var ( - dummyKeys = getDummyKeys(t, 10) + dummyKeys = common.GetDummyKeys(t, 10) amountCoins = std.NewCoins(std.NewCoin(ugnot.Denom, 10)) gasFee = std.NewCoin("gnos", 1) // invalid fee txs = make([]std.Tx, 0) @@ -531,7 +518,7 @@ func TestBalances_GetBalancesFromTransactions(t *testing.T) { t.Parallel() var ( - dummyKeys = getDummyKeys(t, 10) + dummyKeys = common.GetDummyKeys(t, 10) amountCoins = std.NewCoins(std.NewCoin("gnogno", 10)) // invalid send amount gasFee = std.NewCoin(ugnot.Denom, 1) txs = make([]std.Tx, 0) diff --git a/gno.land/cmd/gnoland/genesis_balances_export.go b/contribs/gnogenesis/internal/balances/balances_export.go similarity index 89% rename from gno.land/cmd/gnoland/genesis_balances_export.go rename to contribs/gnogenesis/internal/balances/balances_export.go index ec05d115b97..df9d6795805 100644 --- a/gno.land/cmd/gnoland/genesis_balances_export.go +++ b/contribs/gnogenesis/internal/balances/balances_export.go @@ -1,10 +1,11 @@ -package main +package balances import ( "context" "fmt" "os" + "github.com/gnolang/contribs/gnogenesis/internal/common" "github.com/gnolang/gno/gno.land/pkg/gnoland" "github.com/gnolang/gno/tm2/pkg/bft/types" "github.com/gnolang/gno/tm2/pkg/commands" @@ -28,14 +29,14 @@ func newBalancesExportCmd(balancesCfg *balancesCfg, io commands.IO) *commands.Co func execBalancesExport(cfg *balancesCfg, io commands.IO, args []string) error { // Load the genesis - genesis, loadErr := types.GenesisDocFromFile(cfg.genesisPath) + genesis, loadErr := types.GenesisDocFromFile(cfg.GenesisPath) if loadErr != nil { return fmt.Errorf("unable to load genesis, %w", loadErr) } // Load the genesis state if genesis.AppState == nil { - return errAppStateNotSet + return common.ErrAppStateNotSet } state := genesis.AppState.(gnoland.GnoGenesisState) @@ -47,7 +48,7 @@ func execBalancesExport(cfg *balancesCfg, io commands.IO, args []string) error { // Make sure the output file path is specified if len(args) == 0 { - return errNoOutputFile + return common.ErrNoOutputFile } // Open output file diff --git a/gno.land/cmd/gnoland/genesis_balances_export_test.go b/contribs/gnogenesis/internal/balances/balances_export_test.go similarity index 83% rename from gno.land/cmd/gnoland/genesis_balances_export_test.go rename to contribs/gnogenesis/internal/balances/balances_export_test.go index bd1f6152246..d4f4723df15 100644 --- a/gno.land/cmd/gnoland/genesis_balances_export_test.go +++ b/contribs/gnogenesis/internal/balances/balances_export_test.go @@ -1,10 +1,11 @@ -package main +package balances import ( "bufio" "context" "testing" + "github.com/gnolang/contribs/gnogenesis/internal/common" "github.com/gnolang/gno/gno.land/pkg/gnoland" "github.com/gnolang/gno/gno.land/pkg/gnoland/ugnot" "github.com/gnolang/gno/tm2/pkg/commands" @@ -18,7 +19,7 @@ import ( func getDummyBalances(t *testing.T, count int) []gnoland.Balance { t.Helper() - dummyKeys := getDummyKeys(t, count) + dummyKeys := common.GetDummyKeys(t, count) amount := std.NewCoins(std.NewCoin(ugnot.Denom, 10)) balances := make([]gnoland.Balance, len(dummyKeys)) @@ -40,10 +41,8 @@ func TestGenesis_Balances_Export(t *testing.T) { t.Parallel() // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewBalancesCmd(commands.NewTestIO()) args := []string{ - "genesis", - "balances", "export", "--genesis-path", "dummy-path", @@ -51,7 +50,7 @@ func TestGenesis_Balances_Export(t *testing.T) { // Run the command cmdErr := cmd.ParseAndRun(context.Background(), args) - assert.ErrorContains(t, cmdErr, errUnableToLoadGenesis.Error()) + assert.ErrorContains(t, cmdErr, common.ErrUnableToLoadGenesis.Error()) }) t.Run("invalid genesis app state", func(t *testing.T) { @@ -60,15 +59,13 @@ func TestGenesis_Balances_Export(t *testing.T) { tempGenesis, cleanup := testutils.NewTestFile(t) t.Cleanup(cleanup) - genesis := getDefaultGenesis() + genesis := common.GetDefaultGenesis() genesis.AppState = nil // no app state require.NoError(t, genesis.SaveAs(tempGenesis.Name())) // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewBalancesCmd(commands.NewTestIO()) args := []string{ - "genesis", - "balances", "export", "--genesis-path", tempGenesis.Name(), @@ -76,7 +73,7 @@ func TestGenesis_Balances_Export(t *testing.T) { // Run the command cmdErr := cmd.ParseAndRun(context.Background(), args) - assert.ErrorContains(t, cmdErr, errAppStateNotSet.Error()) + assert.ErrorContains(t, cmdErr, common.ErrAppStateNotSet.Error()) }) t.Run("no output file specified", func(t *testing.T) { @@ -85,17 +82,15 @@ func TestGenesis_Balances_Export(t *testing.T) { tempGenesis, cleanup := testutils.NewTestFile(t) t.Cleanup(cleanup) - genesis := getDefaultGenesis() + genesis := common.GetDefaultGenesis() genesis.AppState = gnoland.GnoGenesisState{ Balances: getDummyBalances(t, 1), } require.NoError(t, genesis.SaveAs(tempGenesis.Name())) // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewBalancesCmd(commands.NewTestIO()) args := []string{ - "genesis", - "balances", "export", "--genesis-path", tempGenesis.Name(), @@ -103,7 +98,7 @@ func TestGenesis_Balances_Export(t *testing.T) { // Run the command cmdErr := cmd.ParseAndRun(context.Background(), args) - assert.ErrorContains(t, cmdErr, errNoOutputFile.Error()) + assert.ErrorContains(t, cmdErr, common.ErrNoOutputFile.Error()) }) t.Run("valid balances export", func(t *testing.T) { @@ -115,7 +110,7 @@ func TestGenesis_Balances_Export(t *testing.T) { tempGenesis, cleanup := testutils.NewTestFile(t) t.Cleanup(cleanup) - genesis := getDefaultGenesis() + genesis := common.GetDefaultGenesis() genesis.AppState = gnoland.GnoGenesisState{ Balances: balances, } @@ -126,10 +121,8 @@ func TestGenesis_Balances_Export(t *testing.T) { t.Cleanup(outputCleanup) // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewBalancesCmd(commands.NewTestIO()) args := []string{ - "genesis", - "balances", "export", "--genesis-path", tempGenesis.Name(), diff --git a/gno.land/cmd/gnoland/genesis_balances_remove.go b/contribs/gnogenesis/internal/balances/balances_remove.go similarity index 84% rename from gno.land/cmd/gnoland/genesis_balances_remove.go rename to contribs/gnogenesis/internal/balances/balances_remove.go index 58a02319c8d..ea2aefda5cc 100644 --- a/gno.land/cmd/gnoland/genesis_balances_remove.go +++ b/contribs/gnogenesis/internal/balances/balances_remove.go @@ -1,4 +1,4 @@ -package main +package balances import ( "context" @@ -6,16 +6,14 @@ import ( "flag" "fmt" + "github.com/gnolang/contribs/gnogenesis/internal/common" "github.com/gnolang/gno/gno.land/pkg/gnoland" "github.com/gnolang/gno/tm2/pkg/bft/types" "github.com/gnolang/gno/tm2/pkg/commands" "github.com/gnolang/gno/tm2/pkg/crypto" ) -var ( - errUnableToLoadGenesis = errors.New("unable to load genesis") - errBalanceNotFound = errors.New("genesis balances entry does not exist") -) +var errBalanceNotFound = errors.New("genesis balances entry does not exist") type balancesRemoveCfg struct { rootCfg *balancesCfg @@ -53,9 +51,9 @@ func (c *balancesRemoveCfg) RegisterFlags(fs *flag.FlagSet) { func execBalancesRemove(cfg *balancesRemoveCfg, io commands.IO) error { // Load the genesis - genesis, loadErr := types.GenesisDocFromFile(cfg.rootCfg.genesisPath) + genesis, loadErr := types.GenesisDocFromFile(cfg.rootCfg.GenesisPath) if loadErr != nil { - return fmt.Errorf("%w, %w", errUnableToLoadGenesis, loadErr) + return fmt.Errorf("%w, %w", common.ErrUnableToLoadGenesis, loadErr) } // Validate the address @@ -66,7 +64,7 @@ func execBalancesRemove(cfg *balancesRemoveCfg, io commands.IO) error { // Check if the genesis state is set at all if genesis.AppState == nil { - return errAppStateNotSet + return common.ErrAppStateNotSet } // Construct the initial genesis balance sheet @@ -90,7 +88,7 @@ func execBalancesRemove(cfg *balancesRemoveCfg, io commands.IO) error { genesis.AppState = state // Save the updated genesis - if err := genesis.SaveAs(cfg.rootCfg.genesisPath); err != nil { + if err := genesis.SaveAs(cfg.rootCfg.GenesisPath); err != nil { return fmt.Errorf("unable to save genesis.json, %w", err) } diff --git a/gno.land/cmd/gnoland/genesis_balances_remove_test.go b/contribs/gnogenesis/internal/balances/balances_remove_test.go similarity index 81% rename from gno.land/cmd/gnoland/genesis_balances_remove_test.go rename to contribs/gnogenesis/internal/balances/balances_remove_test.go index ed11836ba4d..ab99a31c0a9 100644 --- a/gno.land/cmd/gnoland/genesis_balances_remove_test.go +++ b/contribs/gnogenesis/internal/balances/balances_remove_test.go @@ -1,9 +1,10 @@ -package main +package balances import ( "context" "testing" + "github.com/gnolang/contribs/gnogenesis/internal/common" "github.com/gnolang/gno/gno.land/pkg/gnoland" "github.com/gnolang/gno/gno.land/pkg/gnoland/ugnot" "github.com/gnolang/gno/tm2/pkg/bft/types" @@ -19,10 +20,8 @@ func TestGenesis_Balances_Remove(t *testing.T) { t.Run("invalid genesis", func(t *testing.T) { // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewBalancesCmd(commands.NewTestIO()) args := []string{ - "genesis", - "balances", "remove", "--genesis-path", "dummy-path", @@ -30,26 +29,24 @@ func TestGenesis_Balances_Remove(t *testing.T) { // Run the command cmdErr := cmd.ParseAndRun(context.Background(), args) - require.ErrorContains(t, cmdErr, errUnableToLoadGenesis.Error()) + require.ErrorContains(t, cmdErr, common.ErrUnableToLoadGenesis.Error()) }) t.Run("genesis app state not set", func(t *testing.T) { t.Parallel() - dummyKey := getDummyKey(t) + dummyKey := common.GetDummyKey(t) tempGenesis, cleanup := testutils.NewTestFile(t) t.Cleanup(cleanup) - genesis := getDefaultGenesis() + genesis := common.GetDefaultGenesis() genesis.AppState = nil // not set require.NoError(t, genesis.SaveAs(tempGenesis.Name())) // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewBalancesCmd(commands.NewTestIO()) args := []string{ - "genesis", - "balances", "remove", "--genesis-path", tempGenesis.Name(), @@ -59,18 +56,18 @@ func TestGenesis_Balances_Remove(t *testing.T) { // Run the command cmdErr := cmd.ParseAndRun(context.Background(), args) - require.ErrorContains(t, cmdErr, errAppStateNotSet.Error()) + require.ErrorContains(t, cmdErr, common.ErrAppStateNotSet.Error()) }) t.Run("address is present", func(t *testing.T) { t.Parallel() - dummyKey := getDummyKey(t) + dummyKey := common.GetDummyKey(t) tempGenesis, cleanup := testutils.NewTestFile(t) t.Cleanup(cleanup) - genesis := getDefaultGenesis() + genesis := common.GetDefaultGenesis() state := gnoland.GnoGenesisState{ // Set an initial balance value Balances: []gnoland.Balance{ @@ -84,10 +81,8 @@ func TestGenesis_Balances_Remove(t *testing.T) { require.NoError(t, genesis.SaveAs(tempGenesis.Name())) // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewBalancesCmd(commands.NewTestIO()) args := []string{ - "genesis", - "balances", "remove", "--genesis-path", tempGenesis.Name(), @@ -114,12 +109,12 @@ func TestGenesis_Balances_Remove(t *testing.T) { t.Run("address not present", func(t *testing.T) { t.Parallel() - dummyKey := getDummyKey(t) + dummyKey := common.GetDummyKey(t) tempGenesis, cleanup := testutils.NewTestFile(t) t.Cleanup(cleanup) - genesis := getDefaultGenesis() + genesis := common.GetDefaultGenesis() state := gnoland.GnoGenesisState{ Balances: []gnoland.Balance{}, // Empty initial balance } @@ -127,10 +122,8 @@ func TestGenesis_Balances_Remove(t *testing.T) { require.NoError(t, genesis.SaveAs(tempGenesis.Name())) // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewBalancesCmd(commands.NewTestIO()) args := []string{ - "genesis", - "balances", "remove", "--genesis-path", tempGenesis.Name(), diff --git a/contribs/gnogenesis/internal/common/config.go b/contribs/gnogenesis/internal/common/config.go new file mode 100644 index 00000000000..99278b77764 --- /dev/null +++ b/contribs/gnogenesis/internal/common/config.go @@ -0,0 +1,35 @@ +package common + +import ( + "flag" + "time" + + "github.com/gnolang/gno/tm2/pkg/bft/types" +) + +const DefaultChainID = "dev" + +// Cfg is the common +// configuration for genesis commands +// that require a genesis.json +type Cfg struct { + GenesisPath string +} + +func (c *Cfg) RegisterFlags(fs *flag.FlagSet) { + fs.StringVar( + &c.GenesisPath, + "genesis-path", + "./genesis.json", + "the path to the genesis.json", + ) +} + +// GetDefaultGenesis returns the default genesis config +func GetDefaultGenesis() *types.GenesisDoc { + return &types.GenesisDoc{ + GenesisTime: time.Now(), + ChainID: DefaultChainID, + ConsensusParams: types.DefaultConsensusParams(), + } +} diff --git a/contribs/gnogenesis/internal/common/errors.go b/contribs/gnogenesis/internal/common/errors.go new file mode 100644 index 00000000000..6eff43e9dc7 --- /dev/null +++ b/contribs/gnogenesis/internal/common/errors.go @@ -0,0 +1,9 @@ +package common + +import "errors" + +var ( + ErrAppStateNotSet = errors.New("genesis app state not set") + ErrNoOutputFile = errors.New("no output file path specified") + ErrUnableToLoadGenesis = errors.New("unable to load genesis") +) diff --git a/contribs/gnogenesis/internal/common/helpers.go b/contribs/gnogenesis/internal/common/helpers.go new file mode 100644 index 00000000000..2b1f473aed1 --- /dev/null +++ b/contribs/gnogenesis/internal/common/helpers.go @@ -0,0 +1,52 @@ +package common + +import ( + "testing" + + "github.com/gnolang/gno/tm2/pkg/crypto" + "github.com/gnolang/gno/tm2/pkg/crypto/bip39" + "github.com/gnolang/gno/tm2/pkg/crypto/hd" + "github.com/gnolang/gno/tm2/pkg/crypto/keys/client" + "github.com/gnolang/gno/tm2/pkg/crypto/secp256k1" + "github.com/stretchr/testify/require" +) + +// GetDummyKey generates a random public key, +// and returns the key info +func GetDummyKey(t *testing.T) crypto.PubKey { + t.Helper() + + mnemonic, err := client.GenerateMnemonic(256) + require.NoError(t, err) + + seed := bip39.NewSeed(mnemonic, "") + + return generateKeyFromSeed(seed, 0).PubKey() +} + +// generateKeyFromSeed generates a private key from +// the provided seed and index +func generateKeyFromSeed(seed []byte, index uint32) crypto.PrivKey { + pathParams := hd.NewFundraiserParams(0, crypto.CoinType, index) + + masterPriv, ch := hd.ComputeMastersFromSeed(seed) + + //nolint:errcheck // This derivation can never error out, since the path params + // are always going to be valid + derivedPriv, _ := hd.DerivePrivateKeyForPath(masterPriv, ch, pathParams.String()) + + return secp256k1.PrivKeySecp256k1(derivedPriv) +} + +// GetDummyKeys generates random keys for testing +func GetDummyKeys(t *testing.T, count int) []crypto.PubKey { + t.Helper() + + dummyKeys := make([]crypto.PubKey, count) + + for i := 0; i < count; i++ { + dummyKeys[i] = GetDummyKey(t) + } + + return dummyKeys +} diff --git a/gno.land/cmd/gnoland/genesis_generate.go b/contribs/gnogenesis/internal/generate/generate.go similarity index 85% rename from gno.land/cmd/gnoland/genesis_generate.go rename to contribs/gnogenesis/internal/generate/generate.go index 751ac14ae62..729b904d548 100644 --- a/gno.land/cmd/gnoland/genesis_generate.go +++ b/contribs/gnogenesis/internal/generate/generate.go @@ -1,4 +1,4 @@ -package main +package generate import ( "context" @@ -6,12 +6,11 @@ import ( "fmt" "time" + "github.com/gnolang/contribs/gnogenesis/internal/common" "github.com/gnolang/gno/tm2/pkg/bft/types" "github.com/gnolang/gno/tm2/pkg/commands" ) -var defaultChainID = "dev" - type generateCfg struct { outputPath string chainID string @@ -22,14 +21,14 @@ type generateCfg struct { blockTimeIota int64 } -// newGenerateCmd creates the genesis generate subcommand -func newGenerateCmd(io commands.IO) *commands.Command { +// NewGenerateCmd creates the genesis generate subcommand +func NewGenerateCmd(io commands.IO) *commands.Command { cfg := &generateCfg{} return commands.NewCommand( commands.Metadata{ Name: "generate", - ShortUsage: "generate [flags]", + ShortUsage: "[flags]", ShortHelp: "generates a fresh genesis.json", LongHelp: "Generates a node's genesis.json based on specified parameters", }, @@ -58,7 +57,7 @@ func (c *generateCfg) RegisterFlags(fs *flag.FlagSet) { fs.StringVar( &c.chainID, "chain-id", - defaultChainID, + common.DefaultChainID, "the ID of the chain", ) @@ -93,7 +92,7 @@ func (c *generateCfg) RegisterFlags(fs *flag.FlagSet) { func execGenerate(cfg *generateCfg, io commands.IO) error { // Start with the default configuration - genesis := getDefaultGenesis() + genesis := common.GetDefaultGenesis() // Set the genesis time if cfg.genesisTime > 0 { @@ -142,12 +141,3 @@ func execGenerate(cfg *generateCfg, io commands.IO) error { return nil } - -// getDefaultGenesis returns the default genesis config -func getDefaultGenesis() *types.GenesisDoc { - return &types.GenesisDoc{ - GenesisTime: time.Now(), - ChainID: defaultChainID, - ConsensusParams: types.DefaultConsensusParams(), - } -} diff --git a/gno.land/cmd/gnoland/genesis_generate_test.go b/contribs/gnogenesis/internal/generate/generate_test.go similarity index 89% rename from gno.land/cmd/gnoland/genesis_generate_test.go rename to contribs/gnogenesis/internal/generate/generate_test.go index f078a161662..7ac02169d77 100644 --- a/gno.land/cmd/gnoland/genesis_generate_test.go +++ b/contribs/gnogenesis/internal/generate/generate_test.go @@ -1,4 +1,4 @@ -package main +package generate import ( "context" @@ -6,6 +6,7 @@ import ( "path/filepath" "testing" + "github.com/gnolang/contribs/gnogenesis/internal/common" "github.com/gnolang/gno/tm2/pkg/bft/types" "github.com/gnolang/gno/tm2/pkg/commands" "github.com/gnolang/gno/tm2/pkg/testutils" @@ -25,10 +26,8 @@ func TestGenesis_Generate(t *testing.T) { genesisPath := filepath.Join(tempDir, "genesis.json") // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewGenerateCmd(commands.NewTestIO()) args := []string{ - "genesis", - "generate", "--output-path", genesisPath, } @@ -42,7 +41,7 @@ func TestGenesis_Generate(t *testing.T) { require.NoError(t, readErr) // Make sure the default configuration is set - defaultGenesis := getDefaultGenesis() + defaultGenesis := common.GetDefaultGenesis() defaultGenesis.GenesisTime = genesis.GenesisTime assert.Equal(t, defaultGenesis, genesis) @@ -59,10 +58,8 @@ func TestGenesis_Generate(t *testing.T) { genesisPath := filepath.Join(tempDir, "genesis.json") // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewGenerateCmd(commands.NewTestIO()) args := []string{ - "genesis", - "generate", "--chain-id", chainID, "--output-path", @@ -91,10 +88,8 @@ func TestGenesis_Generate(t *testing.T) { genesisPath := filepath.Join(tempDir, "genesis.json") // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewGenerateCmd(commands.NewTestIO()) args := []string{ - "genesis", - "generate", "--block-max-tx-bytes", fmt.Sprintf("%d", blockMaxTxBytes), "--output-path", @@ -127,10 +122,8 @@ func TestGenesis_Generate(t *testing.T) { genesisPath := filepath.Join(tempDir, "genesis.json") // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewGenerateCmd(commands.NewTestIO()) args := []string{ - "genesis", - "generate", "--block-max-data-bytes", fmt.Sprintf("%d", blockMaxDataBytes), "--output-path", @@ -163,10 +156,8 @@ func TestGenesis_Generate(t *testing.T) { genesisPath := filepath.Join(tempDir, "genesis.json") // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewGenerateCmd(commands.NewTestIO()) args := []string{ - "genesis", - "generate", "--block-max-gas", fmt.Sprintf("%d", blockMaxGas), "--output-path", @@ -199,10 +190,8 @@ func TestGenesis_Generate(t *testing.T) { genesisPath := filepath.Join(tempDir, "genesis.json") // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewGenerateCmd(commands.NewTestIO()) args := []string{ - "genesis", - "generate", "--block-time-iota", fmt.Sprintf("%d", blockTimeIota), "--output-path", @@ -235,10 +224,8 @@ func TestGenesis_Generate(t *testing.T) { genesisPath := filepath.Join(tempDir, "genesis.json") // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewGenerateCmd(commands.NewTestIO()) args := []string{ - "genesis", - "generate", "--chain-id", invalidChainID, "--output-path", diff --git a/gno.land/cmd/gnoland/genesis_txs.go b/contribs/gnogenesis/internal/txs/txs.go similarity index 60% rename from gno.land/cmd/gnoland/genesis_txs.go rename to contribs/gnogenesis/internal/txs/txs.go index 46b8d1bd29c..fbf4c6ea3c7 100644 --- a/gno.land/cmd/gnoland/genesis_txs.go +++ b/contribs/gnogenesis/internal/txs/txs.go @@ -1,29 +1,29 @@ -package main +package txs import ( "errors" "flag" + "github.com/gnolang/contribs/gnogenesis/internal/common" "github.com/gnolang/gno/gno.land/pkg/gnoland" "github.com/gnolang/gno/tm2/pkg/bft/types" "github.com/gnolang/gno/tm2/pkg/commands" - "github.com/gnolang/gno/tm2/pkg/std" ) type txsCfg struct { - commonCfg + common.Cfg } var errInvalidGenesisStateType = errors.New("invalid genesis state type") -// newTxsCmd creates the genesis txs subcommand -func newTxsCmd(io commands.IO) *commands.Command { +// NewTxsCmd creates the genesis txs subcommand +func NewTxsCmd(io commands.IO) *commands.Command { cfg := &txsCfg{} cmd := commands.NewCommand( commands.Metadata{ Name: "txs", - ShortUsage: "txs [flags]", + ShortUsage: " [flags]", ShortHelp: "manages the initial genesis transactions", LongHelp: "Manages genesis transactions through input files", }, @@ -42,11 +42,11 @@ func newTxsCmd(io commands.IO) *commands.Command { } func (c *txsCfg) RegisterFlags(fs *flag.FlagSet) { - c.commonCfg.RegisterFlags(fs) + c.Cfg.RegisterFlags(fs) } // appendGenesisTxs saves the given transactions to the genesis doc -func appendGenesisTxs(genesis *types.GenesisDoc, txs []std.Tx) error { +func appendGenesisTxs(genesis *types.GenesisDoc, txs []gnoland.TxWithMetadata) error { // Initialize the app state if it's not present if genesis.AppState == nil { genesis.AppState = gnoland.GnoGenesisState{} @@ -74,3 +74,35 @@ func appendGenesisTxs(genesis *types.GenesisDoc, txs []std.Tx) error { return nil } + +// txStore is a wrapper for TM2 transactions +type txStore []gnoland.TxWithMetadata + +// leftMerge merges the two tx stores, with +// preference to the left +func (i *txStore) leftMerge(b txStore) error { + // Build out the tx hash map + txHashMap := make(map[string]struct{}, len(*i)) + + for _, tx := range *i { + txHash, err := getTxHash(tx.Tx) + if err != nil { + return err + } + + txHashMap[txHash] = struct{}{} + } + + for _, tx := range b { + txHash, err := getTxHash(tx.Tx) + if err != nil { + return err + } + + if _, exists := txHashMap[txHash]; !exists { + *i = append(*i, tx) + } + } + + return nil +} diff --git a/gno.land/cmd/gnoland/genesis_txs_add.go b/contribs/gnogenesis/internal/txs/txs_add.go similarity index 97% rename from gno.land/cmd/gnoland/genesis_txs_add.go rename to contribs/gnogenesis/internal/txs/txs_add.go index 7e7fd25b21e..22b3b1b966a 100644 --- a/gno.land/cmd/gnoland/genesis_txs_add.go +++ b/contribs/gnogenesis/internal/txs/txs_add.go @@ -1,4 +1,4 @@ -package main +package txs import ( "github.com/gnolang/gno/tm2/pkg/commands" diff --git a/gno.land/cmd/gnoland/genesis_txs_add_packages.go b/contribs/gnogenesis/internal/txs/txs_add_packages.go similarity index 90% rename from gno.land/cmd/gnoland/genesis_txs_add_packages.go rename to contribs/gnogenesis/internal/txs/txs_add_packages.go index 56d165c070b..1b4e6e7cffb 100644 --- a/gno.land/cmd/gnoland/genesis_txs_add_packages.go +++ b/contribs/gnogenesis/internal/txs/txs_add_packages.go @@ -1,4 +1,4 @@ -package main +package txs import ( "context" @@ -16,6 +16,7 @@ import ( var errInvalidPackageDir = errors.New("invalid package directory") var ( + // Keep in sync with gno.land/cmd/start.go genesisDeployAddress = crypto.MustAddressFromString("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") // test1 genesisDeployFee = std.NewFee(50000, std.MustParseCoin(ugnot.ValueString(1000000))) ) @@ -42,7 +43,7 @@ func execTxsAddPackages( args []string, ) error { // Load the genesis - genesis, loadErr := types.GenesisDocFromFile(cfg.genesisPath) + genesis, loadErr := types.GenesisDocFromFile(cfg.GenesisPath) if loadErr != nil { return fmt.Errorf("unable to load genesis, %w", loadErr) } @@ -52,7 +53,7 @@ func execTxsAddPackages( return errInvalidPackageDir } - parsedTxs := make([]std.Tx, 0) + parsedTxs := make([]gnoland.TxWithMetadata, 0) for _, path := range args { // Generate transactions from the packages (recursively) txs, err := gnoland.LoadPackagesFromDir(path, genesisDeployAddress, genesisDeployFee) @@ -69,7 +70,7 @@ func execTxsAddPackages( } // Save the updated genesis - if err := genesis.SaveAs(cfg.genesisPath); err != nil { + if err := genesis.SaveAs(cfg.GenesisPath); err != nil { return fmt.Errorf("unable to save genesis.json, %w", err) } diff --git a/gno.land/cmd/gnoland/genesis_txs_add_packages_test.go b/contribs/gnogenesis/internal/txs/txs_add_packages_test.go similarity index 84% rename from gno.land/cmd/gnoland/genesis_txs_add_packages_test.go rename to contribs/gnogenesis/internal/txs/txs_add_packages_test.go index 20c4f84c9ed..12a9287f171 100644 --- a/gno.land/cmd/gnoland/genesis_txs_add_packages_test.go +++ b/contribs/gnogenesis/internal/txs/txs_add_packages_test.go @@ -1,4 +1,4 @@ -package main +package txs import ( "context" @@ -7,6 +7,7 @@ import ( "path/filepath" "testing" + "github.com/gnolang/contribs/gnogenesis/internal/common" "github.com/gnolang/gno/gno.land/pkg/gnoland" vmm "github.com/gnolang/gno/gno.land/pkg/sdk/vm" "github.com/gnolang/gno/tm2/pkg/bft/types" @@ -23,10 +24,8 @@ func TestGenesis_Txs_Add_Packages(t *testing.T) { t.Parallel() // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewTxsCmd(commands.NewTestIO()) args := []string{ - "genesis", - "txs", "add", "packages", "--genesis-path", @@ -35,7 +34,7 @@ func TestGenesis_Txs_Add_Packages(t *testing.T) { // Run the command cmdErr := cmd.ParseAndRun(context.Background(), args) - assert.ErrorContains(t, cmdErr, errUnableToLoadGenesis.Error()) + assert.ErrorContains(t, cmdErr, common.ErrUnableToLoadGenesis.Error()) }) t.Run("invalid package dir", func(t *testing.T) { @@ -44,14 +43,12 @@ func TestGenesis_Txs_Add_Packages(t *testing.T) { tempGenesis, cleanup := testutils.NewTestFile(t) t.Cleanup(cleanup) - genesis := getDefaultGenesis() + genesis := common.GetDefaultGenesis() require.NoError(t, genesis.SaveAs(tempGenesis.Name())) // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewTxsCmd(commands.NewTestIO()) args := []string{ - "genesis", - "txs", "add", "packages", "--genesis-path", @@ -69,7 +66,7 @@ func TestGenesis_Txs_Add_Packages(t *testing.T) { tempGenesis, cleanup := testutils.NewTestFile(t) t.Cleanup(cleanup) - genesis := getDefaultGenesis() + genesis := common.GetDefaultGenesis() require.NoError(t, genesis.SaveAs(tempGenesis.Name())) // Prepare the package @@ -99,10 +96,8 @@ func TestGenesis_Txs_Add_Packages(t *testing.T) { ) // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewTxsCmd(commands.NewTestIO()) args := []string{ - "genesis", - "txs", "add", "packages", "--genesis-path", @@ -123,9 +118,9 @@ func TestGenesis_Txs_Add_Packages(t *testing.T) { state := updatedGenesis.AppState.(gnoland.GnoGenesisState) require.Equal(t, 1, len(state.Txs)) - require.Equal(t, 1, len(state.Txs[0].Msgs)) + require.Equal(t, 1, len(state.Txs[0].Tx.Msgs)) - msgAddPkg, ok := state.Txs[0].Msgs[0].(vmm.MsgAddPackage) + msgAddPkg, ok := state.Txs[0].Tx.Msgs[0].(vmm.MsgAddPackage) require.True(t, ok) assert.Equal(t, packagePath, msgAddPkg.Package.Path) diff --git a/gno.land/cmd/gnoland/genesis_txs_add_sheet.go b/contribs/gnogenesis/internal/txs/txs_add_sheet.go similarity index 71% rename from gno.land/cmd/gnoland/genesis_txs_add_sheet.go rename to contribs/gnogenesis/internal/txs/txs_add_sheet.go index 261a050029c..0bbd4b578cc 100644 --- a/gno.land/cmd/gnoland/genesis_txs_add_sheet.go +++ b/contribs/gnogenesis/internal/txs/txs_add_sheet.go @@ -1,20 +1,16 @@ -package main +package txs import ( "context" "errors" "fmt" - "os" + "github.com/gnolang/gno/gno.land/pkg/gnoland" "github.com/gnolang/gno/tm2/pkg/bft/types" "github.com/gnolang/gno/tm2/pkg/commands" - "github.com/gnolang/gno/tm2/pkg/std" ) -var ( - errInvalidTxsFile = errors.New("unable to open transactions file") - errNoTxsFileSpecified = errors.New("no txs file specified") -) +var errNoTxsFileSpecified = errors.New("no txs file specified") // newTxsAddSheetCmd creates the genesis txs add sheet subcommand func newTxsAddSheetCmd(txsCfg *txsCfg, io commands.IO) *commands.Command { @@ -39,7 +35,7 @@ func execTxsAddSheet( args []string, ) error { // Load the genesis - genesis, loadErr := types.GenesisDocFromFile(cfg.genesisPath) + genesis, loadErr := types.GenesisDocFromFile(cfg.GenesisPath) if loadErr != nil { return fmt.Errorf("unable to load genesis, %w", loadErr) } @@ -49,22 +45,13 @@ func execTxsAddSheet( return errNoTxsFileSpecified } - parsedTxs := make([]std.Tx, 0) + parsedTxs := make([]gnoland.TxWithMetadata, 0) for _, file := range args { - file, loadErr := os.Open(file) - if loadErr != nil { - return fmt.Errorf("%w, %w", errInvalidTxsFile, loadErr) - } - - txs, err := std.ParseTxs(ctx, file) + txs, err := gnoland.ReadGenesisTxs(ctx, file) if err != nil { return fmt.Errorf("unable to parse file, %w", err) } - if err = file.Close(); err != nil { - return fmt.Errorf("unable to gracefully close file, %w", err) - } - parsedTxs = append(parsedTxs, txs...) } @@ -74,7 +61,7 @@ func execTxsAddSheet( } // Save the updated genesis - if err := genesis.SaveAs(cfg.genesisPath); err != nil { + if err := genesis.SaveAs(cfg.GenesisPath); err != nil { return fmt.Errorf("unable to save genesis.json, %w", err) } diff --git a/gno.land/cmd/gnoland/genesis_txs_add_sheet_test.go b/contribs/gnogenesis/internal/txs/txs_add_sheet_test.go similarity index 79% rename from gno.land/cmd/gnoland/genesis_txs_add_sheet_test.go rename to contribs/gnogenesis/internal/txs/txs_add_sheet_test.go index a70446cfe6c..6da3faea6ed 100644 --- a/gno.land/cmd/gnoland/genesis_txs_add_sheet_test.go +++ b/contribs/gnogenesis/internal/txs/txs_add_sheet_test.go @@ -1,4 +1,4 @@ -package main +package txs import ( "context" @@ -6,6 +6,7 @@ import ( "strings" "testing" + "github.com/gnolang/contribs/gnogenesis/internal/common" "github.com/gnolang/gno/gno.land/pkg/gnoland" "github.com/gnolang/gno/gno.land/pkg/gnoland/ugnot" "github.com/gnolang/gno/tm2/pkg/amino" @@ -20,25 +21,27 @@ import ( ) // generateDummyTxs generates dummy transactions -func generateDummyTxs(t *testing.T, count int) []std.Tx { +func generateDummyTxs(t *testing.T, count int) []gnoland.TxWithMetadata { t.Helper() - txs := make([]std.Tx, count) + txs := make([]gnoland.TxWithMetadata, count) for i := 0; i < count; i++ { - txs[i] = std.Tx{ - Msgs: []std.Msg{ - bank.MsgSend{ - FromAddress: crypto.Address{byte(i)}, - ToAddress: crypto.Address{byte((i + 1) % count)}, - Amount: std.NewCoins(std.NewCoin(ugnot.Denom, 1)), + txs[i] = gnoland.TxWithMetadata{ + Tx: std.Tx{ + Msgs: []std.Msg{ + bank.MsgSend{ + FromAddress: crypto.Address{byte(i)}, + ToAddress: crypto.Address{byte((i + 1) % count)}, + Amount: std.NewCoins(std.NewCoin(ugnot.Denom, 1)), + }, }, + Fee: std.Fee{ + GasWanted: 1, + GasFee: std.NewCoin(ugnot.Denom, 1000000), + }, + Memo: fmt.Sprintf("tx %d", i), }, - Fee: std.Fee{ - GasWanted: 1, - GasFee: std.NewCoin(ugnot.Denom, 1000000), - }, - Memo: fmt.Sprintf("tx %d", i), } } @@ -46,7 +49,7 @@ func generateDummyTxs(t *testing.T, count int) []std.Tx { } // encodeDummyTxs encodes the transactions into amino JSON -func encodeDummyTxs(t *testing.T, txs []std.Tx) []string { +func encodeDummyTxs(t *testing.T, txs []gnoland.TxWithMetadata) []string { t.Helper() encodedTxs := make([]string, 0, len(txs)) @@ -70,10 +73,8 @@ func TestGenesis_Txs_Add_Sheets(t *testing.T) { t.Parallel() // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewTxsCmd(commands.NewTestIO()) args := []string{ - "genesis", - "txs", "add", "sheets", "--genesis-path", @@ -82,7 +83,7 @@ func TestGenesis_Txs_Add_Sheets(t *testing.T) { // Run the command cmdErr := cmd.ParseAndRun(context.Background(), args) - assert.ErrorContains(t, cmdErr, errUnableToLoadGenesis.Error()) + assert.ErrorContains(t, cmdErr, common.ErrUnableToLoadGenesis.Error()) }) t.Run("invalid txs file", func(t *testing.T) { @@ -91,14 +92,12 @@ func TestGenesis_Txs_Add_Sheets(t *testing.T) { tempGenesis, cleanup := testutils.NewTestFile(t) t.Cleanup(cleanup) - genesis := getDefaultGenesis() + genesis := common.GetDefaultGenesis() require.NoError(t, genesis.SaveAs(tempGenesis.Name())) // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewTxsCmd(commands.NewTestIO()) args := []string{ - "genesis", - "txs", "add", "sheets", "--genesis-path", @@ -107,8 +106,7 @@ func TestGenesis_Txs_Add_Sheets(t *testing.T) { } // Run the command - cmdErr := cmd.ParseAndRun(context.Background(), args) - assert.ErrorContains(t, cmdErr, errInvalidTxsFile.Error()) + assert.Error(t, cmd.ParseAndRun(context.Background(), args)) }) t.Run("no txs file", func(t *testing.T) { @@ -117,14 +115,12 @@ func TestGenesis_Txs_Add_Sheets(t *testing.T) { tempGenesis, cleanup := testutils.NewTestFile(t) t.Cleanup(cleanup) - genesis := getDefaultGenesis() + genesis := common.GetDefaultGenesis() require.NoError(t, genesis.SaveAs(tempGenesis.Name())) // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewTxsCmd(commands.NewTestIO()) args := []string{ - "genesis", - "txs", "add", "sheets", "--genesis-path", @@ -142,14 +138,12 @@ func TestGenesis_Txs_Add_Sheets(t *testing.T) { tempGenesis, cleanup := testutils.NewTestFile(t) t.Cleanup(cleanup) - genesis := getDefaultGenesis() + genesis := common.GetDefaultGenesis() require.NoError(t, genesis.SaveAs(tempGenesis.Name())) // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewTxsCmd(commands.NewTestIO()) args := []string{ - "genesis", - "txs", "add", "sheets", "--genesis-path", @@ -171,7 +165,7 @@ func TestGenesis_Txs_Add_Sheets(t *testing.T) { tempGenesis, cleanup := testutils.NewTestFile(t) t.Cleanup(cleanup) - genesis := getDefaultGenesis() + genesis := common.GetDefaultGenesis() require.NoError(t, genesis.SaveAs(tempGenesis.Name())) // Prepare the transactions file @@ -187,10 +181,8 @@ func TestGenesis_Txs_Add_Sheets(t *testing.T) { require.NoError(t, err) // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewTxsCmd(commands.NewTestIO()) args := []string{ - "genesis", - "txs", "add", "sheets", "--genesis-path", @@ -226,7 +218,7 @@ func TestGenesis_Txs_Add_Sheets(t *testing.T) { tempGenesis, cleanup := testutils.NewTestFile(t) t.Cleanup(cleanup) - genesis := getDefaultGenesis() + genesis := common.GetDefaultGenesis() genesisState := gnoland.GnoGenesisState{ Txs: txs[0 : len(txs)/2], } @@ -247,10 +239,8 @@ func TestGenesis_Txs_Add_Sheets(t *testing.T) { require.NoError(t, err) // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewTxsCmd(commands.NewTestIO()) args := []string{ - "genesis", - "txs", "add", "sheets", "--genesis-path", diff --git a/gno.land/cmd/gnoland/genesis_txs_export.go b/contribs/gnogenesis/internal/txs/txs_export.go similarity index 92% rename from gno.land/cmd/gnoland/genesis_txs_export.go rename to contribs/gnogenesis/internal/txs/txs_export.go index bf54236b31f..0409f1fd0ac 100644 --- a/gno.land/cmd/gnoland/genesis_txs_export.go +++ b/contribs/gnogenesis/internal/txs/txs_export.go @@ -1,19 +1,17 @@ -package main +package txs import ( "context" - "errors" "fmt" "os" + "github.com/gnolang/contribs/gnogenesis/internal/common" "github.com/gnolang/gno/gno.land/pkg/gnoland" "github.com/gnolang/gno/tm2/pkg/amino" "github.com/gnolang/gno/tm2/pkg/bft/types" "github.com/gnolang/gno/tm2/pkg/commands" ) -var errNoOutputFile = errors.New("no output file path specified") - // newTxsExportCmd creates the genesis txs export subcommand func newTxsExportCmd(txsCfg *txsCfg, io commands.IO) *commands.Command { return commands.NewCommand( @@ -32,7 +30,7 @@ func newTxsExportCmd(txsCfg *txsCfg, io commands.IO) *commands.Command { func execTxsExport(cfg *txsCfg, io commands.IO, args []string) error { // Load the genesis - genesis, loadErr := types.GenesisDocFromFile(cfg.genesisPath) + genesis, loadErr := types.GenesisDocFromFile(cfg.GenesisPath) if loadErr != nil { return fmt.Errorf("unable to load genesis, %w", loadErr) } @@ -51,7 +49,7 @@ func execTxsExport(cfg *txsCfg, io commands.IO, args []string) error { // Make sure the output file path is specified if len(args) == 0 { - return errNoOutputFile + return common.ErrNoOutputFile } // Open output file diff --git a/gno.land/cmd/gnoland/genesis_txs_export_test.go b/contribs/gnogenesis/internal/txs/txs_export_test.go similarity index 81% rename from gno.land/cmd/gnoland/genesis_txs_export_test.go rename to contribs/gnogenesis/internal/txs/txs_export_test.go index 9927f671efb..ad738cd95f7 100644 --- a/gno.land/cmd/gnoland/genesis_txs_export_test.go +++ b/contribs/gnogenesis/internal/txs/txs_export_test.go @@ -1,14 +1,14 @@ -package main +package txs import ( "bufio" "context" "testing" + "github.com/gnolang/contribs/gnogenesis/internal/common" "github.com/gnolang/gno/gno.land/pkg/gnoland" "github.com/gnolang/gno/tm2/pkg/amino" "github.com/gnolang/gno/tm2/pkg/commands" - "github.com/gnolang/gno/tm2/pkg/std" "github.com/gnolang/gno/tm2/pkg/testutils" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -21,10 +21,8 @@ func TestGenesis_Txs_Export(t *testing.T) { t.Parallel() // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewTxsCmd(commands.NewTestIO()) args := []string{ - "genesis", - "txs", "export", "--genesis-path", "dummy-path", @@ -32,7 +30,7 @@ func TestGenesis_Txs_Export(t *testing.T) { // Run the command cmdErr := cmd.ParseAndRun(context.Background(), args) - assert.ErrorContains(t, cmdErr, errUnableToLoadGenesis.Error()) + assert.ErrorContains(t, cmdErr, common.ErrUnableToLoadGenesis.Error()) }) t.Run("invalid genesis app state", func(t *testing.T) { @@ -41,15 +39,13 @@ func TestGenesis_Txs_Export(t *testing.T) { tempGenesis, cleanup := testutils.NewTestFile(t) t.Cleanup(cleanup) - genesis := getDefaultGenesis() + genesis := common.GetDefaultGenesis() genesis.AppState = nil // no app state require.NoError(t, genesis.SaveAs(tempGenesis.Name())) // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewTxsCmd(commands.NewTestIO()) args := []string{ - "genesis", - "txs", "export", "--genesis-path", tempGenesis.Name(), @@ -66,17 +62,15 @@ func TestGenesis_Txs_Export(t *testing.T) { tempGenesis, cleanup := testutils.NewTestFile(t) t.Cleanup(cleanup) - genesis := getDefaultGenesis() + genesis := common.GetDefaultGenesis() genesis.AppState = gnoland.GnoGenesisState{ Txs: generateDummyTxs(t, 1), } require.NoError(t, genesis.SaveAs(tempGenesis.Name())) // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewTxsCmd(commands.NewTestIO()) args := []string{ - "genesis", - "txs", "export", "--genesis-path", tempGenesis.Name(), @@ -84,7 +78,7 @@ func TestGenesis_Txs_Export(t *testing.T) { // Run the command cmdErr := cmd.ParseAndRun(context.Background(), args) - assert.ErrorContains(t, cmdErr, errNoOutputFile.Error()) + assert.ErrorContains(t, cmdErr, common.ErrNoOutputFile.Error()) }) t.Run("valid txs export", func(t *testing.T) { @@ -96,7 +90,7 @@ func TestGenesis_Txs_Export(t *testing.T) { tempGenesis, cleanup := testutils.NewTestFile(t) t.Cleanup(cleanup) - genesis := getDefaultGenesis() + genesis := common.GetDefaultGenesis() genesis.AppState = gnoland.GnoGenesisState{ Txs: txs, } @@ -107,10 +101,8 @@ func TestGenesis_Txs_Export(t *testing.T) { t.Cleanup(outputCleanup) // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewTxsCmd(commands.NewTestIO()) args := []string{ - "genesis", - "txs", "export", "--genesis-path", tempGenesis.Name(), @@ -124,9 +116,9 @@ func TestGenesis_Txs_Export(t *testing.T) { // Validate the transactions were written down scanner := bufio.NewScanner(outputFile) - outputTxs := make([]std.Tx, 0) + outputTxs := make([]gnoland.TxWithMetadata, 0) for scanner.Scan() { - var tx std.Tx + var tx gnoland.TxWithMetadata require.NoError(t, amino.UnmarshalJSON(scanner.Bytes(), &tx)) diff --git a/gno.land/cmd/gnoland/genesis_txs_list.go b/contribs/gnogenesis/internal/txs/txs_list.go similarity index 86% rename from gno.land/cmd/gnoland/genesis_txs_list.go rename to contribs/gnogenesis/internal/txs/txs_list.go index c68fbc30803..c7867da5027 100644 --- a/gno.land/cmd/gnoland/genesis_txs_list.go +++ b/contribs/gnogenesis/internal/txs/txs_list.go @@ -1,4 +1,4 @@ -package main +package txs import ( "bytes" @@ -6,6 +6,7 @@ import ( "errors" "fmt" + "github.com/gnolang/contribs/gnogenesis/internal/common" "github.com/gnolang/gno/gno.land/pkg/gnoland" "github.com/gnolang/gno/tm2/pkg/amino" "github.com/gnolang/gno/tm2/pkg/bft/types" @@ -33,9 +34,9 @@ func newTxsListCmd(txsCfg *txsCfg, io commands.IO) *commands.Command { } func execTxsListCmd(io commands.IO, cfg *txsCfg) error { - genesis, err := types.GenesisDocFromFile(cfg.genesisPath) + genesis, err := types.GenesisDocFromFile(cfg.GenesisPath) if err != nil { - return fmt.Errorf("%w, %w", errUnableToLoadGenesis, err) + return fmt.Errorf("%w, %w", common.ErrUnableToLoadGenesis, err) } gs, ok := genesis.AppState.(gnoland.GnoGenesisState) diff --git a/gno.land/cmd/gnoland/genesis_txs_list_test.go b/contribs/gnogenesis/internal/txs/txs_list_test.go similarity index 81% rename from gno.land/cmd/gnoland/genesis_txs_list_test.go rename to contribs/gnogenesis/internal/txs/txs_list_test.go index d18c2f4d641..d4d9f4d7ba8 100644 --- a/gno.land/cmd/gnoland/genesis_txs_list_test.go +++ b/contribs/gnogenesis/internal/txs/txs_list_test.go @@ -1,10 +1,11 @@ -package main +package txs import ( "bytes" "context" "testing" + "github.com/gnolang/contribs/gnogenesis/internal/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -20,10 +21,8 @@ func TestGenesis_List_All(t *testing.T) { t.Parallel() // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewTxsCmd(commands.NewTestIO()) args := []string{ - "genesis", - "txs", "list", "--genesis-path", "", @@ -31,7 +30,7 @@ func TestGenesis_List_All(t *testing.T) { // Run the command cmdErr := cmd.ParseAndRun(context.Background(), args) - assert.ErrorIs(t, cmdErr, errUnableToLoadGenesis) + assert.ErrorIs(t, cmdErr, common.ErrUnableToLoadGenesis) }) t.Run("list all txs", func(t *testing.T) { @@ -43,7 +42,7 @@ func TestGenesis_List_All(t *testing.T) { // Generate dummy txs txs := generateDummyTxs(t, 10) - genesis := getDefaultGenesis() + genesis := common.GetDefaultGenesis() genesis.AppState = gnoland.GnoGenesisState{ Txs: txs, } @@ -53,10 +52,8 @@ func TestGenesis_List_All(t *testing.T) { buf := bytes.NewBuffer(nil) cio.SetOut(commands.WriteNopCloser(buf)) - cmd := newRootCmd(cio) + cmd := NewTxsCmd(cio) args := []string{ - "genesis", - "txs", "list", "--genesis-path", tempGenesis.Name(), @@ -66,6 +63,6 @@ func TestGenesis_List_All(t *testing.T) { cmdErr := cmd.ParseAndRun(context.Background(), args) require.NoError(t, cmdErr) - require.Len(t, buf.String(), 4442) + require.Len(t, buf.String(), 5262) }) } diff --git a/gno.land/cmd/gnoland/genesis_txs_remove.go b/contribs/gnogenesis/internal/txs/txs_remove.go similarity index 93% rename from gno.land/cmd/gnoland/genesis_txs_remove.go rename to contribs/gnogenesis/internal/txs/txs_remove.go index 49c650f4670..dbfc90fb1dc 100644 --- a/gno.land/cmd/gnoland/genesis_txs_remove.go +++ b/contribs/gnogenesis/internal/txs/txs_remove.go @@ -1,4 +1,4 @@ -package main +package txs import ( "context" @@ -37,7 +37,7 @@ func newTxsRemoveCmd(txsCfg *txsCfg, io commands.IO) *commands.Command { func execTxsRemove(cfg *txsCfg, io commands.IO, args []string) error { // Load the genesis - genesis, loadErr := types.GenesisDocFromFile(cfg.genesisPath) + genesis, loadErr := types.GenesisDocFromFile(cfg.GenesisPath) if loadErr != nil { return fmt.Errorf("unable to load genesis, %w", loadErr) } @@ -59,7 +59,7 @@ func execTxsRemove(cfg *txsCfg, io commands.IO, args []string) error { for indx, tx := range state.Txs { // Find the hash of the transaction - hash, err := getTxHash(tx) + hash, err := getTxHash(tx.Tx) if err != nil { return fmt.Errorf("unable to generate tx hash, %w", err) } @@ -87,7 +87,7 @@ func execTxsRemove(cfg *txsCfg, io commands.IO, args []string) error { genesis.AppState = state // Save the updated genesis - if err := genesis.SaveAs(cfg.genesisPath); err != nil { + if err := genesis.SaveAs(cfg.GenesisPath); err != nil { return fmt.Errorf("unable to save genesis.json, %w", err) } diff --git a/gno.land/cmd/gnoland/genesis_txs_remove_test.go b/contribs/gnogenesis/internal/txs/txs_remove_test.go similarity index 83% rename from gno.land/cmd/gnoland/genesis_txs_remove_test.go rename to contribs/gnogenesis/internal/txs/txs_remove_test.go index ff5af479449..16edbb83e3c 100644 --- a/gno.land/cmd/gnoland/genesis_txs_remove_test.go +++ b/contribs/gnogenesis/internal/txs/txs_remove_test.go @@ -1,9 +1,10 @@ -package main +package txs import ( "context" "testing" + "github.com/gnolang/contribs/gnogenesis/internal/common" "github.com/gnolang/gno/gno.land/pkg/gnoland" "github.com/gnolang/gno/tm2/pkg/bft/types" "github.com/gnolang/gno/tm2/pkg/commands" @@ -19,10 +20,8 @@ func TestGenesis_Txs_Remove(t *testing.T) { t.Parallel() // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewTxsCmd(commands.NewTestIO()) args := []string{ - "genesis", - "txs", "remove", "--genesis-path", "dummy-path", @@ -30,7 +29,7 @@ func TestGenesis_Txs_Remove(t *testing.T) { // Run the command cmdErr := cmd.ParseAndRun(context.Background(), args) - assert.ErrorContains(t, cmdErr, errUnableToLoadGenesis.Error()) + assert.ErrorContains(t, cmdErr, common.ErrUnableToLoadGenesis.Error()) }) t.Run("invalid genesis app state", func(t *testing.T) { @@ -39,15 +38,13 @@ func TestGenesis_Txs_Remove(t *testing.T) { tempGenesis, cleanup := testutils.NewTestFile(t) t.Cleanup(cleanup) - genesis := getDefaultGenesis() + genesis := common.GetDefaultGenesis() genesis.AppState = nil // no app state require.NoError(t, genesis.SaveAs(tempGenesis.Name())) // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewTxsCmd(commands.NewTestIO()) args := []string{ - "genesis", - "txs", "remove", "--genesis-path", tempGenesis.Name(), @@ -66,17 +63,15 @@ func TestGenesis_Txs_Remove(t *testing.T) { // Generate dummy txs txs := generateDummyTxs(t, 10) - genesis := getDefaultGenesis() + genesis := common.GetDefaultGenesis() genesis.AppState = gnoland.GnoGenesisState{ Txs: txs, } require.NoError(t, genesis.SaveAs(tempGenesis.Name())) // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewTxsCmd(commands.NewTestIO()) args := []string{ - "genesis", - "txs", "remove", "--genesis-path", tempGenesis.Name(), @@ -96,20 +91,18 @@ func TestGenesis_Txs_Remove(t *testing.T) { // Generate dummy txs txs := generateDummyTxs(t, 10) - genesis := getDefaultGenesis() + genesis := common.GetDefaultGenesis() genesis.AppState = gnoland.GnoGenesisState{ Txs: txs, } require.NoError(t, genesis.SaveAs(tempGenesis.Name())) - txHash, err := getTxHash(txs[0]) + txHash, err := getTxHash(txs[0].Tx) require.NoError(t, err) // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewTxsCmd(commands.NewTestIO()) args := []string{ - "genesis", - "txs", "remove", "--genesis-path", tempGenesis.Name(), @@ -131,7 +124,7 @@ func TestGenesis_Txs_Remove(t *testing.T) { assert.Len(t, state.Txs, len(txs)-1) for _, tx := range state.Txs { - genesisTxHash, err := getTxHash(tx) + genesisTxHash, err := getTxHash(tx.Tx) require.NoError(t, err) assert.NotEqual(t, txHash, genesisTxHash) diff --git a/gno.land/cmd/gnoland/genesis_validator.go b/contribs/gnogenesis/internal/validator/validator.go similarity index 68% rename from gno.land/cmd/gnoland/genesis_validator.go rename to contribs/gnogenesis/internal/validator/validator.go index 91d3e4af7dd..8cd84f5c9bf 100644 --- a/gno.land/cmd/gnoland/genesis_validator.go +++ b/contribs/gnogenesis/internal/validator/validator.go @@ -1,27 +1,28 @@ -package main +package validator import ( "flag" + "github.com/gnolang/contribs/gnogenesis/internal/common" "github.com/gnolang/gno/tm2/pkg/commands" ) type validatorCfg struct { - commonCfg + common.Cfg address string } -// newValidatorCmd creates the genesis validator subcommand -func newValidatorCmd(io commands.IO) *commands.Command { +// NewValidatorCmd creates the genesis validator subcommand +func NewValidatorCmd(io commands.IO) *commands.Command { cfg := &validatorCfg{ - commonCfg: commonCfg{}, + Cfg: common.Cfg{}, } cmd := commands.NewCommand( commands.Metadata{ Name: "validator", - ShortUsage: "validator [flags]", + ShortUsage: " [flags]", ShortHelp: "validator set management in genesis.json", LongHelp: "Manipulates the genesis.json validator set", }, @@ -38,7 +39,7 @@ func newValidatorCmd(io commands.IO) *commands.Command { } func (c *validatorCfg) RegisterFlags(fs *flag.FlagSet) { - c.commonCfg.RegisterFlags(fs) + c.Cfg.RegisterFlags(fs) fs.StringVar( &c.address, diff --git a/gno.land/cmd/gnoland/genesis_validator_add.go b/contribs/gnogenesis/internal/validator/validator_add.go similarity index 95% rename from gno.land/cmd/gnoland/genesis_validator_add.go rename to contribs/gnogenesis/internal/validator/validator_add.go index 6c44ad93f89..45744f98e82 100644 --- a/gno.land/cmd/gnoland/genesis_validator_add.go +++ b/contribs/gnogenesis/internal/validator/validator_add.go @@ -1,4 +1,4 @@ -package main +package validator import ( "context" @@ -71,7 +71,7 @@ func (c *validatorAddCfg) RegisterFlags(fs *flag.FlagSet) { func execValidatorAdd(cfg *validatorAddCfg, io commands.IO) error { // Load the genesis - genesis, loadErr := types.GenesisDocFromFile(cfg.rootCfg.genesisPath) + genesis, loadErr := types.GenesisDocFromFile(cfg.rootCfg.GenesisPath) if loadErr != nil { return fmt.Errorf("unable to load genesis, %w", loadErr) } @@ -124,7 +124,7 @@ func execValidatorAdd(cfg *validatorAddCfg, io commands.IO) error { genesis.Validators = append(genesis.Validators, validator) // Save the updated genesis - if err := genesis.SaveAs(cfg.rootCfg.genesisPath); err != nil { + if err := genesis.SaveAs(cfg.rootCfg.GenesisPath); err != nil { return fmt.Errorf("unable to save genesis.json, %w", err) } diff --git a/gno.land/cmd/gnoland/genesis_validator_add_test.go b/contribs/gnogenesis/internal/validator/validator_add_test.go similarity index 66% rename from gno.land/cmd/gnoland/genesis_validator_add_test.go rename to contribs/gnogenesis/internal/validator/validator_add_test.go index 528255b3029..4e6155137a3 100644 --- a/gno.land/cmd/gnoland/genesis_validator_add_test.go +++ b/contribs/gnogenesis/internal/validator/validator_add_test.go @@ -1,61 +1,18 @@ -package main +package validator import ( "context" "testing" + "github.com/gnolang/contribs/gnogenesis/internal/common" "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/crypto/bip39" - "github.com/gnolang/gno/tm2/pkg/crypto/hd" - "github.com/gnolang/gno/tm2/pkg/crypto/keys/client" - "github.com/gnolang/gno/tm2/pkg/crypto/secp256k1" "github.com/gnolang/gno/tm2/pkg/testutils" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) -// getDummyKey generates a random public key, -// and returns the key info -func getDummyKey(t *testing.T) crypto.PubKey { - t.Helper() - - mnemonic, err := client.GenerateMnemonic(256) - require.NoError(t, err) - - seed := bip39.NewSeed(mnemonic, "") - - return generateKeyFromSeed(seed, 0).PubKey() -} - -// generateKeyFromSeed generates a private key from -// the provided seed and index -func generateKeyFromSeed(seed []byte, index uint32) crypto.PrivKey { - pathParams := hd.NewFundraiserParams(0, crypto.CoinType, index) - - masterPriv, ch := hd.ComputeMastersFromSeed(seed) - - //nolint:errcheck // This derivation can never error out, since the path params - // are always going to be valid - derivedPriv, _ := hd.DerivePrivateKeyForPath(masterPriv, ch, pathParams.String()) - - return secp256k1.PrivKeySecp256k1(derivedPriv) -} - -// getDummyKeys generates random keys for testing -func getDummyKeys(t *testing.T, count int) []crypto.PubKey { - t.Helper() - - dummyKeys := make([]crypto.PubKey, count) - - for i := 0; i < count; i++ { - dummyKeys[i] = getDummyKey(t) - } - - return dummyKeys -} - func TestGenesis_Validator_Add(t *testing.T) { t.Parallel() @@ -63,10 +20,8 @@ func TestGenesis_Validator_Add(t *testing.T) { t.Parallel() // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewValidatorCmd(commands.NewTestIO()) args := []string{ - "genesis", - "validator", "add", "--genesis-path", "dummy-path", @@ -74,7 +29,7 @@ func TestGenesis_Validator_Add(t *testing.T) { // Run the command cmdErr := cmd.ParseAndRun(context.Background(), args) - assert.ErrorContains(t, cmdErr, errUnableToLoadGenesis.Error()) + assert.ErrorContains(t, cmdErr, common.ErrUnableToLoadGenesis.Error()) }) t.Run("invalid validator address", func(t *testing.T) { @@ -83,14 +38,12 @@ func TestGenesis_Validator_Add(t *testing.T) { tempGenesis, cleanup := testutils.NewTestFile(t) t.Cleanup(cleanup) - genesis := getDefaultGenesis() + genesis := common.GetDefaultGenesis() require.NoError(t, genesis.SaveAs(tempGenesis.Name())) // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewValidatorCmd(commands.NewTestIO()) args := []string{ - "genesis", - "validator", "add", "--genesis-path", tempGenesis.Name(), @@ -109,16 +62,14 @@ func TestGenesis_Validator_Add(t *testing.T) { tempGenesis, cleanup := testutils.NewTestFile(t) t.Cleanup(cleanup) - genesis := getDefaultGenesis() + genesis := common.GetDefaultGenesis() require.NoError(t, genesis.SaveAs(tempGenesis.Name())) - key := getDummyKey(t) + key := common.GetDummyKey(t) // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewValidatorCmd(commands.NewTestIO()) args := []string{ - "genesis", - "validator", "add", "--genesis-path", tempGenesis.Name(), @@ -139,16 +90,14 @@ func TestGenesis_Validator_Add(t *testing.T) { tempGenesis, cleanup := testutils.NewTestFile(t) t.Cleanup(cleanup) - genesis := getDefaultGenesis() + genesis := common.GetDefaultGenesis() require.NoError(t, genesis.SaveAs(tempGenesis.Name())) - key := getDummyKey(t) + key := common.GetDummyKey(t) // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewValidatorCmd(commands.NewTestIO()) args := []string{ - "genesis", - "validator", "add", "--genesis-path", tempGenesis.Name(), @@ -169,16 +118,14 @@ func TestGenesis_Validator_Add(t *testing.T) { tempGenesis, cleanup := testutils.NewTestFile(t) t.Cleanup(cleanup) - genesis := getDefaultGenesis() + genesis := common.GetDefaultGenesis() require.NoError(t, genesis.SaveAs(tempGenesis.Name())) - key := getDummyKey(t) + key := common.GetDummyKey(t) // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewValidatorCmd(commands.NewTestIO()) args := []string{ - "genesis", - "validator", "add", "--genesis-path", tempGenesis.Name(), @@ -201,16 +148,14 @@ func TestGenesis_Validator_Add(t *testing.T) { tempGenesis, cleanup := testutils.NewTestFile(t) t.Cleanup(cleanup) - genesis := getDefaultGenesis() + genesis := common.GetDefaultGenesis() require.NoError(t, genesis.SaveAs(tempGenesis.Name())) - dummyKeys := getDummyKeys(t, 2) + dummyKeys := common.GetDummyKeys(t, 2) // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewValidatorCmd(commands.NewTestIO()) args := []string{ - "genesis", - "validator", "add", "--genesis-path", tempGenesis.Name(), @@ -233,8 +178,8 @@ func TestGenesis_Validator_Add(t *testing.T) { tempGenesis, cleanup := testutils.NewTestFile(t) t.Cleanup(cleanup) - dummyKeys := getDummyKeys(t, 2) - genesis := getDefaultGenesis() + dummyKeys := common.GetDummyKeys(t, 2) + genesis := common.GetDefaultGenesis() // Set an existing validator genesis.Validators = append(genesis.Validators, types.GenesisValidator{ @@ -247,10 +192,8 @@ func TestGenesis_Validator_Add(t *testing.T) { require.NoError(t, genesis.SaveAs(tempGenesis.Name())) // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewValidatorCmd(commands.NewTestIO()) args := []string{ - "genesis", - "validator", "add", "--genesis-path", tempGenesis.Name(), @@ -273,16 +216,14 @@ func TestGenesis_Validator_Add(t *testing.T) { tempGenesis, cleanup := testutils.NewTestFile(t) t.Cleanup(cleanup) - key := getDummyKey(t) - genesis := getDefaultGenesis() + key := common.GetDummyKey(t) + genesis := common.GetDefaultGenesis() require.NoError(t, genesis.SaveAs(tempGenesis.Name())) // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewValidatorCmd(commands.NewTestIO()) args := []string{ - "genesis", - "validator", "add", "--genesis-path", tempGenesis.Name(), diff --git a/gno.land/cmd/gnoland/genesis_validator_remove.go b/contribs/gnogenesis/internal/validator/validator_remove.go similarity index 92% rename from gno.land/cmd/gnoland/genesis_validator_remove.go rename to contribs/gnogenesis/internal/validator/validator_remove.go index 48a15a9abaf..0206fe7d58d 100644 --- a/gno.land/cmd/gnoland/genesis_validator_remove.go +++ b/contribs/gnogenesis/internal/validator/validator_remove.go @@ -1,4 +1,4 @@ -package main +package validator import ( "context" @@ -29,7 +29,7 @@ func newValidatorRemoveCmd(rootCfg *validatorCfg, io commands.IO) *commands.Comm func execValidatorRemove(cfg *validatorCfg, io commands.IO) error { // Load the genesis - genesis, loadErr := types.GenesisDocFromFile(cfg.genesisPath) + genesis, loadErr := types.GenesisDocFromFile(cfg.GenesisPath) if loadErr != nil { return fmt.Errorf("unable to load genesis, %w", loadErr) } @@ -58,7 +58,7 @@ func execValidatorRemove(cfg *validatorCfg, io commands.IO) error { genesis.Validators = append(genesis.Validators[:index], genesis.Validators[index+1:]...) // Save the updated genesis - if err := genesis.SaveAs(cfg.genesisPath); err != nil { + if err := genesis.SaveAs(cfg.GenesisPath); err != nil { return fmt.Errorf("unable to save genesis.json, %w", err) } diff --git a/gno.land/cmd/gnoland/genesis_validator_remove_test.go b/contribs/gnogenesis/internal/validator/validator_remove_test.go similarity index 81% rename from gno.land/cmd/gnoland/genesis_validator_remove_test.go rename to contribs/gnogenesis/internal/validator/validator_remove_test.go index e73e867c5c3..78821f4abee 100644 --- a/gno.land/cmd/gnoland/genesis_validator_remove_test.go +++ b/contribs/gnogenesis/internal/validator/validator_remove_test.go @@ -1,9 +1,10 @@ -package main +package validator import ( "context" "testing" + "github.com/gnolang/contribs/gnogenesis/internal/common" "github.com/gnolang/gno/tm2/pkg/bft/types" "github.com/gnolang/gno/tm2/pkg/commands" "github.com/gnolang/gno/tm2/pkg/testutils" @@ -18,10 +19,8 @@ func TestGenesis_Validator_Remove(t *testing.T) { t.Parallel() // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewValidatorCmd(commands.NewTestIO()) args := []string{ - "genesis", - "validator", "remove", "--genesis-path", "dummy-path", @@ -29,7 +28,7 @@ func TestGenesis_Validator_Remove(t *testing.T) { // Run the command cmdErr := cmd.ParseAndRun(context.Background(), args) - assert.ErrorContains(t, cmdErr, errUnableToLoadGenesis.Error()) + assert.ErrorContains(t, cmdErr, common.ErrUnableToLoadGenesis.Error()) }) t.Run("invalid validator address", func(t *testing.T) { @@ -38,14 +37,12 @@ func TestGenesis_Validator_Remove(t *testing.T) { tempGenesis, cleanup := testutils.NewTestFile(t) t.Cleanup(cleanup) - genesis := getDefaultGenesis() + genesis := common.GetDefaultGenesis() require.NoError(t, genesis.SaveAs(tempGenesis.Name())) // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewValidatorCmd(commands.NewTestIO()) args := []string{ - "genesis", - "validator", "remove", "--genesis-path", tempGenesis.Name(), @@ -64,8 +61,8 @@ func TestGenesis_Validator_Remove(t *testing.T) { tempGenesis, cleanup := testutils.NewTestFile(t) t.Cleanup(cleanup) - dummyKeys := getDummyKeys(t, 2) - genesis := getDefaultGenesis() + dummyKeys := common.GetDummyKeys(t, 2) + genesis := common.GetDefaultGenesis() // Set an existing validator genesis.Validators = append(genesis.Validators, types.GenesisValidator{ @@ -78,10 +75,8 @@ func TestGenesis_Validator_Remove(t *testing.T) { require.NoError(t, genesis.SaveAs(tempGenesis.Name())) // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewValidatorCmd(commands.NewTestIO()) args := []string{ - "genesis", - "validator", "remove", "--genesis-path", tempGenesis.Name(), @@ -100,9 +95,9 @@ func TestGenesis_Validator_Remove(t *testing.T) { tempGenesis, cleanup := testutils.NewTestFile(t) t.Cleanup(cleanup) - dummyKey := getDummyKey(t) + dummyKey := common.GetDummyKey(t) - genesis := getDefaultGenesis() + genesis := common.GetDefaultGenesis() // Set an existing validator genesis.Validators = append(genesis.Validators, types.GenesisValidator{ @@ -115,10 +110,8 @@ func TestGenesis_Validator_Remove(t *testing.T) { require.NoError(t, genesis.SaveAs(tempGenesis.Name())) // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewValidatorCmd(commands.NewTestIO()) args := []string{ - "genesis", - "validator", "remove", "--genesis-path", tempGenesis.Name(), diff --git a/gno.land/cmd/gnoland/genesis_verify.go b/contribs/gnogenesis/internal/verify/verify.go similarity index 77% rename from gno.land/cmd/gnoland/genesis_verify.go rename to contribs/gnogenesis/internal/verify/verify.go index 112b075a58c..9022711ce49 100644 --- a/gno.land/cmd/gnoland/genesis_verify.go +++ b/contribs/gnogenesis/internal/verify/verify.go @@ -1,4 +1,4 @@ -package main +package verify import ( "context" @@ -6,6 +6,7 @@ import ( "flag" "fmt" + "github.com/gnolang/contribs/gnogenesis/internal/common" "github.com/gnolang/gno/gno.land/pkg/gnoland" "github.com/gnolang/gno/tm2/pkg/bft/types" "github.com/gnolang/gno/tm2/pkg/commands" @@ -14,17 +15,17 @@ import ( var errInvalidGenesisState = errors.New("invalid genesis state type") type verifyCfg struct { - commonCfg + common.Cfg } -// newVerifyCmd creates the genesis verify subcommand -func newVerifyCmd(io commands.IO) *commands.Command { +// NewVerifyCmd creates the genesis verify subcommand +func NewVerifyCmd(io commands.IO) *commands.Command { cfg := &verifyCfg{} return commands.NewCommand( commands.Metadata{ Name: "verify", - ShortUsage: "verify [flags]", + ShortUsage: "[flags]", ShortHelp: "verifies a genesis.json", LongHelp: "Verifies a node's genesis.json", }, @@ -36,12 +37,12 @@ func newVerifyCmd(io commands.IO) *commands.Command { } func (c *verifyCfg) RegisterFlags(fs *flag.FlagSet) { - c.commonCfg.RegisterFlags(fs) + c.Cfg.RegisterFlags(fs) } func execVerify(cfg *verifyCfg, io commands.IO) error { // Load the genesis - genesis, loadErr := types.GenesisDocFromFile(cfg.genesisPath) + genesis, loadErr := types.GenesisDocFromFile(cfg.GenesisPath) if loadErr != nil { return fmt.Errorf("unable to load genesis, %w", loadErr) } @@ -60,7 +61,7 @@ func execVerify(cfg *verifyCfg, io commands.IO) error { // Validate the initial transactions for _, tx := range state.Txs { - if validateErr := tx.ValidateBasic(); validateErr != nil { + if validateErr := tx.Tx.ValidateBasic(); validateErr != nil { return fmt.Errorf("invalid transacton, %w", validateErr) } } @@ -73,7 +74,7 @@ func execVerify(cfg *verifyCfg, io commands.IO) error { } } - io.Printfln("Genesis at %s is valid", cfg.genesisPath) + io.Printfln("Genesis at %s is valid", cfg.GenesisPath) return nil } diff --git a/gno.land/cmd/gnoland/genesis_verify_test.go b/contribs/gnogenesis/internal/verify/verify_test.go similarity index 87% rename from gno.land/cmd/gnoland/genesis_verify_test.go rename to contribs/gnogenesis/internal/verify/verify_test.go index 9c93519e495..130bd5e09bc 100644 --- a/gno.land/cmd/gnoland/genesis_verify_test.go +++ b/contribs/gnogenesis/internal/verify/verify_test.go @@ -1,4 +1,4 @@ -package main +package verify import ( "context" @@ -9,7 +9,6 @@ import ( "github.com/gnolang/gno/tm2/pkg/bft/types" "github.com/gnolang/gno/tm2/pkg/commands" "github.com/gnolang/gno/tm2/pkg/crypto/mock" - "github.com/gnolang/gno/tm2/pkg/std" "github.com/gnolang/gno/tm2/pkg/testutils" "github.com/stretchr/testify/require" ) @@ -45,7 +44,7 @@ func TestGenesis_Verify(t *testing.T) { g.AppState = gnoland.GnoGenesisState{ Balances: []gnoland.Balance{}, - Txs: []std.Tx{ + Txs: []gnoland.TxWithMetadata{ {}, }, } @@ -53,10 +52,8 @@ func TestGenesis_Verify(t *testing.T) { require.NoError(t, g.SaveAs(tempFile.Name())) // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewVerifyCmd(commands.NewTestIO()) args := []string{ - "genesis", - "verify", "--genesis-path", tempFile.Name(), } @@ -78,16 +75,14 @@ func TestGenesis_Verify(t *testing.T) { Balances: []gnoland.Balance{ {}, }, - Txs: []std.Tx{}, + Txs: []gnoland.TxWithMetadata{}, } require.NoError(t, g.SaveAs(tempFile.Name())) // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewVerifyCmd(commands.NewTestIO()) args := []string{ - "genesis", - "verify", "--genesis-path", tempFile.Name(), } @@ -106,16 +101,14 @@ func TestGenesis_Verify(t *testing.T) { g := getValidTestGenesis() g.AppState = gnoland.GnoGenesisState{ Balances: []gnoland.Balance{}, - Txs: []std.Tx{}, + Txs: []gnoland.TxWithMetadata{}, } require.NoError(t, g.SaveAs(tempFile.Name())) // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewVerifyCmd(commands.NewTestIO()) args := []string{ - "genesis", - "verify", "--genesis-path", tempFile.Name(), } @@ -135,10 +128,8 @@ func TestGenesis_Verify(t *testing.T) { require.NoError(t, g.SaveAs(tempFile.Name())) // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewVerifyCmd(commands.NewTestIO()) args := []string{ - "genesis", - "verify", "--genesis-path", tempFile.Name(), } @@ -159,10 +150,8 @@ func TestGenesis_Verify(t *testing.T) { require.NoError(t, g.SaveAs(tempFile.Name())) // Create the command - cmd := newRootCmd(commands.NewTestIO()) + cmd := NewVerifyCmd(commands.NewTestIO()) args := []string{ - "genesis", - "verify", "--genesis-path", tempFile.Name(), } diff --git a/contribs/gnogenesis/main.go b/contribs/gnogenesis/main.go new file mode 100644 index 00000000000..a5beb2518dd --- /dev/null +++ b/contribs/gnogenesis/main.go @@ -0,0 +1,14 @@ +package main + +import ( + "context" + "os" + + "github.com/gnolang/gno/tm2/pkg/commands" +) + +func main() { + cmd := newGenesisCmd(commands.NewDefaultIO()) + + cmd.Execute(context.Background(), os.Args[1:]) +} diff --git a/contribs/gnokeykc/go.mod b/contribs/gnokeykc/go.mod index a8e235a5c5a..0c794afd54c 100644 --- a/contribs/gnokeykc/go.mod +++ b/contribs/gnokeykc/go.mod @@ -59,6 +59,6 @@ require ( google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd // indirect google.golang.org/grpc v1.65.0 // indirect - google.golang.org/protobuf v1.34.2 // indirect + google.golang.org/protobuf v1.35.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/contribs/gnokeykc/go.sum b/contribs/gnokeykc/go.sum index b3bfadb3468..50eb5add218 100644 --- a/contribs/gnokeykc/go.sum +++ b/contribs/gnokeykc/go.sum @@ -216,8 +216,8 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/contribs/gnomigrate/Makefile b/contribs/gnomigrate/Makefile new file mode 100644 index 00000000000..155fc997012 --- /dev/null +++ b/contribs/gnomigrate/Makefile @@ -0,0 +1,18 @@ +rundep := go run -modfile ../../misc/devdeps/go.mod +golangci_lint := $(rundep) github.com/golangci/golangci-lint/cmd/golangci-lint + + +.PHONY: install +install: + go install . + +.PHONY: build +build: + go build -o build/gnomigrate . + +lint: + $(golangci_lint) --config ../../.github/golangci.yml run ./... + +test: + go test $(GOTEST_FLAGS) -v ./... + diff --git a/contribs/gnomigrate/README.md b/contribs/gnomigrate/README.md new file mode 100644 index 00000000000..2b4f5ecf831 --- /dev/null +++ b/contribs/gnomigrate/README.md @@ -0,0 +1,59 @@ +## Overview + +`gnomigrate` is a CLI tool designed to migrate Gno legacy data formats to the new standard formats used in Gno +blockchain. + +## Features + +- **Transaction Migration**: Converts legacy `std.Tx` transactions to the new `gnoland.TxWithMetadata` format. + +## Installation + +### Clone the repository + +```shell +git clone https://github.com/gnolang/gno.git +``` + +### Navigate to the project directory + +```shell +cd contribs/gnomigrate +``` + +### Build the binary + +```shell +make build +``` + +### Install the binary + +```shell +make install +``` + +## Migrating legacy transactions + +The `gnomigrate` tool provides the `txs` subcommand to manage the migration of legacy transaction sheets. + +```shell +gnomigrate txs --input-dir --output-dir +``` + +### Flags + +- `--input-dir`: Specifies the directory containing the legacy transaction sheets to migrate. +- `--output-dir`: Specifies the directory where the migrated transaction sheets will be saved. + +### Example + +```shell +gnomigrate txs --input-dir ./legacy_txs --output-dir ./migrated_txs +``` + +This command will: + +- Read all `.jsonl` files from the ./legacy_txs directory, that are Amino-JSON encoded `std.Tx`s. +- Migrate each transaction from `std.Tx` to `gnoland.TxWithMetadata` (no metadata). +- Save the migrated transactions to the `./migrated_txs` directory, preserving the original directory structure. diff --git a/contribs/gnomigrate/go.mod b/contribs/gnomigrate/go.mod new file mode 100644 index 00000000000..c492ae7c818 --- /dev/null +++ b/contribs/gnomigrate/go.mod @@ -0,0 +1,57 @@ +module github.com/gnolang/gnomigrate + +go 1.22 + +require ( + github.com/gnolang/gno v0.0.0-00010101000000-000000000000 + github.com/stretchr/testify v1.9.0 +) + +replace github.com/gnolang/gno => ../.. + +require ( + dario.cat/mergo v1.0.1 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/btcsuite/btcd/btcutil v1.1.6 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cockroachdb/apd/v3 v3.2.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect + github.com/gnolang/overflow v0.0.0-20170615021017-4d914c927216 // indirect + github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/websocket v1.5.3 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect + github.com/libp2p/go-buffer-pool v0.1.0 // indirect + github.com/pelletier/go-toml v1.9.5 // indirect + github.com/peterbourgon/ff/v3 v3.4.0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/rs/cors v1.11.1 // indirect + github.com/rs/xid v1.6.0 // indirect + github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect + go.etcd.io/bbolt v1.3.11 // indirect + go.opentelemetry.io/otel v1.29.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.29.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.29.0 // indirect + go.opentelemetry.io/otel/metric v1.29.0 // indirect + go.opentelemetry.io/otel/sdk v1.29.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.29.0 // indirect + go.opentelemetry.io/otel/trace v1.29.0 // indirect + go.opentelemetry.io/proto/otlp v1.3.1 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/crypto v0.26.0 // indirect + golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 // indirect + golang.org/x/mod v0.20.0 // indirect + golang.org/x/net v0.28.0 // indirect + golang.org/x/sys v0.24.0 // indirect + golang.org/x/term v0.23.0 // indirect + golang.org/x/text v0.17.0 // indirect + golang.org/x/tools v0.24.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd // indirect + google.golang.org/grpc v1.65.0 // indirect + google.golang.org/protobuf v1.35.1 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/contribs/gnomigrate/go.sum b/contribs/gnomigrate/go.sum new file mode 100644 index 00000000000..f3161e47bad --- /dev/null +++ b/contribs/gnomigrate/go.sum @@ -0,0 +1,230 @@ +dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= +dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +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.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= +github.com/btcsuite/btcd v0.24.2 h1:aLmxPguqxza+4ag8R1I2nnJjSu2iFn/kqtHTIImswcY= +github.com/btcsuite/btcd v0.24.2/go.mod h1:5C8ChTkl5ejr3WHj8tkQSCmydiMEPB0ZhQhehpq7Dgg= +github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= +github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= +github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= +github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= +github.com/btcsuite/btcd/btcutil v1.1.6 h1:zFL2+c3Lb9gEgqKNzowKUPQNb8jV7v5Oaodi/AYFd6c= +github.com/btcsuite/btcd/btcutil v1.1.6/go.mod h1:9dFymx8HpuLqBnsPELrImQeTQfKBQqzqGbbV3jK55aE= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cockroachdb/apd/v3 v3.2.1 h1:U+8j7t0axsIgvQUqthuNm82HIrYXodOV2iWLWtEaIwg= +github.com/cockroachdb/apd/v3 v3.2.1/go.mod h1:klXJcjp+FffLTHlhIG69tezTDvdP065naDsHzKhYSqc= +github.com/cosmos/ledger-cosmos-go v0.13.3 h1:7ehuBGuyIytsXbd4MP43mLeoN2LTOEnk5nvue4rK+yM= +github.com/cosmos/ledger-cosmos-go v0.13.3/go.mod h1:HENcEP+VtahZFw38HZ3+LS3Iv5XV6svsnkk9vdJtLr8= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/gnolang/overflow v0.0.0-20170615021017-4d914c927216 h1:GKvsK3oLWG9B1GL7WP/VqwM6C92j5tIvB844oggL9Lk= +github.com/gnolang/overflow v0.0.0-20170615021017-4d914c927216/go.mod h1:xJhtEL7ahjM1WJipt89gel8tHzfIl/LyMY+lCYh38d8= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +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/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= +github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= +github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= +github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= +github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= +github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/peterbourgon/ff/v3 v3.4.0 h1:QBvM/rizZM1cB0p0lGMdmR7HxZeI/ZrBWB4DqLkMUBc= +github.com/peterbourgon/ff/v3 v3.4.0/go.mod h1:zjJVUhx+twciwfDl0zBcFzl4dW8axCRyXE/eKY9RztQ= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= +github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU= +github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= +github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= +github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw= +github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI= +go.etcd.io/bbolt v1.3.11 h1:yGEzV1wPz2yVCLsD8ZAiGHhHVlczyC9d1rP43/VCRJ0= +go.etcd.io/bbolt v1.3.11/go.mod h1:dksAq7YMXoljX0xu6VF5DMZGbhYYoLUalEiSySYAS4I= +go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw= +go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.29.0 h1:k6fQVDQexDE+3jG2SfCQjnHS7OamcP73YMoxEVq5B6k= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.29.0/go.mod h1:t4BrYLHU450Zo9fnydWlIuswB1bm7rM8havDpWOJeDo= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.29.0 h1:xvhQxJ/C9+RTnAj5DpTg7LSM1vbbMTiXt7e9hsfqHNw= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.29.0/go.mod h1:Fcvs2Bz1jkDM+Wf5/ozBGmi3tQ/c9zPKLnsipnfhGAo= +go.opentelemetry.io/otel/metric v1.29.0 h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc= +go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8= +go.opentelemetry.io/otel/sdk v1.29.0 h1:vkqKjk7gwhS8VaWb0POZKmIEDimRCMsopNYnriHyryo= +go.opentelemetry.io/otel/sdk v1.29.0/go.mod h1:pM8Dx5WKnvxLCb+8lG1PRNIDxu9g9b9g59Qr7hfAAok= +go.opentelemetry.io/otel/sdk/metric v1.29.0 h1:K2CfmJohnRgvZ9UAj2/FhIf/okdWcNdBwe1m8xFXiSY= +go.opentelemetry.io/otel/sdk/metric v1.29.0/go.mod h1:6zZLdCl2fkauYoZIOn/soQIDSWFmNSRcICarHfuhNJQ= +go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt39JTi4= +go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= +golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= +golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY= +golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= +golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= +golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd h1:BBOTEWLuuEGQy9n1y9MhVJ9Qt0BDu21X8qZs71/uPZo= +google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:fO8wJzT2zbQbAjbIoos1285VfEIYKDDY+Dt+WpTkh6g= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd h1:6TEm2ZxXoQmFWFlt1vNxvVOa1Q0dXFQD1m/rYjXmS0E= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= +google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/contribs/gnomigrate/internal/txs/txs.go b/contribs/gnomigrate/internal/txs/txs.go new file mode 100644 index 00000000000..4c65ca6ef0b --- /dev/null +++ b/contribs/gnomigrate/internal/txs/txs.go @@ -0,0 +1,199 @@ +package txs + +import ( + "bufio" + "context" + "errors" + "flag" + "fmt" + "os" + "path/filepath" + "strings" + + "github.com/gnolang/gno/gno.land/pkg/gnoland" + "github.com/gnolang/gno/tm2/pkg/amino" + "github.com/gnolang/gno/tm2/pkg/commands" + "github.com/gnolang/gno/tm2/pkg/std" +) + +var ( + errInvalidInputDir = errors.New("invalid input directory") + errInvalidOutputDir = errors.New("invalid output directory") +) + +type txsCfg struct { + inputDir string + outputDir string +} + +// NewTxsCmd creates the migrate txs subcommand +func NewTxsCmd(io commands.IO) *commands.Command { + cfg := &txsCfg{} + + cmd := commands.NewCommand( + commands.Metadata{ + Name: "txs", + ShortUsage: " [flags]", + ShortHelp: "manages the legacy transaction sheet migrations", + LongHelp: "Manages legacy transaction migrations through sheet input files", + }, + cfg, + func(ctx context.Context, _ []string) error { + return cfg.execMigrate(ctx, io) + }, + ) + + return cmd +} + +func (c *txsCfg) RegisterFlags(fs *flag.FlagSet) { + fs.StringVar( + &c.inputDir, + "input-dir", + "", + "the input directory for the legacy transaction sheets", + ) + + fs.StringVar( + &c.outputDir, + "output-dir", + "", + "the output directory for the standard transaction sheets", + ) +} + +func (c *txsCfg) execMigrate(ctx context.Context, io commands.IO) error { + // Make sure the dirs are set + if c.inputDir == "" { + return errInvalidInputDir + } + + if c.outputDir == "" { + return errInvalidOutputDir + } + + // Make sure the output dir is present + if err := os.MkdirAll(c.outputDir, os.ModePerm); err != nil { + return fmt.Errorf("unable to create output dir, %w", err) + } + + return migrateDir(ctx, io, c.inputDir, c.outputDir) +} + +// migrateDir migrates the transaction sheet directory +func migrateDir( + ctx context.Context, + io commands.IO, + sourceDir string, + outputDir string, +) error { + // Read the sheet directory + entries, err := os.ReadDir(sourceDir) + if err != nil { + return fmt.Errorf("error reading directory %s, %w", sourceDir, err) + } + + for _, entry := range entries { + select { + case <-ctx.Done(): + return nil + default: + var ( + srcPath = filepath.Join(sourceDir, entry.Name()) + destPath = filepath.Join(outputDir, entry.Name()) + ) + + // Check if a dir is encountered + if !entry.IsDir() { + // Make sure the file type is valid + if !strings.HasSuffix(entry.Name(), ".jsonl") { + continue + } + + // Process the tx sheet + io.Printfln("Migrating %s -> %s", srcPath, destPath) + + if err := processFile(ctx, io, srcPath, destPath); err != nil { + io.ErrPrintfln("unable to process file %s, %w", srcPath, err) + } + + continue + } + + // Ensure destination directory exists + if err = os.MkdirAll(destPath, os.ModePerm); err != nil { + return fmt.Errorf("error creating directory %s, %w", destPath, err) + } + + // Recursively process the directory + if err = migrateDir(ctx, io, srcPath, destPath); err != nil { + io.ErrPrintfln("unable migrate directory %s, %w", srcPath, err) + } + } + } + + return nil +} + +// processFile processes the old legacy std.Tx sheet into the new standard gnoland.TxWithMetadata +func processFile(ctx context.Context, io commands.IO, source, destination string) error { + file, err := os.Open(source) + if err != nil { + return fmt.Errorf("unable to open file, %w", err) + } + defer file.Close() + + // Create the destination file + outputFile, err := os.Create(destination) + if err != nil { + return fmt.Errorf("unable to create file, %w", err) + } + defer outputFile.Close() + + scanner := bufio.NewScanner(file) + + scanner.Buffer(make([]byte, 1_000_000), 2_000_000) + + for scanner.Scan() { + select { + case <-ctx.Done(): + return nil + default: + var ( + tx std.Tx + txWithMetadata gnoland.TxWithMetadata + ) + + if err = amino.UnmarshalJSON(scanner.Bytes(), &tx); err != nil { + io.ErrPrintfln("unable to read line, %s", err) + + continue + } + + // Convert the std.Tx -> gnoland.TxWithMetadata + txWithMetadata = gnoland.TxWithMetadata{ + Tx: tx, + Metadata: nil, // not set + } + + // Save the new transaction with metadata + marshaledData, err := amino.MarshalJSON(txWithMetadata) + if err != nil { + io.ErrPrintfln("unable to marshal tx, %s", err) + + continue + } + + if _, err = outputFile.WriteString(fmt.Sprintf("%s\n", string(marshaledData))); err != nil { + io.ErrPrintfln("unable to save to output file, %s", err) + } + } + } + + // Check if there were any scanner errors + if err := scanner.Err(); err != nil { + return fmt.Errorf("error encountered during scan, %w", err) + } + + return nil +} diff --git a/contribs/gnomigrate/internal/txs/txs_test.go b/contribs/gnomigrate/internal/txs/txs_test.go new file mode 100644 index 00000000000..edc8addf213 --- /dev/null +++ b/contribs/gnomigrate/internal/txs/txs_test.go @@ -0,0 +1,157 @@ +package txs + +import ( + "context" + "fmt" + "os" + "path/filepath" + "testing" + + "github.com/gnolang/gno/gno.land/pkg/gnoland" + "github.com/gnolang/gno/gno.land/pkg/gnoland/ugnot" + "github.com/gnolang/gno/tm2/pkg/amino" + "github.com/gnolang/gno/tm2/pkg/commands" + "github.com/gnolang/gno/tm2/pkg/crypto" + "github.com/gnolang/gno/tm2/pkg/sdk/bank" + "github.com/gnolang/gno/tm2/pkg/std" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// generateDummyTxs generates dummy transactions +func generateDummyTxs(t *testing.T, count int) []std.Tx { + t.Helper() + + txs := make([]std.Tx, count) + + for i := 0; i < count; i++ { + txs[i] = std.Tx{ + Msgs: []std.Msg{ + bank.MsgSend{ + FromAddress: crypto.Address{byte(i)}, + ToAddress: crypto.Address{byte((i + 1) % count)}, + Amount: std.NewCoins(std.NewCoin(ugnot.Denom, 1)), + }, + }, + Fee: std.Fee{ + GasWanted: 1, + GasFee: std.NewCoin(ugnot.Denom, 1000000), + }, + Memo: fmt.Sprintf("tx %d", i), + } + } + + return txs +} + +func TestMigrate_Txs(t *testing.T) { + t.Parallel() + + t.Run("invalid input dir", func(t *testing.T) { + t.Parallel() + + // Perform the migration + cmd := NewTxsCmd(commands.NewTestIO()) + args := []string{ + "--input-dir", + "", + "--output-dir", + t.TempDir(), + } + + // Run the command + cmdErr := cmd.ParseAndRun(context.Background(), args) + assert.ErrorIs(t, cmdErr, errInvalidInputDir) + }) + + t.Run("invalid output dir", func(t *testing.T) { + t.Parallel() + + // Perform the migration + cmd := NewTxsCmd(commands.NewTestIO()) + args := []string{ + "--input-dir", + t.TempDir(), + "--output-dir", + "", + } + + // Run the command + cmdErr := cmd.ParseAndRun(context.Background(), args) + assert.ErrorIs(t, cmdErr, errInvalidOutputDir) + }) + + t.Run("valid tx sheet migration", func(t *testing.T) { + t.Parallel() + + var ( + inputDir = t.TempDir() + outputDir = t.TempDir() + + txs = generateDummyTxs(t, 10000) + + chunks = 4 + chunkSize = len(txs) / chunks + ) + + getSheetPath := func(dir string, index int) string { + return filepath.Join(dir, fmt.Sprintf("transactions-sheet-%d.jsonl", index)) + } + + // Generate the initial sheet files + files := make([]*os.File, 0, chunks) + for i := 0; i < chunks; i++ { + f, err := os.Create(getSheetPath(inputDir, i)) + require.NoError(t, err) + + files = append(files, f) + } + + for i := 0; i < chunks; i++ { + var ( + start = i * chunkSize + end = start + chunkSize + ) + + if end > len(txs) { + end = len(txs) + } + + tx := txs[start:end] + + f := files[i] + + jsonData, err := amino.MarshalJSON(tx) + require.NoError(t, err) + + _, err = f.WriteString(fmt.Sprintf("%s\n", jsonData)) + require.NoError(t, err) + } + + // Perform the migration + cmd := NewTxsCmd(commands.NewTestIO()) + args := []string{ + "--input-dir", + inputDir, + "--output-dir", + outputDir, + } + + // Run the command + cmdErr := cmd.ParseAndRun(context.Background(), args) + require.NoError(t, cmdErr) + + metadataTxs := make([]gnoland.TxWithMetadata, 0, len(txs)) + for i := 0; i < chunks; i++ { + readTxs, err := gnoland.ReadGenesisTxs(context.Background(), getSheetPath(outputDir, i)) + require.NoError(t, err) + + metadataTxs = append(metadataTxs, readTxs...) + } + + // Make sure the metadata txs match + for index, tx := range metadataTxs { + assert.Equal(t, txs[index], tx.Tx) + } + }) +} diff --git a/contribs/gnomigrate/main.go b/contribs/gnomigrate/main.go new file mode 100644 index 00000000000..ea7e2561e8b --- /dev/null +++ b/contribs/gnomigrate/main.go @@ -0,0 +1,14 @@ +package main + +import ( + "context" + "os" + + "github.com/gnolang/gno/tm2/pkg/commands" +) + +func main() { + cmd := newMigrateCmd(commands.NewDefaultIO()) + + cmd.Execute(context.Background(), os.Args[1:]) +} diff --git a/contribs/gnomigrate/migrate.go b/contribs/gnomigrate/migrate.go new file mode 100644 index 00000000000..6c8667a5f58 --- /dev/null +++ b/contribs/gnomigrate/migrate.go @@ -0,0 +1,24 @@ +package main + +import ( + "github.com/gnolang/gno/tm2/pkg/commands" + "github.com/gnolang/gnomigrate/internal/txs" +) + +func newMigrateCmd(io commands.IO) *commands.Command { + cmd := commands.NewCommand( + commands.Metadata{ + ShortUsage: " [flags] [...]", + ShortHelp: "gno migration suite", + LongHelp: "Gno state migration suite, for managing legacy headaches", + }, + commands.NewEmptyConfig(), + commands.HelpExec, + ) + + cmd.AddSubCommands( + txs.NewTxsCmd(io), + ) + + return cmd +} diff --git a/docs/gno-infrastructure/validators/faq.md b/docs/gno-infrastructure/validators/faq.md index c345b49724a..1a065a5ca56 100644 --- a/docs/gno-infrastructure/validators/faq.md +++ b/docs/gno-infrastructure/validators/faq.md @@ -104,41 +104,6 @@ either a full node or a pruned node, it is important to retain enough blocks to ## Technical References -### How do I generate `genesis.json`? - -`genesis.json` is the file that is used to create the initial state of the chain. To generate `genesis.json`, use -the `gnoland genesis generate` command. Refer -to [this section](../../gno-tooling/cli/gnoland.md#gnoland-genesis-generate-flags) for various flags that allow you to -manipulate the file. - -:::warning - -Editing generated genesis.json manually is extremely dangerous. It may corrupt chain initial state which leads chain to -not start - -::: - -### How do I add or remove validators from `genesis.json`? - -Validators inside `genesis.json` will be included in the validator set at genesis. To manipulate the genesis validator -set, use the `gnoland genesis validator` command with the `add` or `remove` subcommands. Refer -to [this section](../../gno-tooling/cli/gnoland.md#gnoland-genesis-validator-flags) for flags that allow you to -configure the name or the voting power of the validator. - -### How do I add the balance information to the `genesis.json`? - -You may premine coins to various addresses. To modify the balances of addresses at genesis, use -the `gnoland genesis balances` command with the `add` or `remove` subcommands. Refer -to [this section](../../gno-tooling/cli/gnoland.md#gnoland-genesis-balances-add-flags) for various flags that allow you -to update the entire balance sheet with a file or modify the balance of a single address. - -:::info - -Not only `ugnot`, but other coins are accepted. However, be aware that coins other than `ugnot` may not work(send, and -etc.) properly. - -::: - ### How do I initialize `gno secrets`? The `gno secrets init` command allows you to initialize the private information required to run the validator, including diff --git a/docs/gno-infrastructure/validators/setting-up-a-new-chain.md b/docs/gno-infrastructure/validators/setting-up-a-new-chain.md index 0411fa3b02a..5db8a7f1a59 100644 --- a/docs/gno-infrastructure/validators/setting-up-a-new-chain.md +++ b/docs/gno-infrastructure/validators/setting-up-a-new-chain.md @@ -19,7 +19,7 @@ Additionally, you will see the different options you can use to make your Gno in ## Installation -To install the `gnoland` binary, clone the Gno monorepo: +To install the `gnoland` and `gnogenesis` binaries, clone the Gno monorepo: ```bash git clone https://github.com/gnolang/gno.git @@ -30,7 +30,7 @@ Makefile to install the `gnoland` binary: ```bash cd gno.land -make install.gnoland +make install.gnoland && make -C contribs/gnogenesis install ``` To verify that you've installed the binary properly and that you are able to use @@ -93,7 +93,8 @@ Let's break down the most important default settings: :::info Resetting the chain As mentioned, the working directory for the node is located in `data-dir`. To reset the chain, you need -to delete this directory and `genesis.json`, then start the node up again. If you are using the default node configuration, you can run +to delete this directory and `genesis.json`, then start the node up again. If you are using the default node +configuration, you can run `make fclean` from the `gno.land` sub-folder to delete the `gnoland-data` working directory. ::: @@ -201,7 +202,7 @@ executed. Generating an empty `genesis.json` is relatively straightforward: ```shell -gnoland genesis generate +gnogenesis generate ``` The resulting `genesis.json` is empty: @@ -232,7 +233,7 @@ This will generate a `genesis.json` in the calling directory, by default. To che generating the `genesis.json`, you can run the command using the `--help` flag: ```shell -gnoland genesis generate --help +gnogenesis generate --help USAGE generate [flags] @@ -257,7 +258,7 @@ present challenges with users who expect them to be present. The `examples` directory is located in the `$GNOROOT` location, or the local gno repository clone. ```bash -gnoland genesis txs add packages ./examples +gnogenesis txs add packages ./examples ``` ### 4. Add the initial validator set @@ -288,7 +289,7 @@ Updating the `genesis.json` is relatively simple, running the following command validator set: ```shell -gnoland genesis validator add \ +gnogenesis validator add \ --address g14j4dlsh3jzgmhezzp9v8xp7wxs4mvyskuw5ljl \ --pub-key gpub1pggj7ard9eg82cjtv4u52epjx56nzwgjyg9zqaqle3fdduqul4slg6zllypq9r8gj4wlfucy6qfnzmjcgqv675kxjz8jvk \ --name Cuttlas diff --git a/docs/gno-tooling/cli/gnokey/working-with-key-pairs.md b/docs/gno-tooling/cli/gnokey/working-with-key-pairs.md index ba03ca569b4..9bc29da6a18 100644 --- a/docs/gno-tooling/cli/gnokey/working-with-key-pairs.md +++ b/docs/gno-tooling/cli/gnokey/working-with-key-pairs.md @@ -38,6 +38,7 @@ gno.land keychain & client SUBCOMMANDS add adds key to the keybase delete deletes a key from the keybase + rotate rotate the password of a key in the keybase to a new password generate generates a bip39 mnemonic export exports private key armor import imports encrypted private key armor @@ -161,6 +162,18 @@ you can recover it using the key's mnemonic, or by importing it if it was export at a previous point in time. ::: + +## Rotating the password of a private key to a new password +To rotate the password of a private key from the `gnokey` keystore to a new password, we need to know the name or +address of the key to remove. +After we have this information, we can run the following command: + +```bash +gnokey rotate MyKey +``` + +After entering the current key decryption password and the new password, the password of the key will be updated in the keystore. + ## Exporting a private key Private keys stored in the `gnokey` keystore can be exported to a desired place on the user's filesystem. diff --git a/docs/gno-tooling/cli/gnoland.md b/docs/gno-tooling/cli/gnoland.md index 18175871d90..037a1f19d03 100644 --- a/docs/gno-tooling/cli/gnoland.md +++ b/docs/gno-tooling/cli/gnoland.md @@ -29,164 +29,6 @@ Starts the Gnoland blockchain node, with accompanying setup. | `log-level` | String | The log level for the gnoland node. (default: `debug`) | | `skip-failing-genesis-txs` | Boolean | Doesn’t panic when replaying invalid genesis txs. When starting a production-level chain, it is recommended to set this value to `true` to monitor and analyze failing transactions. (default: `false`) | -### gnoland genesis \ [flags] [\...] - -Gno `genesis.json` manipulation suite for managing genesis parameters. - -#### SUBCOMMANDS - -| Name | Description | -|-------------|---------------------------------------------| -| `generate` | Generates a fresh `genesis.json`. | -| `validator` | Validator set management in `genesis.json`. | -| `verify` | Verifies a `genesis.json`. | -| `balances` | Manages `genesis.json` account balances. | -| `txs` | Manages the initial genesis transactions. | - -### gnoland genesis generate [flags] - -Generates a node's `genesis.json` based on specified parameters. - -#### FLAGS - -| Name | Type | Description | -|------------------------|--------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `block-max-data-bytes` | Int | The max size of the block data.(default: `2000000`) | -| `block-max-gas` | Int | The max gas limit for the block. (default: `100000000`) | -| `block-max-tx-bytes` | Int | The max size of the block transaction. (default: `1000000`) | -| `block-time-itoa` | Int | The block time itoa (in ms). (default: `100`) | -| `chain-id` | String | The ID of the chain. (default: `dev`) | -| `genesis-time` | Int | The genesis creation time. (default: `utc now timestamp`) | -| `output-path` : | String | The output path for the `genesis.json`. If the genesis-time of the Genesis File is set to a future time, the chain will automatically start at that time if the node is online. (default: `./genesis.json`) | - -### gnoland genesis validator \ [flags] - -Manipulates the `genesis.json` validator set. - -#### SUBCOMANDS - -| Name | Description | -|----------|----------------------------------------------| -| `add` | Adds a new validator to the `genesis.json`. | -| `remove` | Removes a validator from the `genesis.json`. | - -#### FLAGS - -| Name | Type | Description | -|----------------|--------|------------------------------------------------------------| -| `address` | String | The gno bech32 address of the validator. | -| `genesis-path` | String | The path to the `genesis.json`. (default `./genesis.json`) | - -### gnoland genesis validator add [flags] - -Adds a new validator to the `genesis.json`. - -#### FLAGS - -| Name | Type | Description | -|----------------|--------|-----------------------------------------------------------------| -| `address` | String | The gno bech32 address of the validator. | -| `genesis-path` | String | The path to the `genesis.json`. (default: `./genesis.json`) | -| `name` | String | The name of the validator (must be unique). | -| `power` | Uint | The voting power of the validator (must be > 0). (default: `1`) | -| `pub-key` | String | The bech32 string representation of the validator's public key. | - -```bash -gnoland genesis validator add \ --address g1rzuwh5frve732k4futyw45y78rzuty4626zy6h \ --name test1 \ --pub-key gpub1pggj7ard9eg82cjtv4u52epjx56nzwgjyg9zplmcmggxyxyrch0zcyg684yxmerullv3l6hmau58sk4eyxskmny9h7lsnz - -Validator with address g1rzuwh5frve732k4futyw45y78rzuty4626zy6h added to genesis file -``` - -### gnoland genesis validator remove [flags] - -Removes a validator from the `genesis.json`. - -#### FLAGS - -| Name | Type | Description | -|----------------|--------|-------------------------------------------------------------| -| `address` | String | The gno bech32 address of the validator. | -| `genesis-path` | String | The path to the `genesis.json`. (default: `./genesis.json)` | - -```bash -gnoland genesis validator remove \ --address g1rzuwh5frve732k4futyw45y78rzuty4626zy6h - -Validator with address g1rzuwh5frve732k4futyw45y78rzuty4626zy6h removed from genesis file -``` - -### gnoland genesis verify \ [flags] [\…] - -Verifies a `genesis.json`. - -#### FLAGS - -| Name | Type | Description | -|----------------|--------|-----------------------------------------------------------| -| `genesis-path` | String | The path to the `genesis.json`. (default: `genesis.json`) | - -### gnoland genesis balances \ [flags] [\…] - -Manages `genesis.json` account balances. - -#### SUBCOMMANDS - -| Name | Description | -|----------|--------------------------------------------------------| -| `add` | Adds the balance information. | -| `remove` | Removes the balance information of a specific account. | - -### gnoland genesis balances add [flags] - -#### FLAGS - -| Name | Type | Description | -|-----------------|--------|--------------------------------------------------------------------------------------------| -| `balance-sheet` | String | The path to the balance file containing addresses in the format `
=ugnot`. | -| `genesis-path` | String | The path to the `genesis.json` (default: `./genesis.json`) | -| `parse-export` | String | The path to the transaction export containing a list of transactions (JSONL). | -| `single` | String | The direct balance addition in the format `
=ugnot`. | - -```bash -gnoland genesis balances add \ --single g1rzuwh5frve732k4futyw45y78rzuty4626zy6h=100ugnot - -1 pre-mines saved - -g1rzuwh5frve732k4futyw45y78rzuty4626zy6h:{[24 184 235 209 35 102 125 21 90 169 226 200 234 208 158 56 197 197 146 186] [{%!d(string=ugnot) 100}]}ugnot -``` - -### gnoland balances remove [flags] - -#### FLAGS - -| Name | Type | Description | -|----------------|--------|---------------------------------------------------------------------------------------------| -| `address` | String | The address of the account whose balance information should be removed from `genesis.json`. | -| `genesis-path` | String | The path to the `genesis.json`. (default: `./genesis.json`) | - -```bash -gnoland genesis balances remove \ --address=g1rzuwh5frve732k4futyw45y78rzuty4626zy6h - -Pre-mine information for address g1rzuwh5frve732k4futyw45y78rzuty4626zy6h removed -``` - -### gnoland txs \ [flags] [\…] - -Manages genesis transactions through input files. - -#### SUBCOMMANDS - -| Name | Description | -|----------|---------------------------------------------------| -| `add` | Imports transactions into the `genesis.json`. | -| `remove` | Removes the transactions from the `genesis.json`. | -| `export` | Exports the transactions from the `genesis.json`. | - ### gnoland secrets \ [flags] [\…] The gno secrets manipulation suite for managing the validator key, p2p key and diff --git a/docs/reference/go-gno-compatibility.md b/docs/reference/go-gno-compatibility.md index bad19860655..9f9d611e4fd 100644 --- a/docs/reference/go-gno-compatibility.md +++ b/docs/reference/go-gno-compatibility.md @@ -248,7 +248,7 @@ Legend: | runtime/trace | `gospec` | | slices | `gnics` | | sort | `part`[^6] | -| strconv | `part` | +| strconv | `full`[^10] | | strings | `full` | | sync | `tbd` | | sync/atomic | `tbd` | @@ -292,6 +292,8 @@ Legend: [^8]: `crypto/ed25519` is currently only implemented for `Verify`, which should still cover a majority of use cases. A full implementation is welcome. [^9]: `math/rand` in Gno ports over Go's `math/rand/v2`. +[^10]: `strconv` does not have the methods relating to types `complex64` and + `complex128`. ## Tooling (`gno` binary) @@ -301,9 +303,9 @@ Legend: | go build | gno transpile -gobuild | same intention, limited compatibility | | go clean | gno clean | same intention, limited compatibility | | go doc | gno doc | limited compatibility; see https://github.com/gnolang/gno/issues/522 | -| go env | | | +| go env | gno env | | | go fix | | | -| go fmt | | gofmt (& similar tools, like gofumpt) works on gno code. | +| go fmt | gno fmt | gofmt (& similar tools, like gofumpt) works on gno code. | | go generate | | | | go get | | see `gno mod download`. | | go help | gno $cmd --help | ie. `gno doc --help` | diff --git a/examples/gno.land/p/demo/combinederr/combinederr.gno b/examples/gno.land/p/demo/combinederr/combinederr.gno new file mode 100644 index 00000000000..f446c7846bd --- /dev/null +++ b/examples/gno.land/p/demo/combinederr/combinederr.gno @@ -0,0 +1,40 @@ +package combinederr + +import "strings" + +// CombinedError is a combined execution error +type CombinedError struct { + errors []error +} + +// Error returns the combined execution error +func (e *CombinedError) Error() string { + if len(e.errors) == 0 { + return "" + } + + var sb strings.Builder + + for _, err := range e.errors { + sb.WriteString(err.Error() + "; ") + } + + // Remove the last semicolon and space + result := sb.String() + + return result[:len(result)-2] +} + +// Add adds a new error to the execution error +func (e *CombinedError) Add(err error) { + if err == nil { + return + } + + e.errors = append(e.errors, err) +} + +// Size returns a +func (e *CombinedError) Size() int { + return len(e.errors) +} diff --git a/examples/gno.land/p/demo/combinederr/gno.mod b/examples/gno.land/p/demo/combinederr/gno.mod new file mode 100644 index 00000000000..4c99e0ba7ef --- /dev/null +++ b/examples/gno.land/p/demo/combinederr/gno.mod @@ -0,0 +1 @@ +module gno.land/p/demo/combinederr diff --git a/examples/gno.land/p/demo/dao/dao.gno b/examples/gno.land/p/demo/dao/dao.gno new file mode 100644 index 00000000000..f8ea433192f --- /dev/null +++ b/examples/gno.land/p/demo/dao/dao.gno @@ -0,0 +1,33 @@ +package dao + +const ( + ProposalAddedEvent = "ProposalAdded" // emitted when a new proposal has been added + ProposalAcceptedEvent = "ProposalAccepted" // emitted when a proposal has been accepted + ProposalNotAcceptedEvent = "ProposalNotAccepted" // emitted when a proposal has not been accepted + ProposalExecutedEvent = "ProposalExecuted" // emitted when a proposal has been executed + + ProposalEventIDKey = "proposal-id" + ProposalEventAuthorKey = "proposal-author" + ProposalEventExecutionKey = "exec-status" +) + +// ProposalRequest is a single govdao proposal request +// that contains the necessary information to +// log and generate a valid proposal +type ProposalRequest struct { + Description string // the description associated with the proposal + Executor Executor // the proposal executor +} + +// DAO defines the DAO abstraction +type DAO interface { + // PropStore is the DAO proposal storage + PropStore + + // Propose adds a new proposal to the executor-based GOVDAO. + // Returns the generated proposal ID + Propose(request ProposalRequest) (uint64, error) + + // ExecuteProposal executes the proposal with the given ID + ExecuteProposal(id uint64) error +} diff --git a/examples/gno.land/p/demo/dao/doc.gno b/examples/gno.land/p/demo/dao/doc.gno new file mode 100644 index 00000000000..3fb28204013 --- /dev/null +++ b/examples/gno.land/p/demo/dao/doc.gno @@ -0,0 +1,5 @@ +// Package dao houses common DAO building blocks (framework), which can be used or adopted by any +// specific DAO implementation. By design, the DAO should house the proposals it receives, but not the actual +// DAO members or proposal votes. These abstractions should be implemented by a separate entity, to keep the DAO +// agnostic of implementation details such as these (member / vote management). +package dao diff --git a/examples/gno.land/p/demo/dao/events.gno b/examples/gno.land/p/demo/dao/events.gno new file mode 100644 index 00000000000..97bc794e6f3 --- /dev/null +++ b/examples/gno.land/p/demo/dao/events.gno @@ -0,0 +1,56 @@ +package dao + +import ( + "std" + + "gno.land/p/demo/ufmt" +) + +// EmitProposalAdded emits an event signaling that +// a given proposal was added +func EmitProposalAdded(id uint64, proposer std.Address) { + std.Emit( + ProposalAddedEvent, + ProposalEventIDKey, ufmt.Sprintf("%d", id), + ProposalEventAuthorKey, proposer.String(), + ) +} + +// EmitProposalAccepted emits an event signaling that +// a given proposal was accepted +func EmitProposalAccepted(id uint64) { + std.Emit( + ProposalAcceptedEvent, + ProposalEventIDKey, ufmt.Sprintf("%d", id), + ) +} + +// EmitProposalNotAccepted emits an event signaling that +// a given proposal was not accepted +func EmitProposalNotAccepted(id uint64) { + std.Emit( + ProposalNotAcceptedEvent, + ProposalEventIDKey, ufmt.Sprintf("%d", id), + ) +} + +// EmitProposalExecuted emits an event signaling that +// a given proposal was executed, with the given status +func EmitProposalExecuted(id uint64, status ProposalStatus) { + std.Emit( + ProposalExecutedEvent, + ProposalEventIDKey, ufmt.Sprintf("%d", id), + ProposalEventExecutionKey, status.String(), + ) +} + +// EmitVoteAdded emits an event signaling that +// a vote was cast for a given proposal +func EmitVoteAdded(id uint64, voter std.Address, option VoteOption) { + std.Emit( + VoteAddedEvent, + VoteAddedIDKey, ufmt.Sprintf("%d", id), + VoteAddedAuthorKey, voter.String(), + VoteAddedOptionKey, option.String(), + ) +} diff --git a/examples/gno.land/p/demo/dao/executor.gno b/examples/gno.land/p/demo/dao/executor.gno new file mode 100644 index 00000000000..9291c2c53c5 --- /dev/null +++ b/examples/gno.land/p/demo/dao/executor.gno @@ -0,0 +1,9 @@ +package dao + +// Executor represents a minimal closure-oriented proposal design. +// It is intended to be used by a govdao governance proposal (v1, v2, etc) +type Executor interface { + // Execute executes the given proposal, and returns any error encountered + // during the execution + Execute() error +} diff --git a/examples/gno.land/p/demo/dao/gno.mod b/examples/gno.land/p/demo/dao/gno.mod new file mode 100644 index 00000000000..ecbab2f7692 --- /dev/null +++ b/examples/gno.land/p/demo/dao/gno.mod @@ -0,0 +1,3 @@ +module gno.land/p/demo/dao + +require gno.land/p/demo/ufmt v0.0.0-latest diff --git a/examples/gno.land/p/demo/dao/proposals.gno b/examples/gno.land/p/demo/dao/proposals.gno new file mode 100644 index 00000000000..5cad679d006 --- /dev/null +++ b/examples/gno.land/p/demo/dao/proposals.gno @@ -0,0 +1,62 @@ +package dao + +import "std" + +// ProposalStatus is the currently active proposal status, +// changed based on DAO functionality. +// Status transitions: +// +// ACTIVE -> ACCEPTED -> EXECUTION(SUCCEEDED/FAILED) +// +// ACTIVE -> NOT ACCEPTED +type ProposalStatus string + +var ( + Active ProposalStatus = "active" // proposal is still active + Accepted ProposalStatus = "accepted" // proposal gathered quorum + NotAccepted ProposalStatus = "not accepted" // proposal failed to gather quorum + ExecutionSuccessful ProposalStatus = "execution successful" // proposal is executed successfully + ExecutionFailed ProposalStatus = "execution failed" // proposal is failed during execution +) + +func (s ProposalStatus) String() string { + return string(s) +} + +// PropStore defines the proposal storage abstraction +type PropStore interface { + // Proposals returns the given paginated proposals + Proposals(offset, count uint64) []Proposal + + // ProposalByID returns the proposal associated with + // the given ID, if any + ProposalByID(id uint64) (Proposal, error) + + // Size returns the number of proposals in + // the proposal store + Size() int +} + +// Proposal is the single proposal abstraction +type Proposal interface { + // Author returns the author of the proposal + Author() std.Address + + // Description returns the description of the proposal + Description() string + + // Status returns the status of the proposal + Status() ProposalStatus + + // Executor returns the proposal executor + Executor() Executor + + // Stats returns the voting stats of the proposal + Stats() Stats + + // IsExpired returns a flag indicating if the proposal expired + IsExpired() bool + + // Render renders the proposal in a readable format + Render() string +} diff --git a/examples/gno.land/p/demo/dao/vote.gno b/examples/gno.land/p/demo/dao/vote.gno new file mode 100644 index 00000000000..94369f41e1b --- /dev/null +++ b/examples/gno.land/p/demo/dao/vote.gno @@ -0,0 +1,69 @@ +package dao + +// NOTE: +// This voting pods will be removed in a future version of the +// p/demo/dao package. A DAO shouldn't have to comply with or define how the voting mechanism works internally; +// it should be viewed as an entity that makes decisions +// +// The extent of "votes being enforced" in this implementation is just in the context +// of types a DAO can use (import), and in the context of "Stats", where +// there is a notion of "Yay", "Nay" and "Abstain" votes. +const ( + VoteAddedEvent = "VoteAdded" // emitted when a vote was cast for a proposal + + VoteAddedIDKey = "proposal-id" + VoteAddedAuthorKey = "author" + VoteAddedOptionKey = "option" +) + +// VoteOption is the limited voting option for a DAO proposal +type VoteOption string + +const ( + YesVote VoteOption = "YES" // Proposal should be accepted + NoVote VoteOption = "NO" // Proposal should be rejected + AbstainVote VoteOption = "ABSTAIN" // Side is not chosen +) + +func (v VoteOption) String() string { + return string(v) +} + +// Stats encompasses the proposal voting stats +type Stats struct { + YayVotes uint64 + NayVotes uint64 + AbstainVotes uint64 + + TotalVotingPower uint64 +} + +// YayPercent returns the percentage (0-100) of the yay votes +// in relation to the total voting power +func (v Stats) YayPercent() uint64 { + return v.YayVotes * 100 / v.TotalVotingPower +} + +// NayPercent returns the percentage (0-100) of the nay votes +// in relation to the total voting power +func (v Stats) NayPercent() uint64 { + return v.NayVotes * 100 / v.TotalVotingPower +} + +// AbstainPercent returns the percentage (0-100) of the abstain votes +// in relation to the total voting power +func (v Stats) AbstainPercent() uint64 { + return v.AbstainVotes * 100 / v.TotalVotingPower +} + +// MissingVotes returns the summed voting power that has not +// participated in proposal voting yet +func (v Stats) MissingVotes() uint64 { + return v.TotalVotingPower - (v.YayVotes + v.NayVotes + v.AbstainVotes) +} + +// MissingVotesPercent returns the percentage (0-100) of the missing votes +// in relation to the total voting power +func (v Stats) MissingVotesPercent() uint64 { + return v.MissingVotes() * 100 / v.TotalVotingPower +} diff --git a/examples/gno.land/p/demo/gnorkle/gnorkle/instance.gno b/examples/gno.land/p/demo/gnorkle/gnorkle/instance.gno index 22746d569a8..eea4782909e 100644 --- a/examples/gno.land/p/demo/gnorkle/gnorkle/instance.gno +++ b/examples/gno.land/p/demo/gnorkle/gnorkle/instance.gno @@ -227,7 +227,7 @@ func (i *Instance) GetFeedDefinitions(forAddress string) (string, error) { first = false buf.Write(taskBytes) - return true + return false }) if err != nil { diff --git a/examples/gno.land/p/demo/json/README.md b/examples/gno.land/p/demo/json/README.md index 86bc9928194..d983333d246 100644 --- a/examples/gno.land/p/demo/json/README.md +++ b/examples/gno.land/p/demo/json/README.md @@ -75,7 +75,6 @@ The converted `Node` type allows you to modify the JSON data or search and extra package main import ( - "fmt" "gno.land/p/demo/json" "gno.land/p/demo/ufmt" ) @@ -100,7 +99,6 @@ Encoding (or Marshaling) is the functionality that converts JSON data represente package main import ( - "fmt" "gno.land/p/demo/json" "gno.land/p/demo/ufmt" ) @@ -133,7 +131,6 @@ Here is an example of finding data with a specific key. For more examples, pleas package main import ( - "fmt" "gno.land/p/demo/json" "gno.land/p/demo/ufmt" ) diff --git a/examples/gno.land/p/demo/json/buffer.gno b/examples/gno.land/p/demo/json/buffer.gno index 23fb53fb0ea..a217ee653f9 100644 --- a/examples/gno.land/p/demo/json/buffer.gno +++ b/examples/gno.land/p/demo/json/buffer.gno @@ -3,7 +3,6 @@ package json import ( "errors" "io" - "strings" "gno.land/p/demo/ufmt" ) @@ -112,28 +111,6 @@ func (b *buffer) skip(bs byte) error { return io.EOF } -// skipAny moves the index until it encounters one of the given set of bytes. -func (b *buffer) skipAny(endTokens map[byte]bool) error { - for b.index < b.length { - if _, exists := endTokens[b.data[b.index]]; exists { - return nil - } - - b.index++ - } - - // build error message - var tokens []string - for token := range endTokens { - tokens = append(tokens, string(token)) - } - - return ufmt.Errorf( - "EOF reached before encountering one of the expected tokens: %s", - strings.Join(tokens, ", "), - ) -} - // skipAndReturnIndex moves the buffer index forward by one and returns the new index. func (b *buffer) skipAndReturnIndex() (int, error) { err := b.step() @@ -165,7 +142,7 @@ func (b *buffer) skipUntil(endTokens map[byte]bool) (int, error) { // significantTokens is a map where the keys are the significant characters in a JSON path. // The values in the map are all true, which allows us to use the map as a set for quick lookups. -var significantTokens = map[byte]bool{ +var significantTokens = [256]bool{ dot: true, // access properties of an object dollarSign: true, // root object atSign: true, // current object @@ -174,7 +151,7 @@ var significantTokens = map[byte]bool{ } // filterTokens stores the filter expression tokens. -var filterTokens = map[byte]bool{ +var filterTokens = [256]bool{ aesterisk: true, // wildcard andSign: true, orSign: true, @@ -186,7 +163,7 @@ func (b *buffer) skipToNextSignificantToken() { for b.index < b.length { current := b.data[b.index] - if _, ok := significantTokens[current]; ok { + if significantTokens[current] { break } @@ -205,7 +182,7 @@ func (b *buffer) backslash() bool { count := 0 for i := b.index - 1; ; i-- { - if i >= b.length || b.data[i] != backSlash { + if b.data[i] != backSlash { break } @@ -220,7 +197,7 @@ func (b *buffer) backslash() bool { } // numIndex holds a map of valid numeric characters -var numIndex = map[byte]bool{ +var numIndex = [256]bool{ '0': true, '1': true, '2': true, @@ -255,11 +232,11 @@ func (b *buffer) pathToken() error { } if err := b.skip(c); err != nil { - return errors.New("unmatched quote in path") + return errUnmatchedQuotePath } if b.index >= b.length { - return errors.New("unmatched quote in path") + return errUnmatchedQuotePath } case c == bracketOpen || c == parenOpen: @@ -269,7 +246,7 @@ func (b *buffer) pathToken() error { case c == bracketClose || c == parenClose: inToken = true if len(stack) == 0 || (c == bracketClose && stack[len(stack)-1] != bracketOpen) || (c == parenClose && stack[len(stack)-1] != parenOpen) { - return errors.New("mismatched bracket or parenthesis") + return errUnmatchedParenthesis } stack = stack[:len(stack)-1] @@ -284,7 +261,7 @@ func (b *buffer) pathToken() error { inToken = true inNumber = true } else if !inToken { - return errors.New("unexpected operator at start of token") + return errInvalidToken } default: @@ -300,7 +277,7 @@ func (b *buffer) pathToken() error { end: if len(stack) != 0 { - return errors.New("unclosed bracket or parenthesis at end of path") + return errUnmatchedParenthesis } if first == b.index { @@ -315,15 +292,15 @@ end: } func pathStateContainsValidPathToken(c byte) bool { - if _, ok := significantTokens[c]; ok { + if significantTokens[c] { return true } - if _, ok := filterTokens[c]; ok { + if filterTokens[c] { return true } - if _, ok := numIndex[c]; ok { + if numIndex[c] { return true } @@ -342,7 +319,7 @@ func (b *buffer) numeric(token bool) error { for ; b.index < b.length; b.index++ { b.class = b.getClasses(doubleQuote) if b.class == __ { - return errors.New("invalid token found while parsing path") + return errInvalidToken } b.state = StateTransitionTable[b.last][b.class] @@ -351,7 +328,7 @@ func (b *buffer) numeric(token bool) error { break } - return errors.New("invalid token found while parsing path") + return errInvalidToken } if b.state < __ { @@ -366,7 +343,7 @@ func (b *buffer) numeric(token bool) error { } if b.last != ZE && b.last != IN && b.last != FR && b.last != E3 { - return errors.New("invalid token found while parsing path") + return errInvalidToken } return nil @@ -407,12 +384,12 @@ func (b *buffer) string(search byte, token bool) error { b.class = b.getClasses(search) if b.class == __ { - return errors.New("invalid token found while parsing path") + return errInvalidToken } b.state = StateTransitionTable[b.last][b.class] if b.state == __ { - return errors.New("invalid token found while parsing path") + return errInvalidToken } if b.state < __ { @@ -431,11 +408,11 @@ func (b *buffer) word(bs []byte) error { max := len(bs) index := 0 - for ; b.index < b.length; b.index++ { + for ; b.index < b.length && index < max; b.index++ { c = b.data[b.index] if c != bs[index] { - return errors.New("invalid token found while parsing path") + return errInvalidToken } index++ @@ -445,7 +422,7 @@ func (b *buffer) word(bs []byte) error { } if index != max { - return errors.New("invalid token found while parsing path") + return errInvalidToken } return nil diff --git a/examples/gno.land/p/demo/json/buffer_test.gno b/examples/gno.land/p/demo/json/buffer_test.gno index b8dce390a61..f4102040be5 100644 --- a/examples/gno.land/p/demo/json/buffer_test.gno +++ b/examples/gno.land/p/demo/json/buffer_test.gno @@ -1,6 +1,8 @@ package json -import "testing" +import ( + "testing" +) func TestBufferCurrent(t *testing.T) { tests := []struct { @@ -242,37 +244,6 @@ func TestBufferSkip(t *testing.T) { } } -func TestBufferSkipAny(t *testing.T) { - tests := []struct { - name string - buffer *buffer - s map[byte]bool - wantErr bool - }{ - { - name: "Skip any valid byte", - buffer: &buffer{data: []byte("test"), length: 4, index: 0}, - s: map[byte]bool{'e': true, 'o': true}, - wantErr: false, - }, - { - name: "Skip any to EOF", - buffer: &buffer{data: []byte("test"), length: 4, index: 0}, - s: map[byte]bool{'x': true, 'y': true}, - wantErr: true, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - err := tt.buffer.skipAny(tt.s) - if (err != nil) != tt.wantErr { - t.Errorf("buffer.skipAny() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} - func TestSkipToNextSignificantToken(t *testing.T) { tests := []struct { name string diff --git a/examples/gno.land/p/demo/json/builder.gno b/examples/gno.land/p/demo/json/builder.gno new file mode 100644 index 00000000000..4693d5ec550 --- /dev/null +++ b/examples/gno.land/p/demo/json/builder.gno @@ -0,0 +1,89 @@ +package json + +type NodeBuilder struct { + node *Node +} + +func Builder() *NodeBuilder { + return &NodeBuilder{node: ObjectNode("", nil)} +} + +func (b *NodeBuilder) WriteString(key, value string) *NodeBuilder { + b.node.AppendObject(key, StringNode("", value)) + return b +} + +func (b *NodeBuilder) WriteNumber(key string, value float64) *NodeBuilder { + b.node.AppendObject(key, NumberNode("", value)) + return b +} + +func (b *NodeBuilder) WriteBool(key string, value bool) *NodeBuilder { + b.node.AppendObject(key, BoolNode("", value)) + return b +} + +func (b *NodeBuilder) WriteNull(key string) *NodeBuilder { + b.node.AppendObject(key, NullNode("")) + return b +} + +func (b *NodeBuilder) WriteObject(key string, fn func(*NodeBuilder)) *NodeBuilder { + nestedBuilder := &NodeBuilder{node: ObjectNode("", nil)} + fn(nestedBuilder) + b.node.AppendObject(key, nestedBuilder.node) + return b +} + +func (b *NodeBuilder) WriteArray(key string, fn func(*ArrayBuilder)) *NodeBuilder { + arrayBuilder := &ArrayBuilder{nodes: []*Node{}} + fn(arrayBuilder) + b.node.AppendObject(key, ArrayNode("", arrayBuilder.nodes)) + return b +} + +func (b *NodeBuilder) Node() *Node { + return b.node +} + +type ArrayBuilder struct { + nodes []*Node +} + +func (ab *ArrayBuilder) WriteString(value string) *ArrayBuilder { + ab.nodes = append(ab.nodes, StringNode("", value)) + return ab +} + +func (ab *ArrayBuilder) WriteNumber(value float64) *ArrayBuilder { + ab.nodes = append(ab.nodes, NumberNode("", value)) + return ab +} + +func (ab *ArrayBuilder) WriteInt(value int) *ArrayBuilder { + return ab.WriteNumber(float64(value)) +} + +func (ab *ArrayBuilder) WriteBool(value bool) *ArrayBuilder { + ab.nodes = append(ab.nodes, BoolNode("", value)) + return ab +} + +func (ab *ArrayBuilder) WriteNull() *ArrayBuilder { + ab.nodes = append(ab.nodes, NullNode("")) + return ab +} + +func (ab *ArrayBuilder) WriteObject(fn func(*NodeBuilder)) *ArrayBuilder { + nestedBuilder := &NodeBuilder{node: ObjectNode("", nil)} + fn(nestedBuilder) + ab.nodes = append(ab.nodes, nestedBuilder.node) + return ab +} + +func (ab *ArrayBuilder) WriteArray(fn func(*ArrayBuilder)) *ArrayBuilder { + nestedArrayBuilder := &ArrayBuilder{nodes: []*Node{}} + fn(nestedArrayBuilder) + ab.nodes = append(ab.nodes, ArrayNode("", nestedArrayBuilder.nodes)) + return ab +} diff --git a/examples/gno.land/p/demo/json/builder_test.gno b/examples/gno.land/p/demo/json/builder_test.gno new file mode 100644 index 00000000000..4c882d0d6c8 --- /dev/null +++ b/examples/gno.land/p/demo/json/builder_test.gno @@ -0,0 +1,103 @@ +package json + +import ( + "testing" +) + +func TestNodeBuilder(t *testing.T) { + tests := []struct { + name string + build func() *Node + expected string + }{ + { + name: "plain object", + build: func() *Node { + return Builder(). + WriteString("name", "Alice"). + WriteNumber("age", 30). + WriteBool("is_student", false). + Node() + }, + expected: `{"name":"Alice","age":30,"is_student":false}`, + }, + { + name: "nested object", + build: func() *Node { + return Builder(). + WriteString("name", "Alice"). + WriteObject("address", func(b *NodeBuilder) { + b.WriteString("city", "New York"). + WriteNumber("zipcode", 10001) + }). + Node() + }, + expected: `{"name":"Alice","address":{"city":"New York","zipcode":10001}}`, + }, + { + name: "null node", + build: func() *Node { + return Builder().WriteNull("foo").Node() + }, + expected: `{"foo":null}`, + }, + { + name: "array node", + build: func() *Node { + return Builder(). + WriteArray("items", func(ab *ArrayBuilder) { + ab.WriteString("item1"). + WriteString("item2"). + WriteString("item3") + }). + Node() + }, + expected: `{"items":["item1","item2","item3"]}`, + }, + { + name: "array with objects", + build: func() *Node { + return Builder(). + WriteArray("users", func(ab *ArrayBuilder) { + ab.WriteObject(func(b *NodeBuilder) { + b.WriteString("name", "Bob"). + WriteNumber("age", 25) + }). + WriteObject(func(b *NodeBuilder) { + b.WriteString("name", "Carol"). + WriteNumber("age", 27) + }) + }). + Node() + }, + expected: `{"users":[{"name":"Bob","age":25},{"name":"Carol","age":27}]}`, + }, + { + name: "array with various types", + build: func() *Node { + return Builder(). + WriteArray("values", func(ab *ArrayBuilder) { + ab.WriteString("item1"). + WriteNumber(123). + WriteBool(true). + WriteNull() + }). + Node() + }, + expected: `{"values":["item1",123,true,null]}`, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + node := tt.build() + value, err := Marshal(node) + if err != nil { + t.Errorf("unexpected error: %s", err) + } + if string(value) != tt.expected { + t.Errorf("expected %s, got %s", tt.expected, string(value)) + } + }) + } +} diff --git a/examples/gno.land/p/demo/json/decode_test.gno b/examples/gno.land/p/demo/json/decode_test.gno index 8aad07169f2..dc92f1f84cd 100644 --- a/examples/gno.land/p/demo/json/decode_test.gno +++ b/examples/gno.land/p/demo/json/decode_test.gno @@ -8,8 +8,8 @@ import ( type testNode struct { name string input []byte - _type ValueType value []byte + _type ValueType } func simpleValid(test *testNode, t *testing.T) { diff --git a/examples/gno.land/p/demo/json/eisel_lemire/gno.mod b/examples/gno.land/p/demo/json/eisel_lemire/gno.mod deleted file mode 100644 index d6670de82e2..00000000000 --- a/examples/gno.land/p/demo/json/eisel_lemire/gno.mod +++ /dev/null @@ -1 +0,0 @@ -module gno.land/p/demo/json/eisel_lemire diff --git a/examples/gno.land/p/demo/json/encode.gno b/examples/gno.land/p/demo/json/encode.gno index be90d7aa73d..55828650e22 100644 --- a/examples/gno.land/p/demo/json/encode.gno +++ b/examples/gno.land/p/demo/json/encode.gno @@ -3,10 +3,8 @@ package json import ( "bytes" "errors" - "math" "strconv" - "gno.land/p/demo/json/ryu" "gno.land/p/demo/ufmt" ) @@ -44,17 +42,8 @@ func Marshal(node *Node) ([]byte, error) { return nil, err } - // ufmt does not support %g. by doing so, we need to check if the number is an integer - // after then, apply the correct format for each float and integer numbers. - if math.Mod(nVal, 1.0) == 0 { - // must convert float to integer. otherwise it will be overflowed. - num := ufmt.Sprintf("%d", int(nVal)) - buf.WriteString(num) - } else { - // use ryu algorithm to convert float to string - num := ryu.FormatFloat64(nVal) - buf.WriteString(num) - } + num := strconv.FormatFloat(nVal, 'f', -1, 64) + buf.WriteString(num) case String: sVal, err = node.GetString() diff --git a/examples/gno.land/p/demo/json/encode_test.gno b/examples/gno.land/p/demo/json/encode_test.gno index e8e53993b5c..831a9e0e0a2 100644 --- a/examples/gno.land/p/demo/json/encode_test.gno +++ b/examples/gno.land/p/demo/json/encode_test.gno @@ -37,10 +37,9 @@ func TestMarshal_Primitive(t *testing.T) { name: "42", node: NumberNode("", 42), }, - // TODO: fix output for not to use scientific notation { - name: "1.005e+02", - node: NumberNode("", 100.5), + name: "3.14", + node: NumberNode("", 3.14), }, { name: `[1,2,3]`, diff --git a/examples/gno.land/p/demo/json/errors.gno b/examples/gno.land/p/demo/json/errors.gno new file mode 100644 index 00000000000..e0836dccdff --- /dev/null +++ b/examples/gno.land/p/demo/json/errors.gno @@ -0,0 +1,34 @@ +package json + +import "errors" + +var ( + errNilNode = errors.New("node is nil") + errNotArrayNode = errors.New("node is not array") + errNotBoolNode = errors.New("node is not boolean") + errNotNullNode = errors.New("node is not null") + errNotNumberNode = errors.New("node is not number") + errNotObjectNode = errors.New("node is not object") + errNotStringNode = errors.New("node is not string") + errInvalidToken = errors.New("invalid token") + errIndexNotFound = errors.New("index not found") + errInvalidAppend = errors.New("can't append value to non-appendable node") + errInvalidAppendCycle = errors.New("appending value to itself or its children or parents will cause a cycle") + errInvalidEscapeSequence = errors.New("invalid escape sequence") + errInvalidStringValue = errors.New("invalid string value") + errEmptyBooleanNode = errors.New("boolean node is empty") + errEmptyStringNode = errors.New("string node is empty") + errKeyRequired = errors.New("key is required for object") + errUnmatchedParenthesis = errors.New("mismatched bracket or parenthesis") + errUnmatchedQuotePath = errors.New("unmatched quote in path") +) + +var ( + errInvalidStringInput = errors.New("invalid string input") + errMalformedBooleanValue = errors.New("malformed boolean value") + errEmptyByteSlice = errors.New("empty byte slice") + errInvalidExponentValue = errors.New("invalid exponent value") + errNonDigitCharacters = errors.New("non-digit characters found") + errNumericRangeExceeded = errors.New("numeric value exceeds the range limit") + errMultipleDecimalPoints = errors.New("multiple decimal points found") +) diff --git a/examples/gno.land/p/demo/json/escape.gno b/examples/gno.land/p/demo/json/escape.gno index 5a834068127..ee3e4a79855 100644 --- a/examples/gno.land/p/demo/json/escape.gno +++ b/examples/gno.land/p/demo/json/escape.gno @@ -1,8 +1,6 @@ package json import ( - "bytes" - "errors" "unicode/utf8" ) @@ -13,6 +11,9 @@ const ( surrogateEnd = 0xDFFF basicMultilingualPlaneOffset = 0xFFFF badHex = -1 + + singleUnicodeEscapeLen = 6 + surrogatePairLen = 12 ) var hexLookupTable = [256]int{ @@ -42,48 +43,32 @@ func h2i(c byte) int { // // it returns the processed slice and any error encountered during the Unescape operation. func Unescape(input, output []byte) ([]byte, error) { - // find the index of the first backslash in the input slice. - firstBackslash := bytes.IndexByte(input, backSlash) - if firstBackslash == -1 { - return input, nil - } - - // ensure the output slice has enough capacity to hold the result. + // ensure the output slice has enough capacity to hold the input slice. inputLen := len(input) if cap(output) < inputLen { output = make([]byte, inputLen) } - output = output[:inputLen] - copy(output, input[:firstBackslash]) - - input = input[firstBackslash:] - buf := output[firstBackslash:] - - for len(input) > 0 { - inLen, bufLen, err := processEscapedUTF8(input, buf) - if err != nil { - return nil, err - } - - input = input[inLen:] // the number of bytes consumed in the input - buf = buf[bufLen:] // the number of bytes written to buf + inPos, outPos := 0, 0 - // find the next backslash in the remaining input - nextBackslash := bytes.IndexByte(input, backSlash) - if nextBackslash == -1 { - copy(buf, input) - buf = buf[len(input):] - break + for inPos < len(input) { + c := input[inPos] + if c != backSlash { + output[outPos] = c + inPos++ + outPos++ + } else { + // process escape sequence + inLen, outLen, err := processEscapedUTF8(input[inPos:], output[outPos:]) + if err != nil { + return nil, err + } + inPos += inLen + outPos += outLen } - - copy(buf, input[:nextBackslash]) - - input = input[nextBackslash:] - buf = buf[nextBackslash:] } - return output[:len(output)-len(buf)], nil + return output[:outPos], nil } // isSurrogatePair returns true if the rune is a surrogate pair. @@ -94,6 +79,16 @@ func isSurrogatePair(r rune) bool { return highSurrogateOffset <= r && r <= surrogateEnd } +// isHighSurrogate checks if the rune is a high surrogate (U+D800 to U+DBFF). +func isHighSurrogate(r rune) bool { + return r >= highSurrogateOffset && r <= 0xDBFF +} + +// isLowSurrogate checks if the rune is a low surrogate (U+DC00 to U+DFFF). +func isLowSurrogate(r rune) bool { + return r >= lowSurrogateOffset && r <= surrogateEnd +} + // combineSurrogates reconstruct the original unicode code points in the // supplemental plane by combinin the high and low surrogate. // @@ -122,28 +117,41 @@ func decodeSingleUnicodeEscape(b []byte) (rune, bool) { } // decodeUnicodeEscape decodes a Unicode escape sequence from a byte slice. +// It handles both single Unicode escape sequences and surrogate pairs. func decodeUnicodeEscape(b []byte) (rune, int) { + // decode the first Unicode escape sequence. r, ok := decodeSingleUnicodeEscape(b) if !ok { return utf8.RuneError, -1 } - // determine valid unicode escapes within the BMP + // if the rune is within the BMP and not a surrogate, return it if r <= basicMultilingualPlaneOffset && !isSurrogatePair(r) { return r, 6 } - // Decode the following escape sequence to verify a UTF-16 susergate pair. - r2, ok := decodeSingleUnicodeEscape(b[6:]) - if !ok { + if !isHighSurrogate(r) { + // invalid surrogate pair. return utf8.RuneError, -1 } - if r2 < lowSurrogateOffset { + // if the rune is a high surrogate, need to decode the next escape sequence. + + // ensure there are enough bytes for the next escape sequence. + if len(b) < surrogatePairLen { return utf8.RuneError, -1 } - - return combineSurrogates(r, r2), 12 + // decode the second Unicode escape sequence. + r2, ok := decodeSingleUnicodeEscape(b[singleUnicodeEscapeLen:]) + if !ok { + return utf8.RuneError, -1 + } + // check if the second rune is a low surrogate. + if isLowSurrogate(r2) { + combined := combineSurrogates(r, r2) + return combined, surrogatePairLen + } + return utf8.RuneError, -1 } var escapeByteSet = [256]byte{ @@ -165,7 +173,6 @@ func Unquote(s []byte, border byte) (string, bool) { } // unquoteBytes takes a byte slice and unquotes it by removing -// TODO: consider to move this function to the strconv package. func unquoteBytes(s []byte, border byte) ([]byte, bool) { if len(s) < 2 || s[0] != border || s[len(s)-1] != border { return nil, false @@ -259,21 +266,12 @@ func unquoteBytes(s []byte, border byte) ([]byte, bool) { return b[:w], true } -// processEscapedUTF8 processes the escape sequence in the given byte slice and -// and converts them to UTF-8 characters. The function returns the length of the processed input and output. -// -// The input 'in' must contain the escape sequence to be processed, -// and 'out' provides a space to store the converted characters. -// -// The function returns (input length, output length) if the escape sequence is correct. -// Unicode escape sequences (e.g. \uXXXX) are decoded to UTF-8, other default escape sequences are -// converted to their corresponding special characters (e.g. \n -> newline). -// -// If the escape sequence is invalid, or if 'in' does not completely enclose the escape sequence, -// function returns (-1, -1) to indicate an error. +// processEscapedUTF8 converts escape sequences to UTF-8 characters. +// It decodes Unicode escape sequences (\uXXXX) to UTF-8 and +// converts standard escape sequences (e.g., \n) to their corresponding special characters. func processEscapedUTF8(in, out []byte) (int, int, error) { if len(in) < 2 || in[0] != backSlash { - return -1, -1, errors.New("invalid escape sequence") + return -1, -1, errInvalidEscapeSequence } escapeSeqLen := 2 @@ -282,7 +280,7 @@ func processEscapedUTF8(in, out []byte) (int, int, error) { if escapeChar != 'u' { val := escapeByteSet[escapeChar] if val == 0 { - return -1, -1, errors.New("invalid escape sequence") + return -1, -1, errInvalidEscapeSequence } out[0] = val @@ -291,7 +289,7 @@ func processEscapedUTF8(in, out []byte) (int, int, error) { r, size := decodeUnicodeEscape(in) if size == -1 { - return -1, -1, errors.New("invalid escape sequence") + return -1, -1, errInvalidEscapeSequence } outLen := utf8.EncodeRune(out, r) diff --git a/examples/gno.land/p/demo/json/escape_test.gno b/examples/gno.land/p/demo/json/escape_test.gno index 40c118d93ce..0e2e696e83c 100644 --- a/examples/gno.land/p/demo/json/escape_test.gno +++ b/examples/gno.land/p/demo/json/escape_test.gno @@ -103,24 +103,25 @@ func TestDecodeSingleUnicodeEscape(t *testing.T) { } func TestDecodeUnicodeEscape(t *testing.T) { - testCases := []struct { - input string + tests := []struct { + input []byte expected rune size int }{ - {"\\u0041", 'A', 6}, - {"\\u03B1", 'α', 6}, - {"\\u1F600", 0x1F60, 6}, - {"\\uD830\\uDE03", 0x1C203, 12}, - {"\\uD800\\uDC00", 0x00010000, 12}, - - {"\\u004", utf8.RuneError, -1}, - {"\\uXYZW", utf8.RuneError, -1}, - {"\\uD83D\\u0041", utf8.RuneError, -1}, + {[]byte(`\u0041`), 'A', 6}, + {[]byte(`\uD83D\uDE00`), 0x1F600, 12}, // 😀 + {[]byte(`\uD834\uDD1E`), 0x1D11E, 12}, // 𝄞 + {[]byte(`\uFFFF`), '\uFFFF', 6}, + {[]byte(`\uXYZW`), utf8.RuneError, -1}, + {[]byte(`\uD800`), utf8.RuneError, -1}, // single high surrogate + {[]byte(`\uDC00`), utf8.RuneError, -1}, // single low surrogate + {[]byte(`\uD800\uDC00`), 0x10000, 12}, // First code point above U+FFFF + {[]byte(`\uDBFF\uDFFF`), 0x10FFFF, 12}, // Maximum code point + {[]byte(`\uD83D\u0041`), utf8.RuneError, -1}, // invalid surrogate pair } - for _, tc := range testCases { - r, size := decodeUnicodeEscape([]byte(tc.input)) + for _, tc := range tests { + r, size := decodeUnicodeEscape(tc.input) if r != tc.expected || size != tc.size { t.Errorf("decodeUnicodeEscape(%q) = (%U, %d); want (%U, %d)", tc.input, r, size, tc.expected, tc.size) } @@ -128,7 +129,7 @@ func TestDecodeUnicodeEscape(t *testing.T) { } func TestUnescapeToUTF8(t *testing.T) { - testCases := []struct { + tests := []struct { input []byte expectedIn int expectedOut int @@ -150,7 +151,7 @@ func TestUnescapeToUTF8(t *testing.T) { {[]byte(`\uD83D\u0041`), -1, -1, true}, // invalid unicode escape sequence } - for _, tc := range testCases { + for _, tc := range tests { input := make([]byte, len(tc.input)) copy(input, tc.input) output := make([]byte, utf8.UTFMax) @@ -166,23 +167,32 @@ func TestUnescapeToUTF8(t *testing.T) { } func TestUnescape(t *testing.T) { - testCases := []struct { + tests := []struct { name string input []byte expected []byte + isError bool }{ - {"NoEscape", []byte("hello world"), []byte("hello world")}, - {"SingleEscape", []byte("hello\\nworld"), []byte("hello\nworld")}, - {"MultipleEscapes", []byte("line1\\nline2\\r\\nline3"), []byte("line1\nline2\r\nline3")}, - {"UnicodeEscape", []byte("snowman:\\u2603"), []byte("snowman:\u2603")}, - {"Complex", []byte("tc\\n\\u2603\\r\\nend"), []byte("tc\n\u2603\r\nend")}, + {"NoEscape", []byte("hello world"), []byte("hello world"), false}, + {"SingleEscape", []byte("hello\\nworld"), []byte("hello\nworld"), false}, + {"MultipleEscapes", []byte("line1\\nline2\\r\\nline3"), []byte("line1\nline2\r\nline3"), false}, + {"UnicodeEscape", []byte("snowman:\\u2603"), []byte("snowman:\u2603"), false}, + {"SurrogatePair", []byte("emoji:\\uD83D\\uDE00"), []byte("emoji:😀"), false}, + {"InvalidEscape", []byte("hello\\xworld"), nil, true}, + {"IncompleteUnicode", []byte("incomplete:\\u123"), nil, true}, + {"InvalidSurrogatePair", []byte("invalid:\\uD83D\\u0041"), nil, true}, } - for _, tc := range testCases { + for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - output, _ := Unescape(tc.input, make([]byte, len(tc.input)+10)) - if !bytes.Equal(output, tc.expected) { - t.Errorf("unescape(%q) = %q; want %q", tc.input, output, tc.expected) + output := make([]byte, len(tc.input)*2) // Allocate extra space for possible expansion + result, err := Unescape(tc.input, output) + if (err != nil) != tc.isError { + t.Errorf("Unescape(%q) error = %v; want error = %v", tc.input, err, tc.isError) + } + + if !tc.isError && !bytes.Equal(result, tc.expected) { + t.Errorf("Unescape(%q) = %q; want %q", tc.input, result, tc.expected) } }) } @@ -206,6 +216,7 @@ func TestUnquoteBytes(t *testing.T) { {[]byte("\"\\u0041\""), '"', []byte("A"), true}, {[]byte(`"Hello, 世界"`), '"', []byte("Hello, 世界"), true}, {[]byte(`"Hello, \x80"`), '"', nil, false}, + {[]byte(`"invalid surrogate: \uD83D\u0041"`), '"', nil, false}, } for _, tc := range tests { diff --git a/examples/gno.land/p/demo/json/gno.mod b/examples/gno.land/p/demo/json/gno.mod index 8a380644acc..ef794458c56 100644 --- a/examples/gno.land/p/demo/json/gno.mod +++ b/examples/gno.land/p/demo/json/gno.mod @@ -1,7 +1,3 @@ module gno.land/p/demo/json -require ( - gno.land/p/demo/json/eisel_lemire v0.0.0-latest - gno.land/p/demo/json/ryu v0.0.0-latest - gno.land/p/demo/ufmt v0.0.0-latest -) +require gno.land/p/demo/ufmt v0.0.0-latest diff --git a/examples/gno.land/p/demo/json/indent.gno b/examples/gno.land/p/demo/json/indent.gno index cdcfd4524ee..cdf9d5e976f 100644 --- a/examples/gno.land/p/demo/json/indent.gno +++ b/examples/gno.land/p/demo/json/indent.gno @@ -9,21 +9,7 @@ import ( // A factor no higher than 2 ensures that wasted space never exceeds 50%. const indentGrowthFactor = 2 -// IndentJSON takes a JSON byte slice and a string for indentation, -// then formats the JSON according to the specified indent string. -// This function applies indentation rules as follows: -// -// 1. For top-level arrays and objects, no additional indentation is applied. -// -// 2. For nested structures like arrays within arrays or objects, indentation increases. -// -// 3. Indentation is applied after opening brackets ('[' or '{') and before closing brackets (']' or '}'). -// -// 4. Commas and colons are handled appropriately to maintain valid JSON format. -// -// 5. Nested arrays within objects or arrays receive new lines and indentation based on their depth level. -// -// The function returns the formatted JSON as a byte slice and an error if any issues occurred during formatting. +// IndentJSON formats the JSON data with the specified indentation. func Indent(data []byte, indent string) ([]byte, error) { var ( out bytes.Buffer diff --git a/examples/gno.land/p/demo/json/node.gno b/examples/gno.land/p/demo/json/node.gno index 1e71a101e62..c917150bc3d 100644 --- a/examples/gno.land/p/demo/json/node.gno +++ b/examples/gno.land/p/demo/json/node.gno @@ -44,7 +44,7 @@ func NewNode(prev *Node, b *buffer, typ ValueType, key **string) (*Node, error) prev.next[strconv.Itoa(size)] = curr } else if prev.IsObject() { if key == nil { - return nil, errors.New("key is required for object") + return nil, errKeyRequired } prev.next[**key] = curr @@ -88,7 +88,7 @@ func (n *Node) HasKey(key string) bool { // GetKey returns the value of the given key from the current object node. func (n *Node) GetKey(key string) (*Node, error) { if n == nil { - return nil, errors.New("node is nil") + return nil, errNilNode } if n.Type() != Object { @@ -174,7 +174,7 @@ func (n *Node) Value() (value interface{}, err error) { return nil, nil case Number: - value, err = ParseFloatLiteral(n.source()) + value, err = strconv.ParseFloat(string(n.source()), 64) if err != nil { return nil, err } @@ -185,14 +185,14 @@ func (n *Node) Value() (value interface{}, err error) { var ok bool value, ok = Unquote(n.source(), doubleQuote) if !ok { - return "", errors.New("invalid string value") + return "", errInvalidStringValue } n.value = value case Boolean: if len(n.source()) == 0 { - return nil, errors.New("empty boolean value") + return nil, errEmptyBooleanNode } b := n.source()[0] @@ -319,11 +319,11 @@ func (n *Node) MustIndex(expectIdx int) *Node { // if the index is negative, it returns the index is from the end of the array. func (n *Node) GetIndex(idx int) (*Node, error) { if n == nil { - return nil, errors.New("node is nil") + return nil, errNilNode } if !n.IsArray() { - return nil, errors.New("node is not array") + return nil, errNotArrayNode } if idx > n.Size() { @@ -336,7 +336,7 @@ func (n *Node) GetIndex(idx int) (*Node, error) { child, ok := n.next[strconv.Itoa(idx)] if !ok { - return nil, errors.New("index not found") + return nil, errIndexNotFound } return child, nil @@ -556,11 +556,11 @@ func (n *Node) root() *Node { // } func (n *Node) GetNull() (interface{}, error) { if n == nil { - return nil, errors.New("node is nil") + return nil, errNilNode } if !n.IsNull() { - return nil, errors.New("node is not null") + return nil, errNotNullNode } return nil, nil @@ -590,11 +590,11 @@ func (n *Node) MustNull() interface{} { // println(val) // 10.5 func (n *Node) GetNumeric() (float64, error) { if n == nil { - return 0, errors.New("node is nil") + return 0, errNilNode } if n.nodeType != Number { - return 0, errors.New("node is not number") + return 0, errNotNumberNode } val, err := n.Value() @@ -604,7 +604,7 @@ func (n *Node) GetNumeric() (float64, error) { v, ok := val.(float64) if !ok { - return 0, errors.New("node is not number") + return 0, errNotNumberNode } return v, nil @@ -639,11 +639,11 @@ func (n *Node) MustNumeric() float64 { // println(str) // "foo" func (n *Node) GetString() (string, error) { if n == nil { - return "", errors.New("string node is empty") + return "", errEmptyStringNode } if !n.IsString() { - return "", errors.New("node type is not string") + return "", errNotStringNode } val, err := n.Value() @@ -653,7 +653,7 @@ func (n *Node) GetString() (string, error) { v, ok := val.(string) if !ok { - return "", errors.New("node is not string") + return "", errNotStringNode } return v, nil @@ -683,11 +683,11 @@ func (n *Node) MustString() string { // println(val) // true func (n *Node) GetBool() (bool, error) { if n == nil { - return false, errors.New("node is nil") + return false, errNilNode } if n.nodeType != Boolean { - return false, errors.New("node is not boolean") + return false, errNotBoolNode } val, err := n.Value() @@ -697,7 +697,7 @@ func (n *Node) GetBool() (bool, error) { v, ok := val.(bool) if !ok { - return false, errors.New("node is not boolean") + return false, errNotBoolNode } return v, nil @@ -732,11 +732,11 @@ func (n *Node) MustBool() bool { // result: "foo", 1 func (n *Node) GetArray() ([]*Node, error) { if n == nil { - return nil, errors.New("node is nil") + return nil, errNilNode } if n.nodeType != Array { - return nil, errors.New("node is not array") + return nil, errNotArrayNode } val, err := n.Value() @@ -746,7 +746,7 @@ func (n *Node) GetArray() ([]*Node, error) { v, ok := val.([]*Node) if !ok { - return nil, errors.New("node is not array") + return nil, errNotArrayNode } return v, nil @@ -788,7 +788,7 @@ func (n *Node) MustArray() []*Node { // result: ["bar", "baz", 1, "foo"] func (n *Node) AppendArray(value ...*Node) error { if !n.IsArray() { - return errors.New("can't append value to non-array node") + return errInvalidAppend } for _, val := range value { @@ -836,11 +836,11 @@ func (n *Node) ArrayEach(callback func(i int, target *Node)) { // result: map[string]*Node{"key": StringNode("key", "value")} func (n *Node) GetObject() (map[string]*Node, error) { if n == nil { - return nil, errors.New("node is nil") + return nil, errNilNode } if !n.IsObject() { - return nil, errors.New("node is not object") + return nil, errNotObjectNode } val, err := n.Value() @@ -850,7 +850,7 @@ func (n *Node) GetObject() (map[string]*Node, error) { v, ok := val.(map[string]*Node) if !ok { - return nil, errors.New("node is not object") + return nil, errNotObjectNode } return v, nil @@ -873,7 +873,7 @@ func (n *Node) MustObject() map[string]*Node { // If the current node is not object type, it returns an error. func (n *Node) AppendObject(key string, value *Node) error { if !n.IsObject() { - return errors.New("can't append value to non-object node") + return errInvalidAppend } if err := n.append(&key, value); err != nil { @@ -1003,7 +1003,7 @@ func (n *Node) dropIndex(idx int) { // append is a helper function to append the given value to the current container type node. func (n *Node) append(key *string, val *Node) error { if n.isSameOrParentNode(val) { - return errors.New("can't append same or parent node") + return errInvalidAppendCycle } if val.prev != nil { diff --git a/examples/gno.land/p/demo/json/parser.gno b/examples/gno.land/p/demo/json/parser.gno index 9a2c3a8c817..bae06cb3789 100644 --- a/examples/gno.land/p/demo/json/parser.gno +++ b/examples/gno.land/p/demo/json/parser.gno @@ -2,27 +2,22 @@ package json import ( "bytes" - "errors" - "strconv" - - el "gno.land/p/demo/json/eisel_lemire" ) const ( - absMinInt64 = 1 << 63 - maxInt64 = absMinInt64 - 1 - maxUint64 = 1<<64 - 1 + unescapeStackBufSize = 64 + absMinInt64 = 1 << 63 + maxInt64 = absMinInt64 - 1 + maxUint64 = 1<<64 - 1 ) -const unescapeStackBufSize = 64 - // PaseStringLiteral parses a string from the given byte slice. func ParseStringLiteral(data []byte) (string, error) { var buf [unescapeStackBufSize]byte bf, err := Unescape(data, buf[:]) if err != nil { - return "", errors.New("invalid string input found while parsing string value") + return "", errInvalidStringInput } return string(bf), nil @@ -36,150 +31,6 @@ func ParseBoolLiteral(data []byte) (bool, error) { case bytes.Equal(data, falseLiteral): return false, nil default: - return false, errors.New("JSON Error: malformed boolean value found while parsing boolean value") - } -} - -// PaseFloatLiteral parses a float64 from the given byte slice. -// -// It utilizes double-precision (64-bit) floating-point format as defined -// by the IEEE 754 standard, providing a decimal precision of approximately 15 digits. -func ParseFloatLiteral(bytes []byte) (float64, error) { - if len(bytes) == 0 { - return -1, errors.New("JSON Error: empty byte slice found while parsing float value") - } - - neg, bytes := trimNegativeSign(bytes) - - var exponentPart []byte - for i, c := range bytes { - if lower(c) == 'e' { - exponentPart = bytes[i+1:] - bytes = bytes[:i] - break - } - } - - man, exp10, err := extractMantissaAndExp10(bytes) - if err != nil { - return -1, err - } - - if len(exponentPart) > 0 { - exp, err := strconv.Atoi(string(exponentPart)) - if err != nil { - return -1, errors.New("JSON Error: invalid exponent value found while parsing float value") - } - exp10 += exp - } - - // for fast float64 conversion - f, success := el.EiselLemire64(man, exp10, neg) - if !success { - return 0, nil - } - - return f, nil -} - -func ParseIntLiteral(bytes []byte) (int64, error) { - if len(bytes) == 0 { - return 0, errors.New("JSON Error: empty byte slice found while parsing integer value") - } - - neg, bytes := trimNegativeSign(bytes) - - var n uint64 = 0 - for _, c := range bytes { - if notDigit(c) { - return 0, errors.New("JSON Error: non-digit characters found while parsing integer value") - } - - if n > maxUint64/10 { - return 0, errors.New("JSON Error: numeric value exceeds the range limit") - } - - n *= 10 - - n1 := n + uint64(c-'0') - if n1 < n { - return 0, errors.New("JSON Error: numeric value exceeds the range limit") - } - - n = n1 - } - - if n > maxInt64 { - if neg && n == absMinInt64 { - return -absMinInt64, nil - } - - return 0, errors.New("JSON Error: numeric value exceeds the range limit") + return false, errMalformedBooleanValue } - - if neg { - return -int64(n), nil - } - - return int64(n), nil -} - -// extractMantissaAndExp10 parses a byte slice representing a decimal number and extracts the mantissa and the exponent of its base-10 representation. -// It iterates through the bytes, constructing the mantissa by treating each byte as a digit. -// If a decimal point is encountered, the function keeps track of the position of the decimal point to calculate the exponent. -// The function ensures that: -// - The number contains at most one decimal point. -// - All characters in the byte slice are digits or a single decimal point. -// - The resulting mantissa does not overflow a uint64. -func extractMantissaAndExp10(bytes []byte) (uint64, int, error) { - var ( - man uint64 - exp10 int - decimalFound bool - ) - - for _, c := range bytes { - if c == dot { - if decimalFound { - return 0, 0, errors.New("JSON Error: multiple decimal points found while parsing float value") - } - decimalFound = true - continue - } - - if notDigit(c) { - return 0, 0, errors.New("JSON Error: non-digit characters found while parsing integer value") - } - - digit := uint64(c - '0') - - if man > (maxUint64-digit)/10 { - return 0, 0, errors.New("JSON Error: numeric value exceeds the range limit") - } - - man = man*10 + digit - - if decimalFound { - exp10-- - } - } - - return man, exp10, nil -} - -func trimNegativeSign(bytes []byte) (bool, []byte) { - if bytes[0] == minus { - return true, bytes[1:] - } - - return false, bytes -} - -func notDigit(c byte) bool { - return (c & 0xF0) != 0x30 -} - -// lower converts a byte to lower case if it is an uppercase letter. -func lower(c byte) byte { - return c | 0x20 } diff --git a/examples/gno.land/p/demo/json/parser_test.gno b/examples/gno.land/p/demo/json/parser_test.gno index 078aa048a61..a05e313f67b 100644 --- a/examples/gno.land/p/demo/json/parser_test.gno +++ b/examples/gno.land/p/demo/json/parser_test.gno @@ -64,125 +64,3 @@ func TestParseBoolLiteral(t *testing.T) { } } } - -func TestParseFloatLiteral(t *testing.T) { - tests := []struct { - input string - expected float64 - }{ - {"123", 123}, - {"-123", -123}, - {"123.456", 123.456}, - {"-123.456", -123.456}, - {"12345678.1234567890", 12345678.1234567890}, - {"-12345678.09123456789", -12345678.09123456789}, - {"0.123", 0.123}, - {"-0.123", -0.123}, - {"", -1}, - {"abc", -1}, - {"123.45.6", -1}, - {"999999999999999999999", -1}, - } - - for _, tt := range tests { - t.Run(tt.input, func(t *testing.T) { - got, _ := ParseFloatLiteral([]byte(tt.input)) - if got != tt.expected { - t.Errorf("ParseFloatLiteral(%s): got %v, want %v", tt.input, got, tt.expected) - } - }) - } -} - -func TestParseFloatWithScientificNotation(t *testing.T) { - tests := []struct { - input string - expected float64 - }{ - {"1e6", 1000000}, - {"1E6", 1000000}, - {"1.23e10", 1.23e10}, - {"1.23E10", 1.23e10}, - {"-1.23e10", -1.23e10}, - {"-1.23E10", -1.23e10}, - {"2.45e-8", 2.45e-8}, - {"2.45E-8", 2.45e-8}, - {"-2.45e-8", -2.45e-8}, - {"-2.45E-8", -2.45e-8}, - {"5e0", 5}, - {"-5e0", -5}, - {"5E+0", 5}, - {"5e+1", 50}, - {"1e-1", 0.1}, - {"1E-1", 0.1}, - {"-1e-1", -0.1}, - {"-1E-1", -0.1}, - } - - for _, tt := range tests { - t.Run(tt.input, func(t *testing.T) { - got, err := ParseFloatLiteral([]byte(tt.input)) - if got != tt.expected { - t.Errorf("ParseFloatLiteral(%s): got %v, want %v", tt.input, got, tt.expected) - } - - if err != nil { - t.Errorf("ParseFloatLiteral(%s): got error %v", tt.input, err) - } - }) - } -} - -func TestParseFloat_May_Interoperability_Problem(t *testing.T) { - tests := []struct { - input string - shouldErr bool - }{ - {"3.141592653589793238462643383279", true}, - {"1E400", false}, // TODO: should error - } - - for _, tt := range tests { - t.Run(tt.input, func(t *testing.T) { - _, err := ParseFloatLiteral([]byte(tt.input)) - if tt.shouldErr && err == nil { - t.Errorf("ParseFloatLiteral(%s): expected error, but not error", tt.input) - } - }) - } -} - -func TestParseIntLiteral(t *testing.T) { - tests := []struct { - input string - expected int64 - }{ - {"0", 0}, - {"1", 1}, - {"-1", -1}, - {"12345", 12345}, - {"-12345", -12345}, - {"9223372036854775807", 9223372036854775807}, - {"-9223372036854775808", -9223372036854775808}, - {"-92233720368547758081", 0}, - {"18446744073709551616", 0}, - {"9223372036854775808", 0}, - {"-9223372036854775809", 0}, - {"", 0}, - {"abc", 0}, - {"12345x", 0}, - {"123e5", 0}, - {"9223372036854775807x", 0}, - {"27670116110564327410", 0}, - {"-27670116110564327410", 0}, - } - - for _, tt := range tests { - t.Run(tt.input, func(t *testing.T) { - got, _ := ParseIntLiteral([]byte(tt.input)) - if got != tt.expected { - t.Errorf("ParseIntLiteral(%s): got %v, want %v", tt.input, got, tt.expected) - } - }) - } -} diff --git a/examples/gno.land/p/demo/json/ryu/License b/examples/gno.land/p/demo/json/ryu/License deleted file mode 100644 index 55beeadce54..00000000000 --- a/examples/gno.land/p/demo/json/ryu/License +++ /dev/null @@ -1,21 +0,0 @@ -# Apache License - -Copyright 2018 Ulf Adams -Modifications copyright 2019 Caleb Spare - -The contents of this file may be used under the terms of the Apache License, -Version 2.0. - - (See accompanying file LICENSE or copy at - ) - -Unless required by applicable law or agreed to in writing, this software -is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, either express or implied. - -The code in this file is part of a Go translation of the C code originally written by -Ulf Adams, which can be found at . The original source -code is licensed under the Apache License 2.0. This code is a derivative work thereof, -adapted and modified to meet the specifications of the Gno language project. - -Please note that the modifications are also under the Apache License 2.0 unless otherwise specified. diff --git a/examples/gno.land/p/demo/json/ryu/floatconv.gno b/examples/gno.land/p/demo/json/ryu/floatconv.gno deleted file mode 100644 index 617141d2734..00000000000 --- a/examples/gno.land/p/demo/json/ryu/floatconv.gno +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright 2018 Ulf Adams -// Modifications copyright 2019 Caleb Spare -// -// The contents of this file may be used under the terms of the Apache License, -// Version 2.0. -// -// (See accompanying file LICENSE or copy at -// http://www.apache.org/licenses/LICENSE-2.0) -// -// Unless required by applicable law or agreed to in writing, this software -// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. -// -// The code in this file is part of a Go translation of the C code originally written by -// Ulf Adams, which can be found at https://github.com/ulfjack/ryu. The original source -// code is licensed under the Apache License 2.0. This code is a derivative work thereof, -// adapted and modified to meet the specifications of the Gno language project. -// -// original Go implementation can be found at https://github.com/cespare/ryu. -// -// Please note that the modifications are also under the Apache License 2.0 unless -// otherwise specified. - -// Package ryu implements the Ryu algorithm for quickly converting floating -// point numbers into strings. -package ryu - -import ( - "math" -) - -const ( - mantBits32 = 23 - expBits32 = 8 - bias32 = 127 - - mantBits64 = 52 - expBits64 = 11 - bias64 = 1023 -) - -// FormatFloat64 converts a 64-bit floating point number f to a string. -// It behaves like strconv.FormatFloat(f, 'e', -1, 64). -func FormatFloat64(f float64) string { - b := make([]byte, 0, 24) - b = AppendFloat64(b, f) - return string(b) -} - -// AppendFloat64 appends the string form of the 64-bit floating point number f, -// as generated by FormatFloat64, to b and returns the extended buffer. -func AppendFloat64(b []byte, f float64) []byte { - // Step 1: Decode the floating-point number. - // Unify normalized and subnormal cases. - u := math.Float64bits(f) - neg := u>>(mantBits64+expBits64) != 0 - mant := u & (uint64(1)<> mantBits64) & (uint64(1)<= 0, "e >= 0") - assert(e <= 1650, "e <= 1650") - return (uint32(e) * 78913) >> 18 -} - -// log10Pow5 returns floor(log_10(5^e)). -func log10Pow5(e int32) uint32 { - // The first value this approximation fails for is 5^2621 - // which is just greater than 10^1832. - assert(e >= 0, "e >= 0") - assert(e <= 2620, "e <= 2620") - return (uint32(e) * 732923) >> 20 -} - -// pow5Bits returns ceil(log_2(5^e)), or else 1 if e==0. -func pow5Bits(e int32) int32 { - // This approximation works up to the point that the multiplication - // overflows at e = 3529. If the multiplication were done in 64 bits, - // it would fail at 5^4004 which is just greater than 2^9297. - assert(e >= 0, "e >= 0") - assert(e <= 3528, "e <= 3528") - return int32((uint32(e)*1217359)>>19 + 1) -} diff --git a/examples/gno.land/p/demo/json/ryu/floatconv_test.gno b/examples/gno.land/p/demo/json/ryu/floatconv_test.gno deleted file mode 100644 index 7f01d4034f7..00000000000 --- a/examples/gno.land/p/demo/json/ryu/floatconv_test.gno +++ /dev/null @@ -1,33 +0,0 @@ -package ryu - -import ( - "math" - "testing" -) - -func TestFormatFloat64(t *testing.T) { - tests := []struct { - name string - value float64 - expected string - }{ - {"positive infinity", math.Inf(1), "+Inf"}, - {"negative infinity", math.Inf(-1), "-Inf"}, - {"NaN", math.NaN(), "NaN"}, - {"zero", 0.0, "0e+00"}, - {"negative zero", -0.0, "0e+00"}, - {"positive number", 3.14159, "3.14159e+00"}, - {"negative number", -2.71828, "-2.71828e+00"}, - {"very small number", 1.23e-20, "1.23e-20"}, - {"very large number", 1.23e+20, "1.23e+20"}, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - result := FormatFloat64(test.value) - if result != test.expected { - t.Errorf("FormatFloat64(%v) = %q, expected %q", test.value, result, test.expected) - } - }) - } -} diff --git a/examples/gno.land/p/demo/json/ryu/gno.mod b/examples/gno.land/p/demo/json/ryu/gno.mod deleted file mode 100644 index 86a1988b052..00000000000 --- a/examples/gno.land/p/demo/json/ryu/gno.mod +++ /dev/null @@ -1 +0,0 @@ -module gno.land/p/demo/json/ryu diff --git a/examples/gno.land/p/demo/json/ryu/ryu64.gno b/examples/gno.land/p/demo/json/ryu/ryu64.gno deleted file mode 100644 index 249e3d0f526..00000000000 --- a/examples/gno.land/p/demo/json/ryu/ryu64.gno +++ /dev/null @@ -1,344 +0,0 @@ -package ryu - -import ( - "math/bits" -) - -type uint128 struct { - lo uint64 - hi uint64 -} - -// dec64 is a floating decimal type representing m * 10^e. -type dec64 struct { - m uint64 - e int32 -} - -func (d dec64) append(b []byte, neg bool) []byte { - // Step 5: Print the decimal representation. - if neg { - b = append(b, '-') - } - - out := d.m - outLen := decimalLen64(out) - bufLen := outLen - if bufLen > 1 { - bufLen++ // extra space for '.' - } - - // Print the decimal digits. - n := len(b) - if cap(b)-len(b) >= bufLen { - // Avoid function call in the common case. - b = b[:len(b)+bufLen] - } else { - b = append(b, make([]byte, bufLen)...) - } - - // Avoid expensive 64-bit divisions. - // We have at most 17 digits, and uint32 can store 9 digits. - // If the output doesn't fit into a uint32, cut off 8 digits - // so the rest will fit into a uint32. - var i int - if out>>32 > 0 { - var out32 uint32 - out, out32 = out/1e8, uint32(out%1e8) - for ; i < 8; i++ { - b[n+outLen-i] = '0' + byte(out32%10) - out32 /= 10 - } - } - out32 := uint32(out) - for ; i < outLen-1; i++ { - b[n+outLen-i] = '0' + byte(out32%10) - out32 /= 10 - } - b[n] = '0' + byte(out32%10) - - // Print the '.' if needed. - if outLen > 1 { - b[n+1] = '.' - } - - // Print the exponent. - b = append(b, 'e') - exp := d.e + int32(outLen) - 1 - if exp < 0 { - b = append(b, '-') - exp = -exp - } else { - // Unconditionally print a + here to match strconv's formatting. - b = append(b, '+') - } - // Always print at least two digits to match strconv's formatting. - d2 := exp % 10 - exp /= 10 - d1 := exp % 10 - d0 := exp / 10 - if d0 > 0 { - b = append(b, '0'+byte(d0)) - } - b = append(b, '0'+byte(d1), '0'+byte(d2)) - - return b -} - -func float64ToDecimalExactInt(mant, exp uint64) (d dec64, ok bool) { - e := exp - bias64 - if e > mantBits64 { - return d, false - } - shift := mantBits64 - e - mant |= 1 << mantBits64 // implicit 1 - d.m = mant >> shift - if d.m<= 0 { - // This expression is slightly faster than max(0, log10Pow2(e2) - 1). - q := log10Pow2(e2) - boolToUint32(e2 > 3) - e10 = int32(q) - k := pow5InvNumBits64 + pow5Bits(int32(q)) - 1 - i := -e2 + int32(q) + k - mul := pow5InvSplit64[q] - vr = mulShift64(4*m2, mul, i) - vp = mulShift64(4*m2+2, mul, i) - vm = mulShift64(4*m2-1-mmShift, mul, i) - if q <= 21 { - // This should use q <= 22, but I think 21 is also safe. - // Smaller values may still be safe, but it's more - // difficult to reason about them. Only one of mp, mv, - // and mm can be a multiple of 5, if any. - if mv%5 == 0 { - vrIsTrailingZeros = multipleOfPowerOfFive64(mv, q) - } else if acceptBounds { - // Same as min(e2 + (^mm & 1), pow5Factor64(mm)) >= q - // <=> e2 + (^mm & 1) >= q && pow5Factor64(mm) >= q - // <=> true && pow5Factor64(mm) >= q, since e2 >= q. - vmIsTrailingZeros = multipleOfPowerOfFive64(mv-1-mmShift, q) - } else if multipleOfPowerOfFive64(mv+2, q) { - vp-- - } - } - } else { - // This expression is slightly faster than max(0, log10Pow5(-e2) - 1). - q := log10Pow5(-e2) - boolToUint32(-e2 > 1) - e10 = int32(q) + e2 - i := -e2 - int32(q) - k := pow5Bits(i) - pow5NumBits64 - j := int32(q) - k - mul := pow5Split64[i] - vr = mulShift64(4*m2, mul, j) - vp = mulShift64(4*m2+2, mul, j) - vm = mulShift64(4*m2-1-mmShift, mul, j) - if q <= 1 { - // {vr,vp,vm} is trailing zeros if {mv,mp,mm} has at least q trailing 0 bits. - // mv = 4 * m2, so it always has at least two trailing 0 bits. - vrIsTrailingZeros = true - if acceptBounds { - // mm = mv - 1 - mmShift, so it has 1 trailing 0 bit iff mmShift == 1. - vmIsTrailingZeros = mmShift == 1 - } else { - // mp = mv + 2, so it always has at least one trailing 0 bit. - vp-- - } - } else if q < 63 { // TODO(ulfjack/cespare): Use a tighter bound here. - // We need to compute min(ntz(mv), pow5Factor64(mv) - e2) >= q - 1 - // <=> ntz(mv) >= q - 1 && pow5Factor64(mv) - e2 >= q - 1 - // <=> ntz(mv) >= q - 1 (e2 is negative and -e2 >= q) - // <=> (mv & ((1 << (q - 1)) - 1)) == 0 - // We also need to make sure that the left shift does not overflow. - vrIsTrailingZeros = multipleOfPowerOfTwo64(mv, q-1) - } - } - - // Step 4: Find the shortest decimal representation - // in the interval of valid representations. - var removed int32 - var lastRemovedDigit uint8 - var out uint64 - // On average, we remove ~2 digits. - if vmIsTrailingZeros || vrIsTrailingZeros { - // General case, which happens rarely (~0.7%). - for { - vpDiv10 := vp / 10 - vmDiv10 := vm / 10 - if vpDiv10 <= vmDiv10 { - break - } - vmMod10 := vm % 10 - vrDiv10 := vr / 10 - vrMod10 := vr % 10 - vmIsTrailingZeros = vmIsTrailingZeros && vmMod10 == 0 - vrIsTrailingZeros = vrIsTrailingZeros && lastRemovedDigit == 0 - lastRemovedDigit = uint8(vrMod10) - vr = vrDiv10 - vp = vpDiv10 - vm = vmDiv10 - removed++ - } - if vmIsTrailingZeros { - for { - vmDiv10 := vm / 10 - vmMod10 := vm % 10 - if vmMod10 != 0 { - break - } - vpDiv10 := vp / 10 - vrDiv10 := vr / 10 - vrMod10 := vr % 10 - vrIsTrailingZeros = vrIsTrailingZeros && lastRemovedDigit == 0 - lastRemovedDigit = uint8(vrMod10) - vr = vrDiv10 - vp = vpDiv10 - vm = vmDiv10 - removed++ - } - } - if vrIsTrailingZeros && lastRemovedDigit == 5 && vr%2 == 0 { - // Round even if the exact number is .....50..0. - lastRemovedDigit = 4 - } - out = vr - // We need to take vr + 1 if vr is outside bounds - // or we need to round up. - if (vr == vm && (!acceptBounds || !vmIsTrailingZeros)) || lastRemovedDigit >= 5 { - out++ - } - } else { - // Specialized for the common case (~99.3%). - // Percentages below are relative to this. - roundUp := false - for vp/100 > vm/100 { - // Optimization: remove two digits at a time (~86.2%). - roundUp = vr%100 >= 50 - vr /= 100 - vp /= 100 - vm /= 100 - removed += 2 - } - // Loop iterations below (approximately), without optimization above: - // 0: 0.03%, 1: 13.8%, 2: 70.6%, 3: 14.0%, 4: 1.40%, 5: 0.14%, 6+: 0.02% - // Loop iterations below (approximately), with optimization above: - // 0: 70.6%, 1: 27.8%, 2: 1.40%, 3: 0.14%, 4+: 0.02% - for vp/10 > vm/10 { - roundUp = vr%10 >= 5 - vr /= 10 - vp /= 10 - vm /= 10 - removed++ - } - // We need to take vr + 1 if vr is outside bounds - // or we need to round up. - out = vr + boolToUint64(vr == vm || roundUp) - } - - return dec64{m: out, e: e10 + removed} -} - -var powersOf10 = [...]uint64{ - 1e0, - 1e1, - 1e2, - 1e3, - 1e4, - 1e5, - 1e6, - 1e7, - 1e8, - 1e9, - 1e10, - 1e11, - 1e12, - 1e13, - 1e14, - 1e15, - 1e16, - 1e17, - // We only need to find the length of at most 17 digit numbers. -} - -func decimalLen64(u uint64) int { - // http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10 - log2 := 64 - bits.LeadingZeros64(u) - 1 - t := (log2 + 1) * 1233 >> 12 - return t - boolToInt(u < powersOf10[t]) + 1 -} - -func mulShift64(m uint64, mul uint128, shift int32) uint64 { - hihi, hilo := bits.Mul64(m, mul.hi) - lohi, _ := bits.Mul64(m, mul.lo) - sum := uint128{hi: hihi, lo: lohi + hilo} - if sum.lo < lohi { - sum.hi++ // overflow - } - return shiftRight128(sum, shift-64) -} - -func shiftRight128(v uint128, shift int32) uint64 { - // The shift value is always modulo 64. - // In the current implementation of the 64-bit version - // of Ryu, the shift value is always < 64. - // (It is in the range [2, 59].) - // Check this here in case a future change requires larger shift - // values. In this case this function needs to be adjusted. - assert(shift < 64, "shift < 64") - return (v.hi << uint64(64-shift)) | (v.lo >> uint(shift)) -} - -func pow5Factor64(v uint64) uint32 { - for n := uint32(0); ; n++ { - q, r := v/5, v%5 - if r != 0 { - return n - } - v = q - } -} - -func multipleOfPowerOfFive64(v uint64, p uint32) bool { - return pow5Factor64(v) >= p -} - -func multipleOfPowerOfTwo64(v uint64, p uint32) bool { - return uint32(bits.TrailingZeros64(v)) >= p -} diff --git a/examples/gno.land/p/demo/json/ryu/table.gno b/examples/gno.land/p/demo/json/ryu/table.gno deleted file mode 100644 index fe33ad90a57..00000000000 --- a/examples/gno.land/p/demo/json/ryu/table.gno +++ /dev/null @@ -1,678 +0,0 @@ -// Code generated by running "go generate". DO NOT EDIT. - -// Copyright 2018 Ulf Adams -// Modifications copyright 2019 Caleb Spare -// -// The contents of this file may be used under the terms of the Apache License, -// Version 2.0. -// -// (See accompanying file LICENSE or copy at -// http://www.apache.org/licenses/LICENSE-2.0) -// -// Unless required by applicable law or agreed to in writing, this software -// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. -// -// The code in this file is part of a Go translation of the C code written by -// Ulf Adams which may be found at https://github.com/ulfjack/ryu. That source -// code is licensed under Apache 2.0 and this code is derivative work thereof. - -package ryu - -const pow5NumBits32 = 61 - -var pow5Split32 = [...]uint64{ - 1152921504606846976, 1441151880758558720, 1801439850948198400, 2251799813685248000, - 1407374883553280000, 1759218604441600000, 2199023255552000000, 1374389534720000000, - 1717986918400000000, 2147483648000000000, 1342177280000000000, 1677721600000000000, - 2097152000000000000, 1310720000000000000, 1638400000000000000, 2048000000000000000, - 1280000000000000000, 1600000000000000000, 2000000000000000000, 1250000000000000000, - 1562500000000000000, 1953125000000000000, 1220703125000000000, 1525878906250000000, - 1907348632812500000, 1192092895507812500, 1490116119384765625, 1862645149230957031, - 1164153218269348144, 1455191522836685180, 1818989403545856475, 2273736754432320594, - 1421085471520200371, 1776356839400250464, 2220446049250313080, 1387778780781445675, - 1734723475976807094, 2168404344971008868, 1355252715606880542, 1694065894508600678, - 2117582368135750847, 1323488980084844279, 1654361225106055349, 2067951531382569187, - 1292469707114105741, 1615587133892632177, 2019483917365790221, -} - -const pow5InvNumBits32 = 59 - -var pow5InvSplit32 = [...]uint64{ - 576460752303423489, 461168601842738791, 368934881474191033, 295147905179352826, - 472236648286964522, 377789318629571618, 302231454903657294, 483570327845851670, - 386856262276681336, 309485009821345069, 495176015714152110, 396140812571321688, - 316912650057057351, 507060240091291761, 405648192073033409, 324518553658426727, - 519229685853482763, 415383748682786211, 332306998946228969, 531691198313966350, - 425352958651173080, 340282366920938464, 544451787073501542, 435561429658801234, - 348449143727040987, 557518629963265579, 446014903970612463, 356811923176489971, - 570899077082383953, 456719261665907162, 365375409332725730, -} - -const pow5NumBits64 = 121 - -var pow5Split64 = [...]uint128{ - {0, 72057594037927936}, - {0, 90071992547409920}, - {0, 112589990684262400}, - {0, 140737488355328000}, - {0, 87960930222080000}, - {0, 109951162777600000}, - {0, 137438953472000000}, - {0, 85899345920000000}, - {0, 107374182400000000}, - {0, 134217728000000000}, - {0, 83886080000000000}, - {0, 104857600000000000}, - {0, 131072000000000000}, - {0, 81920000000000000}, - {0, 102400000000000000}, - {0, 128000000000000000}, - {0, 80000000000000000}, - {0, 100000000000000000}, - {0, 125000000000000000}, - {0, 78125000000000000}, - {0, 97656250000000000}, - {0, 122070312500000000}, - {0, 76293945312500000}, - {0, 95367431640625000}, - {0, 119209289550781250}, - {4611686018427387904, 74505805969238281}, - {10376293541461622784, 93132257461547851}, - {8358680908399640576, 116415321826934814}, - {612489549322387456, 72759576141834259}, - {14600669991935148032, 90949470177292823}, - {13639151471491547136, 113686837721616029}, - {3213881284082270208, 142108547152020037}, - {4314518811765112832, 88817841970012523}, - {781462496279003136, 111022302462515654}, - {10200200157203529728, 138777878078144567}, - {13292654125893287936, 86736173798840354}, - {7392445620511834112, 108420217248550443}, - {4628871007212404736, 135525271560688054}, - {16728102434789916672, 84703294725430033}, - {7075069988205232128, 105879118406787542}, - {18067209522111315968, 132348898008484427}, - {8986162942105878528, 82718061255302767}, - {6621017659204960256, 103397576569128459}, - {3664586055578812416, 129246970711410574}, - {16125424340018921472, 80779356694631608}, - {1710036351314100224, 100974195868289511}, - {15972603494424788992, 126217744835361888}, - {9982877184015493120, 78886090522101180}, - {12478596480019366400, 98607613152626475}, - {10986559581596820096, 123259516440783094}, - {2254913720070624656, 77037197775489434}, - {12042014186943056628, 96296497219361792}, - {15052517733678820785, 120370621524202240}, - {9407823583549262990, 75231638452626400}, - {11759779479436578738, 94039548065783000}, - {14699724349295723422, 117549435082228750}, - {4575641699882439235, 73468396926392969}, - {10331238143280436948, 91835496157991211}, - {8302361660673158281, 114794370197489014}, - {1154580038986672043, 143492962746861268}, - {9944984561221445835, 89683101716788292}, - {12431230701526807293, 112103877145985365}, - {1703980321626345405, 140129846432481707}, - {17205888765512323542, 87581154020301066}, - {12283988920035628619, 109476442525376333}, - {1519928094762372062, 136845553156720417}, - {12479170105294952299, 85528470722950260}, - {15598962631618690374, 106910588403687825}, - {5663645234241199255, 133638235504609782}, - {17374836326682913246, 83523897190381113}, - {7883487353071477846, 104404871487976392}, - {9854359191339347308, 130506089359970490}, - {10770660513014479971, 81566305849981556}, - {13463325641268099964, 101957882312476945}, - {2994098996302961243, 127447352890596182}, - {15706369927971514489, 79654595556622613}, - {5797904354682229399, 99568244445778267}, - {2635694424925398845, 124460305557222834}, - {6258995034005762182, 77787690973264271}, - {3212057774079814824, 97234613716580339}, - {17850130272881932242, 121543267145725423}, - {18073860448192289507, 75964541966078389}, - {8757267504958198172, 94955677457597987}, - {6334898362770359811, 118694596821997484}, - {13182683513586250689, 74184123013748427}, - {11866668373555425458, 92730153767185534}, - {5609963430089506015, 115912692208981918}, - {17341285199088104971, 72445432630613698}, - {12453234462005355406, 90556790788267123}, - {10954857059079306353, 113195988485333904}, - {13693571323849132942, 141494985606667380}, - {17781854114260483896, 88434366004167112}, - {3780573569116053255, 110542957505208891}, - {114030942967678664, 138178696881511114}, - {4682955357782187069, 86361685550944446}, - {15077066234082509644, 107952106938680557}, - {5011274737320973344, 134940133673350697}, - {14661261756894078100, 84337583545844185}, - {4491519140835433913, 105421979432305232}, - {5614398926044292391, 131777474290381540}, - {12732371365632458552, 82360921431488462}, - {6692092170185797382, 102951151789360578}, - {17588487249587022536, 128688939736700722}, - {15604490549419276989, 80430587335437951}, - {14893927168346708332, 100538234169297439}, - {14005722942005997511, 125672792711621799}, - {15671105866394830300, 78545495444763624}, - {1142138259283986260, 98181869305954531}, - {15262730879387146537, 122727336632443163}, - {7233363790403272633, 76704585395276977}, - {13653390756431478696, 95880731744096221}, - {3231680390257184658, 119850914680120277}, - {4325643253124434363, 74906821675075173}, - {10018740084832930858, 93633527093843966}, - {3300053069186387764, 117041908867304958}, - {15897591223523656064, 73151193042065598}, - {10648616992549794273, 91438991302581998}, - {4087399203832467033, 114298739128227498}, - {14332621041645359599, 142873423910284372}, - {18181260187883125557, 89295889943927732}, - {4279831161144355331, 111619862429909666}, - {14573160988285219972, 139524828037387082}, - {13719911636105650386, 87203017523366926}, - {7926517508277287175, 109003771904208658}, - {684774848491833161, 136254714880260823}, - {7345513307948477581, 85159196800163014}, - {18405263671790372785, 106448996000203767}, - {18394893571310578077, 133061245000254709}, - {13802651491282805250, 83163278125159193}, - {3418256308821342851, 103954097656448992}, - {4272820386026678563, 129942622070561240}, - {2670512741266674102, 81214138794100775}, - {17173198981865506339, 101517673492625968}, - {3019754653622331308, 126897091865782461}, - {4193189667727651020, 79310682416114038}, - {14464859121514339583, 99138353020142547}, - {13469387883465536574, 123922941275178184}, - {8418367427165960359, 77451838296986365}, - {15134645302384838353, 96814797871232956}, - {471562554271496325, 121018497339041196}, - {9518098633274461011, 75636560836900747}, - {7285937273165688360, 94545701046125934}, - {18330793628311886258, 118182126307657417}, - {4539216990053847055, 73863828942285886}, - {14897393274422084627, 92329786177857357}, - {4786683537745442072, 115412232722321697}, - {14520892257159371055, 72132645451451060}, - {18151115321449213818, 90165806814313825}, - {8853836096529353561, 112707258517892282}, - {1843923083806916143, 140884073147365353}, - {12681666973447792349, 88052545717103345}, - {2017025661527576725, 110065682146379182}, - {11744654113764246714, 137582102682973977}, - {422879793461572340, 85988814176858736}, - {528599741826965425, 107486017721073420}, - {660749677283706782, 134357522151341775}, - {7330497575943398595, 83973451344588609}, - {13774807988356636147, 104966814180735761}, - {3383451930163631472, 131208517725919702}, - {15949715511634433382, 82005323578699813}, - {6102086334260878016, 102506654473374767}, - {3015921899398709616, 128133318091718459}, - {18025852251620051174, 80083323807324036}, - {4085571240815512351, 100104154759155046}, - {14330336087874166247, 125130193448943807}, - {15873989082562435760, 78206370905589879}, - {15230800334775656796, 97757963631987349}, - {5203442363187407284, 122197454539984187}, - {946308467778435600, 76373409087490117}, - {5794571603150432404, 95466761359362646}, - {16466586540792816313, 119333451699203307}, - {7985773578781816244, 74583407312002067}, - {5370530955049882401, 93229259140002584}, - {6713163693812353001, 116536573925003230}, - {18030785363914884337, 72835358703127018}, - {13315109668038829614, 91044198378908773}, - {2808829029766373305, 113805247973635967}, - {17346094342490130344, 142256559967044958}, - {6229622945628943561, 88910349979403099}, - {3175342663608791547, 111137937474253874}, - {13192550366365765242, 138922421842817342}, - {3633657960551215372, 86826513651760839}, - {18377130505971182927, 108533142064701048}, - {4524669058754427043, 135666427580876311}, - {9745447189362598758, 84791517238047694}, - {2958436949848472639, 105989396547559618}, - {12921418224165366607, 132486745684449522}, - {12687572408530742033, 82804216052780951}, - {11247779492236039638, 103505270065976189}, - {224666310012885835, 129381587582470237}, - {2446259452971747599, 80863492239043898}, - {12281196353069460307, 101079365298804872}, - {15351495441336825384, 126349206623506090}, - {14206370669262903769, 78968254139691306}, - {8534591299723853903, 98710317674614133}, - {15279925143082205283, 123387897093267666}, - {14161639232853766206, 77117435683292291}, - {13090363022639819853, 96396794604115364}, - {16362953778299774816, 120495993255144205}, - {12532689120651053212, 75309995784465128}, - {15665861400813816515, 94137494730581410}, - {10358954714162494836, 117671868413226763}, - {4168503687137865320, 73544917758266727}, - {598943590494943747, 91931147197833409}, - {5360365506546067587, 114913933997291761}, - {11312142901609972388, 143642417496614701}, - {9375932322719926695, 89776510935384188}, - {11719915403399908368, 112220638669230235}, - {10038208235822497557, 140275798336537794}, - {10885566165816448877, 87672373960336121}, - {18218643725697949000, 109590467450420151}, - {18161618638695048346, 136988084313025189}, - {13656854658398099168, 85617552695640743}, - {12459382304570236056, 107021940869550929}, - {1739169825430631358, 133777426086938662}, - {14922039196176308311, 83610891304336663}, - {14040862976792997485, 104513614130420829}, - {3716020665709083144, 130642017663026037}, - {4628355925281870917, 81651261039391273}, - {10397130925029726550, 102064076299239091}, - {8384727637859770284, 127580095374048864}, - {5240454773662356427, 79737559608780540}, - {6550568467077945534, 99671949510975675}, - {3576524565420044014, 124589936888719594}, - {6847013871814915412, 77868710555449746}, - {17782139376623420074, 97335888194312182}, - {13004302183924499284, 121669860242890228}, - {17351060901807587860, 76043662651806392}, - {3242082053549933210, 95054578314757991}, - {17887660622219580224, 118818222893447488}, - {11179787888887237640, 74261389308404680}, - {13974734861109047050, 92826736635505850}, - {8245046539531533005, 116033420794382313}, - {16682369133275677888, 72520887996488945}, - {7017903361312433648, 90651109995611182}, - {17995751238495317868, 113313887494513977}, - {8659630992836983623, 141642359368142472}, - {5412269370523114764, 88526474605089045}, - {11377022731581281359, 110658093256361306}, - {4997906377621825891, 138322616570451633}, - {14652906532082110942, 86451635356532270}, - {9092761128247862869, 108064544195665338}, - {2142579373455052779, 135080680244581673}, - {12868327154477877747, 84425425152863545}, - {2250350887815183471, 105531781441079432}, - {2812938609768979339, 131914726801349290}, - {6369772649532999991, 82446704250843306}, - {17185587848771025797, 103058380313554132}, - {3035240737254230630, 128822975391942666}, - {6508711479211282048, 80514359619964166}, - {17359261385868878368, 100642949524955207}, - {17087390713908710056, 125803686906194009}, - {3762090168551861929, 78627304316371256}, - {4702612710689827411, 98284130395464070}, - {15101637925217060072, 122855162994330087}, - {16356052730901744401, 76784476871456304}, - {1998321839917628885, 95980596089320381}, - {7109588318324424010, 119975745111650476}, - {13666864735807540814, 74984840694781547}, - {12471894901332038114, 93731050868476934}, - {6366496589810271835, 117163813585596168}, - {3979060368631419896, 73227383490997605}, - {9585511479216662775, 91534229363747006}, - {2758517312166052660, 114417786704683758}, - {12671518677062341634, 143022233380854697}, - {1002170145522881665, 89388895863034186}, - {10476084718758377889, 111736119828792732}, - {13095105898447972362, 139670149785990915}, - {5878598177316288774, 87293843616244322}, - {16571619758500136775, 109117304520305402}, - {11491152661270395161, 136396630650381753}, - {264441385652915120, 85247894156488596}, - {330551732066143900, 106559867695610745}, - {5024875683510067779, 133199834619513431}, - {10058076329834874218, 83249896637195894}, - {3349223375438816964, 104062370796494868}, - {4186529219298521205, 130077963495618585}, - {14145795808130045513, 81298727184761615}, - {13070558741735168987, 101623408980952019}, - {11726512408741573330, 127029261226190024}, - {7329070255463483331, 79393288266368765}, - {13773023837756742068, 99241610332960956}, - {17216279797195927585, 124052012916201195}, - {8454331864033760789, 77532508072625747}, - {5956228811614813082, 96915635090782184}, - {7445286014518516353, 121144543863477730}, - {9264989777501460624, 75715339914673581}, - {16192923240304213684, 94644174893341976}, - {1794409976670715490, 118305218616677471}, - {8039035263060279037, 73940761635423419}, - {5437108060397960892, 92425952044279274}, - {16019757112352226923, 115532440055349092}, - {788976158365366019, 72207775034593183}, - {14821278253238871236, 90259718793241478}, - {9303225779693813237, 112824648491551848}, - {11629032224617266546, 141030810614439810}, - {11879831158813179495, 88144256634024881}, - {1014730893234310657, 110180320792531102}, - {10491785653397664129, 137725400990663877}, - {8863209042587234033, 86078375619164923}, - {6467325284806654637, 107597969523956154}, - {17307528642863094104, 134497461904945192}, - {10817205401789433815, 84060913690590745}, - {18133192770664180173, 105076142113238431}, - {18054804944902837312, 131345177641548039}, - {18201782118205355176, 82090736025967524}, - {4305483574047142354, 102613420032459406}, - {14605226504413703751, 128266775040574257}, - {2210737537617482988, 80166734400358911}, - {16598479977304017447, 100208418000448638}, - {11524727934775246001, 125260522500560798}, - {2591268940807140847, 78287826562850499}, - {17074144231291089770, 97859783203563123}, - {16730994270686474309, 122324729004453904}, - {10456871419179046443, 76452955627783690}, - {3847717237119032246, 95566194534729613}, - {9421332564826178211, 119457743168412016}, - {5888332853016361382, 74661089480257510}, - {16583788103125227536, 93326361850321887}, - {16118049110479146516, 116657952312902359}, - {16991309721690548428, 72911220195563974}, - {12015765115258409727, 91139025244454968}, - {15019706394073012159, 113923781555568710}, - {9551260955736489391, 142404726944460888}, - {5969538097335305869, 89002954340288055}, - {2850236603241744433, 111253692925360069}, -} - -const pow5InvNumBits64 = 122 - -var pow5InvSplit64 = [...]uint128{ - {1, 288230376151711744}, - {3689348814741910324, 230584300921369395}, - {2951479051793528259, 184467440737095516}, - {17118578500402463900, 147573952589676412}, - {12632330341676300947, 236118324143482260}, - {10105864273341040758, 188894659314785808}, - {15463389048156653253, 151115727451828646}, - {17362724847566824558, 241785163922925834}, - {17579528692795369969, 193428131138340667}, - {6684925324752475329, 154742504910672534}, - {18074578149087781173, 247588007857076054}, - {18149011334012135262, 198070406285660843}, - {3451162622983977240, 158456325028528675}, - {5521860196774363583, 253530120045645880}, - {4417488157419490867, 202824096036516704}, - {7223339340677503017, 162259276829213363}, - {7867994130342094503, 259614842926741381}, - {2605046489531765280, 207691874341393105}, - {2084037191625412224, 166153499473114484}, - {10713157136084480204, 265845599156983174}, - {12259874523609494487, 212676479325586539}, - {13497248433629505913, 170141183460469231}, - {14216899864323388813, 272225893536750770}, - {11373519891458711051, 217780714829400616}, - {5409467098425058518, 174224571863520493}, - {4965798542738183305, 278759314981632789}, - {7661987648932456967, 223007451985306231}, - {2440241304404055250, 178405961588244985}, - {3904386087046488400, 285449538541191976}, - {17880904128604832013, 228359630832953580}, - {14304723302883865611, 182687704666362864}, - {15133127457049002812, 146150163733090291}, - {16834306301794583852, 233840261972944466}, - {9778096226693756759, 187072209578355573}, - {15201174610838826053, 149657767662684458}, - {2185786488890659746, 239452428260295134}, - {5437978005854438120, 191561942608236107}, - {15418428848909281466, 153249554086588885}, - {6222742084545298729, 245199286538542217}, - {16046240111861969953, 196159429230833773}, - {1768945645263844993, 156927543384667019}, - {10209010661905972635, 251084069415467230}, - {8167208529524778108, 200867255532373784}, - {10223115638361732810, 160693804425899027}, - {1599589762411131202, 257110087081438444}, - {4969020624670815285, 205688069665150755}, - {3975216499736652228, 164550455732120604}, - {13739044029062464211, 263280729171392966}, - {7301886408508061046, 210624583337114373}, - {13220206756290269483, 168499666669691498}, - {17462981995322520850, 269599466671506397}, - {6591687966774196033, 215679573337205118}, - {12652048002903177473, 172543658669764094}, - {9175230360419352987, 276069853871622551}, - {3650835473593572067, 220855883097298041}, - {17678063637842498946, 176684706477838432}, - {13527506561580357021, 282695530364541492}, - {3443307619780464970, 226156424291633194}, - {6443994910566282300, 180925139433306555}, - {5155195928453025840, 144740111546645244}, - {15627011115008661990, 231584178474632390}, - {12501608892006929592, 185267342779705912}, - {2622589484121723027, 148213874223764730}, - {4196143174594756843, 237142198758023568}, - {10735612169159626121, 189713759006418854}, - {12277838550069611220, 151771007205135083}, - {15955192865369467629, 242833611528216133}, - {1696107848069843133, 194266889222572907}, - {12424932722681605476, 155413511378058325}, - {1433148282581017146, 248661618204893321}, - {15903913885032455010, 198929294563914656}, - {9033782293284053685, 159143435651131725}, - {14454051669254485895, 254629497041810760}, - {11563241335403588716, 203703597633448608}, - {16629290697806691620, 162962878106758886}, - {781423413297334329, 260740604970814219}, - {4314487545379777786, 208592483976651375}, - {3451590036303822229, 166873987181321100}, - {5522544058086115566, 266998379490113760}, - {4418035246468892453, 213598703592091008}, - {10913125826658934609, 170878962873672806}, - {10082303693170474728, 273406340597876490}, - {8065842954536379782, 218725072478301192}, - {17520720807854834795, 174980057982640953}, - {5897060404116273733, 279968092772225526}, - {1028299508551108663, 223974474217780421}, - {15580034865808528224, 179179579374224336}, - {17549358155809824511, 286687326998758938}, - {2971440080422128639, 229349861599007151}, - {17134547323305344204, 183479889279205720}, - {13707637858644275364, 146783911423364576}, - {14553522944347019935, 234854258277383322}, - {4264120725993795302, 187883406621906658}, - {10789994210278856888, 150306725297525326}, - {9885293106962350374, 240490760476040522}, - {529536856086059653, 192392608380832418}, - {7802327114352668369, 153914086704665934}, - {1415676938738538420, 246262538727465495}, - {1132541550990830736, 197010030981972396}, - {15663428499760305882, 157608024785577916}, - {17682787970132668764, 252172839656924666}, - {10456881561364224688, 201738271725539733}, - {15744202878575200397, 161390617380431786}, - {17812026976236499989, 258224987808690858}, - {3181575136763469022, 206579990246952687}, - {13613306553636506187, 165263992197562149}, - {10713244041592678929, 264422387516099439}, - {12259944048016053467, 211537910012879551}, - {6118606423670932450, 169230328010303641}, - {2411072648389671274, 270768524816485826}, - {16686253377679378312, 216614819853188660}, - {13349002702143502650, 173291855882550928}, - {17669055508687693916, 277266969412081485}, - {14135244406950155133, 221813575529665188}, - {240149081334393137, 177450860423732151}, - {11452284974360759988, 283921376677971441}, - {5472479164746697667, 227137101342377153}, - {11756680961281178780, 181709681073901722}, - {2026647139541122378, 145367744859121378}, - {18000030682233437097, 232588391774594204}, - {18089373360528660001, 186070713419675363}, - {3403452244197197031, 148856570735740291}, - {16513570034941246220, 238170513177184465}, - {13210856027952996976, 190536410541747572}, - {3189987192878576934, 152429128433398058}, - {1414630693863812771, 243886605493436893}, - {8510402184574870864, 195109284394749514}, - {10497670562401807014, 156087427515799611}, - {9417575270359070576, 249739884025279378}, - {14912757845771077107, 199791907220223502}, - {4551508647133041040, 159833525776178802}, - {10971762650154775986, 255733641241886083}, - {16156107749607641435, 204586912993508866}, - {9235537384944202825, 163669530394807093}, - {11087511001168814197, 261871248631691349}, - {12559357615676961681, 209496998905353079}, - {13736834907283479668, 167597599124282463}, - {18289587036911657145, 268156158598851941}, - {10942320814787415393, 214524926879081553}, - {16132554281313752961, 171619941503265242}, - {11054691591134363444, 274591906405224388}, - {16222450902391311402, 219673525124179510}, - {12977960721913049122, 175738820099343608}, - {17075388340318968271, 281182112158949773}, - {2592264228029443648, 224945689727159819}, - {5763160197165465241, 179956551781727855}, - {9221056315464744386, 287930482850764568}, - {14755542681855616155, 230344386280611654}, - {15493782960226403247, 184275509024489323}, - {1326979923955391628, 147420407219591459}, - {9501865507812447252, 235872651551346334}, - {11290841220991868125, 188698121241077067}, - {1653975347309673853, 150958496992861654}, - {10025058185179298811, 241533595188578646}, - {4330697733401528726, 193226876150862917}, - {14532604630946953951, 154581500920690333}, - {1116074521063664381, 247330401473104534}, - {4582208431592841828, 197864321178483627}, - {14733813189500004432, 158291456942786901}, - {16195403473716186445, 253266331108459042}, - {5577625149489128510, 202613064886767234}, - {8151448934333213131, 162090451909413787}, - {16731667109675051333, 259344723055062059}, - {17074682502481951390, 207475778444049647}, - {6281048372501740465, 165980622755239718}, - {6360328581260874421, 265568996408383549}, - {8777611679750609860, 212455197126706839}, - {10711438158542398211, 169964157701365471}, - {9759603424184016492, 271942652322184754}, - {11497031554089123517, 217554121857747803}, - {16576322872755119460, 174043297486198242}, - {11764721337440549842, 278469275977917188}, - {16790474699436260520, 222775420782333750}, - {13432379759549008416, 178220336625867000}, - {3045063541568861850, 285152538601387201}, - {17193446092222730773, 228122030881109760}, - {13754756873778184618, 182497624704887808}, - {18382503128506368341, 145998099763910246}, - {3586563302416817083, 233596959622256395}, - {2869250641933453667, 186877567697805116}, - {17052795772514404226, 149502054158244092}, - {12527077977055405469, 239203286653190548}, - {17400360011128145022, 191362629322552438}, - {2852241564676785048, 153090103458041951}, - {15631632947708587046, 244944165532867121}, - {8815957543424959314, 195955332426293697}, - {18120812478965698421, 156764265941034957}, - {14235904707377476180, 250822825505655932}, - {4010026136418160298, 200658260404524746}, - {17965416168102169531, 160526608323619796}, - {2919224165770098987, 256842573317791675}, - {2335379332616079190, 205474058654233340}, - {1868303466092863352, 164379246923386672}, - {6678634360490491686, 263006795077418675}, - {5342907488392393349, 210405436061934940}, - {4274325990713914679, 168324348849547952}, - {10528270399884173809, 269318958159276723}, - {15801313949391159694, 215455166527421378}, - {1573004715287196786, 172364133221937103}, - {17274202803427156150, 275782613155099364}, - {17508711057483635243, 220626090524079491}, - {10317620031244997871, 176500872419263593}, - {12818843235250086271, 282401395870821749}, - {13944423402941979340, 225921116696657399}, - {14844887537095493795, 180736893357325919}, - {15565258844418305359, 144589514685860735}, - {6457670077359736959, 231343223497377177}, - {16234182506113520537, 185074578797901741}, - {9297997190148906106, 148059663038321393}, - {11187446689496339446, 236895460861314229}, - {12639306166338981880, 189516368689051383}, - {17490142562555006151, 151613094951241106}, - {2158786396894637579, 242580951921985771}, - {16484424376483351356, 194064761537588616}, - {9498190686444770762, 155251809230070893}, - {11507756283569722895, 248402894768113429}, - {12895553841597688639, 198722315814490743}, - {17695140702761971558, 158977852651592594}, - {17244178680193423523, 254364564242548151}, - {10105994129412828495, 203491651394038521}, - {4395446488788352473, 162793321115230817}, - {10722063196803274280, 260469313784369307}, - {1198952927958798777, 208375451027495446}, - {15716557601334680315, 166700360821996356}, - {17767794532651667857, 266720577315194170}, - {14214235626121334286, 213376461852155336}, - {7682039686155157106, 170701169481724269}, - {1223217053622520399, 273121871170758831}, - {15735968901865657612, 218497496936607064}, - {16278123936234436413, 174797997549285651}, - {219556594781725998, 279676796078857043}, - {7554342905309201445, 223741436863085634}, - {9732823138989271479, 178993149490468507}, - {815121763415193074, 286389039184749612}, - {11720143854957885429, 229111231347799689}, - {13065463898708218666, 183288985078239751}, - {6763022304224664610, 146631188062591801}, - {3442138057275642729, 234609900900146882}, - {13821756890046245153, 187687920720117505}, - {11057405512036996122, 150150336576094004}, - {6623802375033462826, 240240538521750407}, - {16367088344252501231, 192192430817400325}, - {13093670675402000985, 153753944653920260}, - {2503129006933649959, 246006311446272417}, - {13070549649772650937, 196805049157017933}, - {17835137349301941396, 157444039325614346}, - {2710778055689733971, 251910462920982955}, - {2168622444551787177, 201528370336786364}, - {5424246770383340065, 161222696269429091}, - {1300097203129523457, 257956314031086546}, - {15797473021471260058, 206365051224869236}, - {8948629602435097724, 165092040979895389}, - {3249760919670425388, 264147265567832623}, - {9978506365220160957, 211317812454266098}, - {15361502721659949412, 169054249963412878}, - {2442311466204457120, 270486799941460606}, - {16711244431931206989, 216389439953168484}, - {17058344360286875914, 173111551962534787}, - {12535955717491360170, 276978483140055660}, - {10028764573993088136, 221582786512044528}, - {15401709288678291155, 177266229209635622}, - {9885339602917624555, 283625966735416996}, - {4218922867592189321, 226900773388333597}, - {14443184738299482427, 181520618710666877}, - {4175850161155765295, 145216494968533502}, - {10370709072591134795, 232346391949653603}, - {15675264887556728482, 185877113559722882}, - {5161514280561562140, 148701690847778306}, - {879725219414678777, 237922705356445290}, - {703780175531743021, 190338164285156232}, - {11631070584651125387, 152270531428124985}, - {162968861732249003, 243632850284999977}, - {11198421533611530172, 194906280227999981}, - {5269388412147313814, 155925024182399985}, - {8431021459435702103, 249480038691839976}, - {3055468352806651359, 199584030953471981}, - {17201769941212962380, 159667224762777584}, - {16454785461715008838, 255467559620444135}, - {13163828369372007071, 204374047696355308}, - {17909760324981426303, 163499238157084246}, - {2830174816776909822, 261598781051334795}, - {2264139853421527858, 209279024841067836}, - {16568707141704863579, 167423219872854268}, - {4373838538276319787, 267877151796566830}, - {3499070830621055830, 214301721437253464}, - {6488605479238754987, 171441377149802771}, - {3003071137298187333, 274306203439684434}, - {6091805724580460189, 219444962751747547}, - {15941491023890099121, 175555970201398037}, - {10748990379256517301, 280889552322236860}, - {8599192303405213841, 224711641857789488}, - {14258051472207991719, 179769313486231590}, -} diff --git a/examples/gno.land/r/gov/dao/gno.mod b/examples/gno.land/p/demo/membstore/gno.mod similarity index 54% rename from examples/gno.land/r/gov/dao/gno.mod rename to examples/gno.land/p/demo/membstore/gno.mod index f3c0bae990e..da22a8dcae4 100644 --- a/examples/gno.land/r/gov/dao/gno.mod +++ b/examples/gno.land/p/demo/membstore/gno.mod @@ -1,8 +1,9 @@ -module gno.land/r/gov/dao +module gno.land/p/demo/membstore require ( + gno.land/p/demo/avl v0.0.0-latest gno.land/p/demo/testutils v0.0.0-latest + gno.land/p/demo/uassert v0.0.0-latest gno.land/p/demo/ufmt v0.0.0-latest gno.land/p/demo/urequire v0.0.0-latest - gno.land/p/gov/proposal v0.0.0-latest ) diff --git a/examples/gno.land/p/demo/membstore/members.gno b/examples/gno.land/p/demo/membstore/members.gno new file mode 100644 index 00000000000..0bbaaaa8b04 --- /dev/null +++ b/examples/gno.land/p/demo/membstore/members.gno @@ -0,0 +1,38 @@ +package membstore + +import ( + "std" +) + +// MemberStore defines the member storage abstraction +type MemberStore interface { + // Members returns all members in the store + Members(offset, count uint64) []Member + + // Size returns the current size of the store + Size() int + + // IsMember returns a flag indicating if the given address + // belongs to a member + IsMember(address std.Address) bool + + // TotalPower returns the total voting power of the member store + TotalPower() uint64 + + // Member returns the requested member + Member(address std.Address) (Member, error) + + // AddMember adds a member to the store + AddMember(member Member) error + + // UpdateMember updates the member in the store. + // If updating a member's voting power to 0, + // the member will be removed + UpdateMember(address std.Address, member Member) error +} + +// Member holds the relevant member information +type Member struct { + Address std.Address // bech32 gno address of the member (unique) + VotingPower uint64 // the voting power of the member +} diff --git a/examples/gno.land/p/demo/membstore/membstore.gno b/examples/gno.land/p/demo/membstore/membstore.gno new file mode 100644 index 00000000000..6e1932978d9 --- /dev/null +++ b/examples/gno.land/p/demo/membstore/membstore.gno @@ -0,0 +1,209 @@ +package membstore + +import ( + "errors" + "std" + + "gno.land/p/demo/avl" + "gno.land/p/demo/ufmt" +) + +var ( + ErrAlreadyMember = errors.New("address is already a member") + ErrMissingMember = errors.New("address is not a member") + ErrInvalidAddressUpdate = errors.New("invalid address update") + ErrNotGovDAO = errors.New("caller not correct govdao instance") +) + +// maxRequestMembers is the maximum number of +// paginated members that can be requested +const maxRequestMembers = 50 + +type Option func(*MembStore) + +// WithInitialMembers initializes the member store +// with an initial member list +func WithInitialMembers(members []Member) Option { + return func(store *MembStore) { + for _, m := range members { + memberAddr := m.Address.String() + + // Check if the member already exists + if store.members.Has(memberAddr) { + panic(ufmt.Errorf("%s, %s", memberAddr, ErrAlreadyMember)) + } + + store.members.Set(memberAddr, m) + store.totalVotingPower += m.VotingPower + } + } +} + +// WithDAOPkgPath initializes the member store +// with a dao package path guard +func WithDAOPkgPath(daoPkgPath string) Option { + return func(store *MembStore) { + store.daoPkgPath = daoPkgPath + } +} + +// MembStore implements the dao.MembStore abstraction +type MembStore struct { + daoPkgPath string // active dao pkg path, if any + members *avl.Tree // std.Address -> Member + totalVotingPower uint64 // cached value for quick lookups +} + +// NewMembStore creates a new member store +func NewMembStore(opts ...Option) *MembStore { + m := &MembStore{ + members: avl.NewTree(), // empty set + daoPkgPath: "", // no dao guard + totalVotingPower: 0, + } + + // Apply the options + for _, opt := range opts { + opt(m) + } + + return m +} + +// AddMember adds member to the member store `m`. +// It fails if the caller is not GovDAO or +// if the member is already present +func (m *MembStore) AddMember(member Member) error { + if !m.isCallerDAORealm() { + return ErrNotGovDAO + } + + // Check if the member exists + if m.IsMember(member.Address) { + return ErrAlreadyMember + } + + // Add the member + m.members.Set(member.Address.String(), member) + + // Update the total voting power + m.totalVotingPower += member.VotingPower + + return nil +} + +// UpdateMember updates the member with the given address. +// Updating fails if the caller is not GovDAO. +func (m *MembStore) UpdateMember(address std.Address, member Member) error { + if !m.isCallerDAORealm() { + return ErrNotGovDAO + } + + // Get the member + oldMember, err := m.Member(address) + if err != nil { + return err + } + + // Check if this is a removal request + if member.VotingPower == 0 { + m.members.Remove(address.String()) + + // Update the total voting power + m.totalVotingPower -= oldMember.VotingPower + + return nil + } + + // Check that the member wouldn't be + // overwriting an existing one + isAddressUpdate := address != member.Address + if isAddressUpdate && m.IsMember(member.Address) { + return ErrInvalidAddressUpdate + } + + // Remove the old member info + // in case the address changed + if address != member.Address { + m.members.Remove(address.String()) + } + + // Save the new member info + m.members.Set(member.Address.String(), member) + + // Update the total voting power + difference := member.VotingPower - oldMember.VotingPower + m.totalVotingPower += difference + + return nil +} + +// IsMember returns a flag indicating if the given +// address belongs to a member of the member store +func (m *MembStore) IsMember(address std.Address) bool { + _, exists := m.members.Get(address.String()) + + return exists +} + +// Member returns the member associated with the given address +func (m *MembStore) Member(address std.Address) (Member, error) { + member, exists := m.members.Get(address.String()) + if !exists { + return Member{}, ErrMissingMember + } + + return member.(Member), nil +} + +// Members returns a paginated list of members from +// the member store. If the store is empty, an empty slice +// is returned instead +func (m *MembStore) Members(offset, count uint64) []Member { + // Calculate the left and right bounds + if count < 1 || offset >= uint64(m.members.Size()) { + return []Member{} + } + + // Limit the maximum number of returned members + if count > maxRequestMembers { + count = maxRequestMembers + } + + // Gather the members + members := make([]Member, 0) + m.members.IterateByOffset( + int(offset), + int(count), + func(_ string, val interface{}) bool { + member := val.(Member) + + // Save the member + members = append(members, member) + + return false + }) + + return members +} + +// Size returns the number of active members in the member store +func (m *MembStore) Size() int { + return m.members.Size() +} + +// TotalPower returns the total voting power +// of the member store +func (m *MembStore) TotalPower() uint64 { + return m.totalVotingPower +} + +// isCallerDAORealm returns a flag indicating if the +// current caller context is the active DAO Realm. +// We need to include a dao guard, even if the +// executor guarantees it, because +// the API of the member store is public and callable +// by anyone who has a reference to the member store instance. +func (m *MembStore) isCallerDAORealm() bool { + return m.daoPkgPath == "" || std.CurrentRealm().PkgPath() == m.daoPkgPath +} diff --git a/examples/gno.land/p/demo/membstore/membstore_test.gno b/examples/gno.land/p/demo/membstore/membstore_test.gno new file mode 100644 index 00000000000..2181adde077 --- /dev/null +++ b/examples/gno.land/p/demo/membstore/membstore_test.gno @@ -0,0 +1,317 @@ +package membstore + +import ( + "testing" + + "std" + + "gno.land/p/demo/testutils" + "gno.land/p/demo/uassert" + "gno.land/p/demo/ufmt" + "gno.land/p/demo/urequire" +) + +// generateMembers generates dummy govdao members +func generateMembers(t *testing.T, count int) []Member { + t.Helper() + + members := make([]Member, 0, count) + + for i := 0; i < count; i++ { + members = append(members, Member{ + Address: testutils.TestAddress(ufmt.Sprintf("member %d", i)), + VotingPower: 10, + }) + } + + return members +} + +func TestMembStore_GetMember(t *testing.T) { + t.Parallel() + + t.Run("member not found", func(t *testing.T) { + t.Parallel() + + // Create an empty store + m := NewMembStore() + + _, err := m.Member(testutils.TestAddress("random")) + uassert.ErrorIs(t, err, ErrMissingMember) + }) + + t.Run("valid member fetched", func(t *testing.T) { + t.Parallel() + + // Create a non-empty store + members := generateMembers(t, 1) + + m := NewMembStore(WithInitialMembers(members)) + + _, err := m.Member(members[0].Address) + uassert.NoError(t, err) + }) +} + +func TestMembStore_GetMembers(t *testing.T) { + t.Parallel() + + t.Run("no members", func(t *testing.T) { + t.Parallel() + + // Create an empty store + m := NewMembStore() + + members := m.Members(0, 10) + uassert.Equal(t, 0, len(members)) + }) + + t.Run("proper pagination", func(t *testing.T) { + t.Parallel() + + var ( + numMembers = maxRequestMembers * 2 + halfRange = numMembers / 2 + + members = generateMembers(t, numMembers) + m = NewMembStore(WithInitialMembers(members)) + + verifyMembersPresent = func(members, fetchedMembers []Member) { + for _, fetchedMember := range fetchedMembers { + for _, member := range members { + if member.Address != fetchedMember.Address { + continue + } + + uassert.Equal(t, member.VotingPower, fetchedMember.VotingPower) + } + } + } + ) + + urequire.Equal(t, numMembers, m.Size()) + + fetchedMembers := m.Members(0, uint64(halfRange)) + urequire.Equal(t, halfRange, len(fetchedMembers)) + + // Verify the members + verifyMembersPresent(members, fetchedMembers) + + // Fetch the other half + fetchedMembers = m.Members(uint64(halfRange), uint64(halfRange)) + urequire.Equal(t, halfRange, len(fetchedMembers)) + + // Verify the members + verifyMembersPresent(members, fetchedMembers) + }) +} + +func TestMembStore_IsMember(t *testing.T) { + t.Parallel() + + t.Run("non-existing member", func(t *testing.T) { + t.Parallel() + + // Create an empty store + m := NewMembStore() + + uassert.False(t, m.IsMember(testutils.TestAddress("random"))) + }) + + t.Run("existing member", func(t *testing.T) { + t.Parallel() + + // Create a non-empty store + members := generateMembers(t, 50) + + m := NewMembStore(WithInitialMembers(members)) + + for _, member := range members { + uassert.True(t, m.IsMember(member.Address)) + } + }) +} + +func TestMembStore_AddMember(t *testing.T) { + t.Parallel() + + t.Run("caller not govdao", func(t *testing.T) { + t.Parallel() + + // Create an empty store + m := NewMembStore(WithDAOPkgPath("gno.land/r/gov/dao")) + + // Attempt to add a member + member := generateMembers(t, 1)[0] + uassert.ErrorIs(t, m.AddMember(member), ErrNotGovDAO) + }) + + t.Run("member already exists", func(t *testing.T) { + t.Parallel() + + var ( + // Execute as the /r/gov/dao caller + daoPkgPath = "gno.land/r/gov/dao" + r = std.NewCodeRealm(daoPkgPath) + ) + + std.TestSetRealm(r) + + // Create a non-empty store + members := generateMembers(t, 1) + m := NewMembStore(WithDAOPkgPath(daoPkgPath), WithInitialMembers(members)) + + // Attempt to add a member + uassert.ErrorIs(t, m.AddMember(members[0]), ErrAlreadyMember) + }) + + t.Run("new member added", func(t *testing.T) { + t.Parallel() + + var ( + // Execute as the /r/gov/dao caller + daoPkgPath = "gno.land/r/gov/dao" + r = std.NewCodeRealm(daoPkgPath) + ) + + std.TestSetRealm(r) + + // Create an empty store + members := generateMembers(t, 1) + m := NewMembStore(WithDAOPkgPath(daoPkgPath)) + + // Attempt to add a member + urequire.NoError(t, m.AddMember(members[0])) + + // Make sure the member is added + uassert.True(t, m.IsMember(members[0].Address)) + }) +} + +func TestMembStore_Size(t *testing.T) { + t.Parallel() + + t.Run("empty govdao", func(t *testing.T) { + t.Parallel() + + // Create an empty store + m := NewMembStore() + + uassert.Equal(t, 0, m.Size()) + }) + + t.Run("non-empty govdao", func(t *testing.T) { + t.Parallel() + + // Create a non-empty store + members := generateMembers(t, 50) + m := NewMembStore(WithInitialMembers(members)) + + uassert.Equal(t, len(members), m.Size()) + }) +} + +func TestMembStore_UpdateMember(t *testing.T) { + t.Parallel() + + t.Run("caller not govdao", func(t *testing.T) { + t.Parallel() + + // Create an empty store + m := NewMembStore(WithDAOPkgPath("gno.land/r/gov/dao")) + + // Attempt to update a member + member := generateMembers(t, 1)[0] + uassert.ErrorIs(t, m.UpdateMember(member.Address, member), ErrNotGovDAO) + }) + + t.Run("non-existing member", func(t *testing.T) { + t.Parallel() + + var ( + // Execute as the /r/gov/dao caller + daoPkgPath = "gno.land/r/gov/dao" + r = std.NewCodeRealm(daoPkgPath) + ) + + std.TestSetRealm(r) + + // Create an empty store + members := generateMembers(t, 1) + m := NewMembStore(WithDAOPkgPath(daoPkgPath)) + + // Attempt to update a member + uassert.ErrorIs(t, m.UpdateMember(members[0].Address, members[0]), ErrMissingMember) + }) + + t.Run("overwrite member attempt", func(t *testing.T) { + t.Parallel() + + var ( + // Execute as the /r/gov/dao caller + daoPkgPath = "gno.land/r/gov/dao" + r = std.NewCodeRealm(daoPkgPath) + ) + + std.TestSetRealm(r) + + // Create a non-empty store + members := generateMembers(t, 2) + m := NewMembStore(WithDAOPkgPath(daoPkgPath), WithInitialMembers(members)) + + // Attempt to update a member + uassert.ErrorIs(t, m.UpdateMember(members[0].Address, members[1]), ErrInvalidAddressUpdate) + }) + + t.Run("successful update", func(t *testing.T) { + t.Parallel() + + var ( + // Execute as the /r/gov/dao caller + daoPkgPath = "gno.land/r/gov/dao" + r = std.NewCodeRealm(daoPkgPath) + ) + + std.TestSetRealm(r) + + // Create a non-empty store + members := generateMembers(t, 1) + m := NewMembStore(WithDAOPkgPath(daoPkgPath), WithInitialMembers(members)) + + oldVotingPower := m.totalVotingPower + urequire.Equal(t, members[0].VotingPower, oldVotingPower) + + votingPower := uint64(300) + members[0].VotingPower = votingPower + + // Attempt to update a member + uassert.NoError(t, m.UpdateMember(members[0].Address, members[0])) + uassert.Equal(t, votingPower, m.Members(0, 10)[0].VotingPower) + urequire.Equal(t, votingPower, m.totalVotingPower) + }) + + t.Run("member removed", func(t *testing.T) { + t.Parallel() + + var ( + // Execute as the /r/gov/dao caller + daoPkgPath = "gno.land/r/gov/dao" + r = std.NewCodeRealm(daoPkgPath) + ) + + std.TestSetRealm(r) + + // Create a non-empty store + members := generateMembers(t, 1) + m := NewMembStore(WithDAOPkgPath(daoPkgPath), WithInitialMembers(members)) + + votingPower := uint64(0) + members[0].VotingPower = votingPower + + // Attempt to update a member + uassert.NoError(t, m.UpdateMember(members[0].Address, members[0])) + + // Make sure the member was removed + uassert.False(t, m.IsMember(members[0].Address)) + }) +} diff --git a/examples/gno.land/p/demo/ownable/ownable_test.gno b/examples/gno.land/p/demo/ownable/ownable_test.gno index a9d97154f45..dee40fa6e1d 100644 --- a/examples/gno.land/p/demo/ownable/ownable_test.gno +++ b/examples/gno.land/p/demo/ownable/ownable_test.gno @@ -33,15 +33,6 @@ func TestNewWithAddress(t *testing.T) { } } -func TestOwner(t *testing.T) { - std.TestSetRealm(std.NewUserRealm(alice)) - - o := New() - expected := alice - got := o.Owner() - uassert.Equal(t, expected, got) -} - func TestTransferOwnership(t *testing.T) { std.TestSetRealm(std.NewUserRealm(alice)) diff --git a/examples/gno.land/p/demo/simpledao/dao.gno b/examples/gno.land/p/demo/simpledao/dao.gno new file mode 100644 index 00000000000..7a20237ec3f --- /dev/null +++ b/examples/gno.land/p/demo/simpledao/dao.gno @@ -0,0 +1,215 @@ +package simpledao + +import ( + "errors" + "std" + + "gno.land/p/demo/avl" + "gno.land/p/demo/dao" + "gno.land/p/demo/membstore" + "gno.land/p/demo/ufmt" +) + +var ( + ErrInvalidExecutor = errors.New("invalid executor provided") + ErrInsufficientProposalFunds = errors.New("insufficient funds for proposal") + ErrInsufficientExecuteFunds = errors.New("insufficient funds for executing proposal") + ErrProposalExecuted = errors.New("proposal already executed") + ErrProposalInactive = errors.New("proposal is inactive") + ErrProposalNotAccepted = errors.New("proposal is not accepted") +) + +var ( + minProposalFeeValue int64 = 100 * 1_000_000 // minimum gnot required for a govdao proposal (100 GNOT) + minExecuteFeeValue int64 = 500 * 1_000_000 // minimum gnot required for a govdao proposal (500 GNOT) + + minProposalFee = std.NewCoin("ugnot", minProposalFeeValue) + minExecuteFee = std.NewCoin("ugnot", minExecuteFeeValue) +) + +// SimpleDAO is a simple DAO implementation +type SimpleDAO struct { + proposals *avl.Tree // seqid.ID -> proposal + membStore membstore.MemberStore +} + +// New creates a new instance of the simpledao DAO +func New(membStore membstore.MemberStore) *SimpleDAO { + return &SimpleDAO{ + proposals: avl.NewTree(), + membStore: membStore, + } +} + +func (s *SimpleDAO) Propose(request dao.ProposalRequest) (uint64, error) { + // Make sure the executor is set + if request.Executor == nil { + return 0, ErrInvalidExecutor + } + + var ( + caller = getDAOCaller() + sentCoins = std.GetOrigSend() // Get the sent coins, if any + canCoverFee = sentCoins.AmountOf("ugnot") >= minProposalFee.Amount + ) + + // Check if the proposal is valid + if !s.membStore.IsMember(caller) && !canCoverFee { + return 0, ErrInsufficientProposalFunds + } + + // Create the wrapped proposal + prop := &proposal{ + author: caller, + description: request.Description, + executor: request.Executor, + status: dao.Active, + tally: newTally(), + getTotalVotingPowerFn: s.membStore.TotalPower, + } + + // Add the proposal + id, err := s.addProposal(prop) + if err != nil { + return 0, ufmt.Errorf("unable to add proposal, %s", err.Error()) + } + + // Emit the proposal added event + dao.EmitProposalAdded(id, caller) + + return id, nil +} + +func (s *SimpleDAO) VoteOnProposal(id uint64, option dao.VoteOption) error { + // Verify the GOVDAO member + caller := getDAOCaller() + + member, err := s.membStore.Member(caller) + if err != nil { + return ufmt.Errorf("unable to get govdao member, %s", err.Error()) + } + + // Check if the proposal exists + propRaw, err := s.ProposalByID(id) + if err != nil { + return ufmt.Errorf("unable to get proposal %d, %s", id, err.Error()) + } + + prop := propRaw.(*proposal) + + // Check the proposal status + if prop.Status() == dao.ExecutionSuccessful || + prop.Status() == dao.ExecutionFailed { + // Proposal was already executed, nothing to vote on anymore. + // + // In fact, the proposal should stop accepting + // votes as soon as a 2/3+ majority is reached + // on either option, but leaving the ability to vote still, + // even if a proposal is accepted, or not accepted, + // leaves room for "principle" vote decisions to be recorded + return ErrProposalInactive + } + + // Cast the vote + if err = prop.tally.castVote(member, option); err != nil { + return ufmt.Errorf("unable to vote on proposal %d, %s", id, err.Error()) + } + + // Emit the vote cast event + dao.EmitVoteAdded(id, caller, option) + + // Check the votes to see if quorum is reached + var ( + totalPower = s.membStore.TotalPower() + majorityPower = (2 * totalPower) / 3 + ) + + acceptProposal := func() { + prop.status = dao.Accepted + + dao.EmitProposalAccepted(id) + } + + declineProposal := func() { + prop.status = dao.NotAccepted + + dao.EmitProposalNotAccepted(id) + } + + switch { + case prop.tally.yays > majorityPower: + // 2/3+ voted YES + acceptProposal() + case prop.tally.nays > majorityPower: + // 2/3+ voted NO + declineProposal() + case prop.tally.abstains > majorityPower: + // 2/3+ voted ABSTAIN + declineProposal() + case prop.tally.yays+prop.tally.nays+prop.tally.abstains >= totalPower: + // Everyone voted, but it's undecided, + // hence the proposal can't go through + declineProposal() + default: + // Quorum not reached + } + + return nil +} + +func (s *SimpleDAO) ExecuteProposal(id uint64) error { + var ( + caller = getDAOCaller() + sentCoins = std.GetOrigSend() // Get the sent coins, if any + canCoverFee = sentCoins.AmountOf("ugnot") >= minExecuteFee.Amount + ) + + // Check if the non-DAO member can cover the execute fee + if !s.membStore.IsMember(caller) && !canCoverFee { + return ErrInsufficientExecuteFunds + } + + // Check if the proposal exists + propRaw, err := s.ProposalByID(id) + if err != nil { + return ufmt.Errorf("unable to get proposal %d, %s", id, err.Error()) + } + + prop := propRaw.(*proposal) + + // Check if the proposal is executed + if prop.Status() == dao.ExecutionSuccessful || + prop.Status() == dao.ExecutionFailed { + // Proposal is already executed + return ErrProposalExecuted + } + + // Check the proposal status + if prop.Status() != dao.Accepted { + // Proposal is not accepted, cannot be executed + return ErrProposalNotAccepted + } + + // Emit an event when the execution finishes + defer dao.EmitProposalExecuted(id, prop.status) + + // Attempt to execute the proposal + if err = prop.executor.Execute(); err != nil { + prop.status = dao.ExecutionFailed + + return ufmt.Errorf("error during proposal %d execution, %s", id, err.Error()) + } + + // Update the proposal status + prop.status = dao.ExecutionSuccessful + + return nil +} + +// getDAOCaller returns the DAO caller. +// XXX: This is not a great way to determine the caller, and it is very unsafe. +// However, the current MsgRun context does not persist escaping the main() scope. +// Until a better solution is developed, this enables proposals to be made through a package deployment + init() +func getDAOCaller() std.Address { + return std.GetOrigCaller() +} diff --git a/examples/gno.land/p/demo/simpledao/dao_test.gno b/examples/gno.land/p/demo/simpledao/dao_test.gno new file mode 100644 index 00000000000..fb32895e72f --- /dev/null +++ b/examples/gno.land/p/demo/simpledao/dao_test.gno @@ -0,0 +1,829 @@ +package simpledao + +import ( + "errors" + "std" + "testing" + + "gno.land/p/demo/dao" + "gno.land/p/demo/membstore" + "gno.land/p/demo/testutils" + "gno.land/p/demo/uassert" + "gno.land/p/demo/ufmt" + "gno.land/p/demo/urequire" +) + +// generateMembers generates dummy govdao members +func generateMembers(t *testing.T, count int) []membstore.Member { + t.Helper() + + members := make([]membstore.Member, 0, count) + + for i := 0; i < count; i++ { + members = append(members, membstore.Member{ + Address: testutils.TestAddress(ufmt.Sprintf("member %d", i)), + VotingPower: 10, + }) + } + + return members +} + +func TestSimpleDAO_Propose(t *testing.T) { + t.Parallel() + + t.Run("invalid executor", func(t *testing.T) { + t.Parallel() + + s := New(nil) + + _, err := s.Propose(dao.ProposalRequest{}) + uassert.ErrorIs( + t, + err, + ErrInvalidExecutor, + ) + }) + + t.Run("caller cannot cover fee", func(t *testing.T) { + t.Parallel() + + var ( + called = false + cb = func() error { + called = true + + return nil + } + ex = &mockExecutor{ + executeFn: cb, + } + + sentCoins = std.NewCoins( + std.NewCoin( + "ugnot", + minProposalFeeValue-1, + ), + ) + + ms = &mockMemberStore{ + isMemberFn: func(_ std.Address) bool { + return false + }, + } + s = New(ms) + ) + + // Set the sent coins to be lower + // than the proposal fee + std.TestSetOrigSend(sentCoins, std.Coins{}) + + _, err := s.Propose(dao.ProposalRequest{ + Executor: ex, + }) + uassert.ErrorIs( + t, + err, + ErrInsufficientProposalFunds, + ) + + uassert.False(t, called) + }) + + t.Run("proposal added", func(t *testing.T) { + t.Parallel() + + var ( + called = false + cb = func() error { + called = true + + return nil + } + + ex = &mockExecutor{ + executeFn: cb, + } + description = "Proposal description" + + proposer = testutils.TestAddress("proposer") + sentCoins = std.NewCoins( + std.NewCoin( + "ugnot", + minProposalFeeValue, // enough to cover + ), + ) + + ms = &mockMemberStore{ + isMemberFn: func(addr std.Address) bool { + return addr == proposer + }, + } + s = New(ms) + ) + + // Set the sent coins to be enough + // to cover the fee + std.TestSetOrigSend(sentCoins, std.Coins{}) + std.TestSetOrigCaller(proposer) + + // Make sure the proposal was added + id, err := s.Propose(dao.ProposalRequest{ + Description: description, + Executor: ex, + }) + uassert.NoError(t, err) + uassert.False(t, called) + + // Make sure the proposal exists + prop, err := s.ProposalByID(id) + uassert.NoError(t, err) + + uassert.Equal(t, proposer.String(), prop.Author().String()) + uassert.Equal(t, description, prop.Description()) + uassert.Equal(t, dao.Active.String(), prop.Status().String()) + + stats := prop.Stats() + + uassert.Equal(t, uint64(0), stats.YayVotes) + uassert.Equal(t, uint64(0), stats.NayVotes) + uassert.Equal(t, uint64(0), stats.AbstainVotes) + uassert.Equal(t, uint64(0), stats.TotalVotingPower) + }) +} + +func TestSimpleDAO_VoteOnProposal(t *testing.T) { + t.Parallel() + + t.Run("not govdao member", func(t *testing.T) { + t.Parallel() + + var ( + voter = testutils.TestAddress("voter") + fetchErr = errors.New("fetch error") + + ms = &mockMemberStore{ + memberFn: func(_ std.Address) (membstore.Member, error) { + return membstore.Member{ + Address: voter, + }, fetchErr + }, + } + s = New(ms) + ) + + std.TestSetOrigCaller(voter) + + // Attempt to vote on the proposal + uassert.ErrorContains( + t, + s.VoteOnProposal(0, dao.YesVote), + fetchErr.Error(), + ) + }) + + t.Run("missing proposal", func(t *testing.T) { + t.Parallel() + + var ( + voter = testutils.TestAddress("voter") + ms = &mockMemberStore{ + memberFn: func(a std.Address) (membstore.Member, error) { + if a != voter { + return membstore.Member{}, errors.New("not found") + } + + return membstore.Member{ + Address: voter, + }, nil + }, + } + + s = New(ms) + ) + + std.TestSetOrigCaller(voter) + + // Attempt to vote on the proposal + uassert.ErrorContains( + t, + s.VoteOnProposal(0, dao.YesVote), + ErrMissingProposal.Error(), + ) + }) + + t.Run("proposal executed", func(t *testing.T) { + t.Parallel() + + var ( + voter = testutils.TestAddress("voter") + + ms = &mockMemberStore{ + memberFn: func(a std.Address) (membstore.Member, error) { + if a != voter { + return membstore.Member{}, errors.New("not found") + } + + return membstore.Member{ + Address: voter, + }, nil + }, + } + s = New(ms) + + prop = &proposal{ + status: dao.ExecutionSuccessful, + } + ) + + std.TestSetOrigCaller(voter) + + // Add an initial proposal + id, err := s.addProposal(prop) + urequire.NoError(t, err) + + // Attempt to vote on the proposal + uassert.ErrorIs( + t, + s.VoteOnProposal(id, dao.YesVote), + ErrProposalInactive, + ) + }) + + t.Run("double vote on proposal", func(t *testing.T) { + t.Parallel() + + var ( + voter = testutils.TestAddress("voter") + member = membstore.Member{ + Address: voter, + VotingPower: 10, + } + + ms = &mockMemberStore{ + memberFn: func(a std.Address) (membstore.Member, error) { + if a != voter { + return membstore.Member{}, errors.New("not found") + } + + return member, nil + }, + } + s = New(ms) + + prop = &proposal{ + status: dao.Active, + executor: &mockExecutor{}, + tally: newTally(), + } + ) + + std.TestSetOrigCaller(voter) + + // Cast the initial vote + urequire.NoError(t, prop.tally.castVote(member, dao.YesVote)) + + // Add an initial proposal + id, err := s.addProposal(prop) + urequire.NoError(t, err) + + // Attempt to vote on the proposal + uassert.ErrorContains( + t, + s.VoteOnProposal(id, dao.YesVote), + ErrAlreadyVoted.Error(), + ) + }) + + t.Run("majority accepted", func(t *testing.T) { + t.Parallel() + + var ( + members = generateMembers(t, 50) + + ms = &mockMemberStore{ + memberFn: func(address std.Address) (membstore.Member, error) { + for _, m := range members { + if m.Address == address { + return m, nil + } + } + + return membstore.Member{}, errors.New("not found") + }, + + totalPowerFn: func() uint64 { + power := uint64(0) + + for _, m := range members { + power += m.VotingPower + } + + return power + }, + } + s = New(ms) + + prop = &proposal{ + status: dao.Active, + executor: &mockExecutor{}, + tally: newTally(), + } + ) + + // Add an initial proposal + id, err := s.addProposal(prop) + urequire.NoError(t, err) + + majorityIndex := (len(members)*2)/3 + 1 // 2/3+ + for _, m := range members[:majorityIndex] { + std.TestSetOrigCaller(m.Address) + + // Attempt to vote on the proposal + urequire.NoError( + t, + s.VoteOnProposal(id, dao.YesVote), + ) + } + + // Make sure the proposal was accepted + uassert.Equal(t, dao.Accepted.String(), prop.status.String()) + }) + + t.Run("majority rejected", func(t *testing.T) { + t.Parallel() + + var ( + members = generateMembers(t, 50) + + ms = &mockMemberStore{ + memberFn: func(address std.Address) (membstore.Member, error) { + for _, m := range members { + if m.Address == address { + return m, nil + } + } + + return membstore.Member{}, errors.New("member not found") + }, + + totalPowerFn: func() uint64 { + power := uint64(0) + + for _, m := range members { + power += m.VotingPower + } + + return power + }, + } + s = New(ms) + + prop = &proposal{ + status: dao.Active, + executor: &mockExecutor{}, + tally: newTally(), + } + ) + + // Add an initial proposal + id, err := s.addProposal(prop) + urequire.NoError(t, err) + + majorityIndex := (len(members)*2)/3 + 1 // 2/3+ + for _, m := range members[:majorityIndex] { + std.TestSetOrigCaller(m.Address) + + // Attempt to vote on the proposal + urequire.NoError( + t, + s.VoteOnProposal(id, dao.NoVote), + ) + } + + // Make sure the proposal was not accepted + uassert.Equal(t, dao.NotAccepted.String(), prop.status.String()) + }) + + t.Run("majority abstained", func(t *testing.T) { + t.Parallel() + + var ( + members = generateMembers(t, 50) + + ms = &mockMemberStore{ + memberFn: func(address std.Address) (membstore.Member, error) { + for _, m := range members { + if m.Address == address { + return m, nil + } + } + + return membstore.Member{}, errors.New("member not found") + }, + + totalPowerFn: func() uint64 { + power := uint64(0) + + for _, m := range members { + power += m.VotingPower + } + + return power + }, + } + s = New(ms) + + prop = &proposal{ + status: dao.Active, + executor: &mockExecutor{}, + tally: newTally(), + } + ) + + // Add an initial proposal + id, err := s.addProposal(prop) + urequire.NoError(t, err) + + majorityIndex := (len(members)*2)/3 + 1 // 2/3+ + for _, m := range members[:majorityIndex] { + std.TestSetOrigCaller(m.Address) + + // Attempt to vote on the proposal + urequire.NoError( + t, + s.VoteOnProposal(id, dao.AbstainVote), + ) + } + + // Make sure the proposal was not accepted + uassert.Equal(t, dao.NotAccepted.String(), prop.status.String()) + }) + + t.Run("everyone voted, undecided", func(t *testing.T) { + t.Parallel() + + var ( + members = generateMembers(t, 50) + + ms = &mockMemberStore{ + memberFn: func(address std.Address) (membstore.Member, error) { + for _, m := range members { + if m.Address == address { + return m, nil + } + } + + return membstore.Member{}, errors.New("member not found") + }, + + totalPowerFn: func() uint64 { + power := uint64(0) + + for _, m := range members { + power += m.VotingPower + } + + return power + }, + } + s = New(ms) + + prop = &proposal{ + status: dao.Active, + executor: &mockExecutor{}, + tally: newTally(), + } + ) + + // Add an initial proposal + id, err := s.addProposal(prop) + urequire.NoError(t, err) + + // The first half votes yes + for _, m := range members[:len(members)/2] { + std.TestSetOrigCaller(m.Address) + + // Attempt to vote on the proposal + urequire.NoError( + t, + s.VoteOnProposal(id, dao.YesVote), + ) + } + + // The other half votes no + for _, m := range members[len(members)/2:] { + std.TestSetOrigCaller(m.Address) + + // Attempt to vote on the proposal + urequire.NoError( + t, + s.VoteOnProposal(id, dao.NoVote), + ) + } + + // Make sure the proposal is not active, + // since everyone voted, and it was undecided + uassert.Equal(t, dao.NotAccepted.String(), prop.status.String()) + }) + + t.Run("proposal undecided", func(t *testing.T) { + t.Parallel() + + var ( + members = generateMembers(t, 50) + + ms = &mockMemberStore{ + memberFn: func(address std.Address) (membstore.Member, error) { + for _, m := range members { + if m.Address == address { + return m, nil + } + } + + return membstore.Member{}, errors.New("member not found") + }, + + totalPowerFn: func() uint64 { + power := uint64(0) + + for _, m := range members { + power += m.VotingPower + } + + return power + }, + } + s = New(ms) + + prop = &proposal{ + status: dao.Active, + executor: &mockExecutor{}, + tally: newTally(), + } + ) + + // Add an initial proposal + id, err := s.addProposal(prop) + urequire.NoError(t, err) + + // The first quarter votes yes + for _, m := range members[:len(members)/4] { + std.TestSetOrigCaller(m.Address) + + // Attempt to vote on the proposal + urequire.NoError( + t, + s.VoteOnProposal(id, dao.YesVote), + ) + } + + // The second quarter votes no + for _, m := range members[len(members)/4 : len(members)/2] { + std.TestSetOrigCaller(m.Address) + + // Attempt to vote on the proposal + urequire.NoError( + t, + s.VoteOnProposal(id, dao.NoVote), + ) + } + + // Make sure the proposal is still active, + // since there wasn't quorum reached on any decision + uassert.Equal(t, dao.Active.String(), prop.status.String()) + }) +} + +func TestSimpleDAO_ExecuteProposal(t *testing.T) { + t.Parallel() + + t.Run("caller cannot cover fee", func(t *testing.T) { + t.Parallel() + + var ( + sentCoins = std.NewCoins( + std.NewCoin( + "ugnot", + minExecuteFeeValue-1, + ), + ) + + ms = &mockMemberStore{ + isMemberFn: func(_ std.Address) bool { + return false + }, + } + s = New(ms) + ) + + // Set the sent coins to be lower + // than the execute fee + std.TestSetOrigSend(sentCoins, std.Coins{}) + + uassert.ErrorIs( + t, + s.ExecuteProposal(0), + ErrInsufficientExecuteFunds, + ) + }) + + t.Run("missing proposal", func(t *testing.T) { + t.Parallel() + + var ( + sentCoins = std.NewCoins( + std.NewCoin( + "ugnot", + minExecuteFeeValue, + ), + ) + + ms = &mockMemberStore{ + isMemberFn: func(_ std.Address) bool { + return true + }, + } + + s = New(ms) + ) + + // Set the sent coins to be enough + // so the execution can take place + std.TestSetOrigSend(sentCoins, std.Coins{}) + + uassert.ErrorContains( + t, + s.ExecuteProposal(0), + ErrMissingProposal.Error(), + ) + }) + + t.Run("proposal not accepted", func(t *testing.T) { + t.Parallel() + + var ( + voter = testutils.TestAddress("voter") + + ms = &mockMemberStore{ + isMemberFn: func(_ std.Address) bool { + return true + }, + } + s = New(ms) + + prop = &proposal{ + status: dao.NotAccepted, + } + ) + + std.TestSetOrigCaller(voter) + + // Add an initial proposal + id, err := s.addProposal(prop) + urequire.NoError(t, err) + + // Attempt to vote on the proposal + uassert.ErrorIs( + t, + s.ExecuteProposal(id), + ErrProposalNotAccepted, + ) + }) + + t.Run("proposal already executed", func(t *testing.T) { + t.Parallel() + + testTable := []struct { + name string + status dao.ProposalStatus + }{ + { + "execution was successful", + dao.ExecutionSuccessful, + }, + { + "execution failed", + dao.ExecutionFailed, + }, + } + + for _, testCase := range testTable { + t.Run(testCase.name, func(t *testing.T) { + t.Parallel() + + var ( + voter = testutils.TestAddress("voter") + + ms = &mockMemberStore{ + isMemberFn: func(_ std.Address) bool { + return true + }, + } + s = New(ms) + + prop = &proposal{ + status: testCase.status, + } + ) + + std.TestSetOrigCaller(voter) + + // Add an initial proposal + id, err := s.addProposal(prop) + urequire.NoError(t, err) + + // Attempt to vote on the proposal + uassert.ErrorIs( + t, + s.ExecuteProposal(id), + ErrProposalExecuted, + ) + }) + } + }) + + t.Run("execution error", func(t *testing.T) { + t.Parallel() + + var ( + voter = testutils.TestAddress("voter") + + ms = &mockMemberStore{ + isMemberFn: func(_ std.Address) bool { + return true + }, + } + + s = New(ms) + + execError = errors.New("exec error") + + mockExecutor = &mockExecutor{ + executeFn: func() error { + return execError + }, + } + + prop = &proposal{ + status: dao.Accepted, + executor: mockExecutor, + } + ) + + std.TestSetOrigCaller(voter) + + // Add an initial proposal + id, err := s.addProposal(prop) + urequire.NoError(t, err) + + // Attempt to vote on the proposal + uassert.ErrorContains( + t, + s.ExecuteProposal(id), + execError.Error(), + ) + + uassert.Equal(t, dao.ExecutionFailed.String(), prop.status.String()) + }) + + t.Run("successful execution", func(t *testing.T) { + t.Parallel() + + var ( + voter = testutils.TestAddress("voter") + + ms = &mockMemberStore{ + isMemberFn: func(_ std.Address) bool { + return true + }, + } + s = New(ms) + + called = false + mockExecutor = &mockExecutor{ + executeFn: func() error { + called = true + + return nil + }, + } + + prop = &proposal{ + status: dao.Accepted, + executor: mockExecutor, + } + ) + + std.TestSetOrigCaller(voter) + + // Add an initial proposal + id, err := s.addProposal(prop) + urequire.NoError(t, err) + + // Attempt to vote on the proposal + uassert.NoError(t, s.ExecuteProposal(id)) + uassert.Equal(t, dao.ExecutionSuccessful.String(), prop.status.String()) + uassert.True(t, called) + }) +} diff --git a/examples/gno.land/p/demo/simpledao/gno.mod b/examples/gno.land/p/demo/simpledao/gno.mod new file mode 100644 index 00000000000..f6f14f379ec --- /dev/null +++ b/examples/gno.land/p/demo/simpledao/gno.mod @@ -0,0 +1,12 @@ +module gno.land/p/demo/simpledao + +require ( + gno.land/p/demo/avl v0.0.0-latest + gno.land/p/demo/dao v0.0.0-latest + gno.land/p/demo/membstore v0.0.0-latest + gno.land/p/demo/seqid v0.0.0-latest + gno.land/p/demo/testutils v0.0.0-latest + gno.land/p/demo/uassert v0.0.0-latest + gno.land/p/demo/ufmt v0.0.0-latest + gno.land/p/demo/urequire v0.0.0-latest +) diff --git a/examples/gno.land/p/demo/simpledao/mock_test.gno b/examples/gno.land/p/demo/simpledao/mock_test.gno new file mode 100644 index 00000000000..0cf12ccff01 --- /dev/null +++ b/examples/gno.land/p/demo/simpledao/mock_test.gno @@ -0,0 +1,97 @@ +package simpledao + +import ( + "std" + + "gno.land/p/demo/membstore" +) + +type executeDelegate func() error + +type mockExecutor struct { + executeFn executeDelegate +} + +func (m *mockExecutor) Execute() error { + if m.executeFn != nil { + return m.executeFn() + } + + return nil +} + +type ( + membersDelegate func(uint64, uint64) []membstore.Member + sizeDelegate func() int + isMemberDelegate func(std.Address) bool + totalPowerDelegate func() uint64 + memberDelegate func(std.Address) (membstore.Member, error) + addMemberDelegate func(membstore.Member) error + updateMemberDelegate func(std.Address, membstore.Member) error +) + +type mockMemberStore struct { + membersFn membersDelegate + sizeFn sizeDelegate + isMemberFn isMemberDelegate + totalPowerFn totalPowerDelegate + memberFn memberDelegate + addMemberFn addMemberDelegate + updateMemberFn updateMemberDelegate +} + +func (m *mockMemberStore) Members(offset, count uint64) []membstore.Member { + if m.membersFn != nil { + return m.membersFn(offset, count) + } + + return nil +} + +func (m *mockMemberStore) Size() int { + if m.sizeFn != nil { + return m.sizeFn() + } + + return 0 +} + +func (m *mockMemberStore) IsMember(address std.Address) bool { + if m.isMemberFn != nil { + return m.isMemberFn(address) + } + + return false +} + +func (m *mockMemberStore) TotalPower() uint64 { + if m.totalPowerFn != nil { + return m.totalPowerFn() + } + + return 0 +} + +func (m *mockMemberStore) Member(address std.Address) (membstore.Member, error) { + if m.memberFn != nil { + return m.memberFn(address) + } + + return membstore.Member{}, nil +} + +func (m *mockMemberStore) AddMember(member membstore.Member) error { + if m.addMemberFn != nil { + return m.addMemberFn(member) + } + + return nil +} + +func (m *mockMemberStore) UpdateMember(address std.Address, member membstore.Member) error { + if m.updateMemberFn != nil { + return m.updateMemberFn(address, member) + } + + return nil +} diff --git a/examples/gno.land/p/demo/simpledao/propstore.gno b/examples/gno.land/p/demo/simpledao/propstore.gno new file mode 100644 index 00000000000..972297ff0ce --- /dev/null +++ b/examples/gno.land/p/demo/simpledao/propstore.gno @@ -0,0 +1,163 @@ +package simpledao + +import ( + "errors" + "std" + + "gno.land/p/demo/dao" + "gno.land/p/demo/seqid" + "gno.land/p/demo/ufmt" +) + +var ErrMissingProposal = errors.New("proposal is missing") + +// maxRequestProposals is the maximum number of +// paginated proposals that can be requested +const maxRequestProposals = 10 + +// proposal is the internal simpledao proposal implementation +type proposal struct { + author std.Address // initiator of the proposal + description string // description of the proposal + + executor dao.Executor // executor for the proposal + status dao.ProposalStatus // status of the proposal + + tally *tally // voting tally + getTotalVotingPowerFn func() uint64 // callback for the total voting power +} + +func (p *proposal) Author() std.Address { + return p.author +} + +func (p *proposal) Description() string { + return p.description +} + +func (p *proposal) Status() dao.ProposalStatus { + return p.status +} + +func (p *proposal) Executor() dao.Executor { + return p.executor +} + +func (p *proposal) Stats() dao.Stats { + // Get the total voting power of the body + totalPower := p.getTotalVotingPowerFn() + + return dao.Stats{ + YayVotes: p.tally.yays, + NayVotes: p.tally.nays, + AbstainVotes: p.tally.abstains, + TotalVotingPower: totalPower, + } +} + +func (p *proposal) IsExpired() bool { + return false // this proposal never expires +} + +func (p *proposal) Render() string { + // Fetch the voting stats + stats := p.Stats() + + output := "" + output += ufmt.Sprintf("Author: %s", p.Author().String()) + output += "\n\n" + output += p.Description() + output += "\n\n" + output += ufmt.Sprintf("Status: %s", p.Status().String()) + output += "\n\n" + output += ufmt.Sprintf( + "Voting stats: YAY %d (%d%%), NAY %d (%d%%), ABSTAIN %d (%d%%), HAVEN'T VOTED %d (%d%%)", + stats.YayVotes, + stats.YayPercent(), + stats.NayVotes, + stats.NayPercent(), + stats.AbstainVotes, + stats.AbstainPercent(), + stats.MissingVotes(), + stats.MissingVotesPercent(), + ) + output += "\n\n" + output += ufmt.Sprintf("Threshold met: %t", stats.YayVotes > (2*stats.TotalVotingPower)/3) + + return output +} + +// addProposal adds a new simpledao proposal to the store +func (s *SimpleDAO) addProposal(proposal *proposal) (uint64, error) { + // See what the next proposal number should be + nextID := uint64(s.proposals.Size()) + + // Save the proposal + s.proposals.Set(getProposalID(nextID), proposal) + + return nextID, nil +} + +func (s *SimpleDAO) Proposals(offset, count uint64) []dao.Proposal { + // Check the requested count + if count < 1 { + return []dao.Proposal{} + } + + // Limit the maximum number of returned proposals + if count > maxRequestProposals { + count = maxRequestProposals + } + + var ( + startIndex = offset + endIndex = startIndex + count + + numProposals = uint64(s.proposals.Size()) + ) + + // Check if the current offset has any proposals + if startIndex >= numProposals { + return []dao.Proposal{} + } + + // Check if the right bound is good + if endIndex > numProposals { + endIndex = numProposals + } + + props := make([]dao.Proposal, 0) + s.proposals.Iterate( + getProposalID(startIndex), + getProposalID(endIndex), + func(_ string, val interface{}) bool { + prop := val.(*proposal) + + // Save the proposal + props = append(props, prop) + + return false + }, + ) + + return props +} + +func (s *SimpleDAO) ProposalByID(id uint64) (dao.Proposal, error) { + prop, exists := s.proposals.Get(getProposalID(id)) + if !exists { + return nil, ErrMissingProposal + } + + return prop.(*proposal), nil +} + +func (s *SimpleDAO) Size() int { + return s.proposals.Size() +} + +// getProposalID generates a sequential proposal ID +// from the given ID number +func getProposalID(id uint64) string { + return seqid.ID(id).String() +} diff --git a/examples/gno.land/p/demo/simpledao/propstore_test.gno b/examples/gno.land/p/demo/simpledao/propstore_test.gno new file mode 100644 index 00000000000..5aa6ba91a1e --- /dev/null +++ b/examples/gno.land/p/demo/simpledao/propstore_test.gno @@ -0,0 +1,256 @@ +package simpledao + +import ( + "testing" + + "gno.land/p/demo/dao" + "gno.land/p/demo/testutils" + "gno.land/p/demo/uassert" + "gno.land/p/demo/ufmt" + "gno.land/p/demo/urequire" +) + +// generateProposals generates dummy proposals +func generateProposals(t *testing.T, count int) []*proposal { + t.Helper() + + var ( + members = generateMembers(t, count) + proposals = make([]*proposal, 0, count) + ) + + for i := 0; i < count; i++ { + proposal := &proposal{ + author: members[i].Address, + description: ufmt.Sprintf("proposal %d", i), + status: dao.Active, + tally: newTally(), + getTotalVotingPowerFn: func() uint64 { + return 0 + }, + executor: nil, + } + + proposals = append(proposals, proposal) + } + + return proposals +} + +func equalProposals(t *testing.T, p1, p2 dao.Proposal) { + t.Helper() + + uassert.Equal( + t, + p1.Author().String(), + p2.Author().String(), + ) + + uassert.Equal( + t, + p1.Description(), + p2.Description(), + ) + + uassert.Equal( + t, + p1.Status().String(), + p2.Status().String(), + ) + + p1Stats := p1.Stats() + p2Stats := p2.Stats() + + uassert.Equal(t, p1Stats.YayVotes, p2Stats.YayVotes) + uassert.Equal(t, p1Stats.NayVotes, p2Stats.NayVotes) + uassert.Equal(t, p1Stats.AbstainVotes, p2Stats.AbstainVotes) + uassert.Equal(t, p1Stats.TotalVotingPower, p2Stats.TotalVotingPower) +} + +func TestProposal_Data(t *testing.T) { + t.Parallel() + + t.Run("author", func(t *testing.T) { + t.Parallel() + + p := &proposal{ + author: testutils.TestAddress("address"), + } + + uassert.Equal(t, p.author, p.Author()) + }) + + t.Run("description", func(t *testing.T) { + t.Parallel() + + p := &proposal{ + description: "example proposal description", + } + + uassert.Equal(t, p.description, p.Description()) + }) + + t.Run("status", func(t *testing.T) { + t.Parallel() + + p := &proposal{ + status: dao.ExecutionSuccessful, + } + + uassert.Equal(t, p.status.String(), p.Status().String()) + }) + + t.Run("executor", func(t *testing.T) { + t.Parallel() + + var ( + numCalled = 0 + cb = func() error { + numCalled++ + + return nil + } + + ex = &mockExecutor{ + executeFn: cb, + } + + p = &proposal{ + executor: ex, + } + ) + + urequire.NoError(t, p.executor.Execute()) + urequire.NoError(t, p.Executor().Execute()) + + uassert.Equal(t, 2, numCalled) + }) + + t.Run("no votes", func(t *testing.T) { + t.Parallel() + + p := &proposal{ + tally: newTally(), + getTotalVotingPowerFn: func() uint64 { + return 0 + }, + } + + stats := p.Stats() + + uassert.Equal(t, uint64(0), stats.YayVotes) + uassert.Equal(t, uint64(0), stats.NayVotes) + uassert.Equal(t, uint64(0), stats.AbstainVotes) + uassert.Equal(t, uint64(0), stats.TotalVotingPower) + }) + + t.Run("existing votes", func(t *testing.T) { + t.Parallel() + + var ( + members = generateMembers(t, 50) + totalPower = uint64(len(members)) * 10 + + p = &proposal{ + tally: newTally(), + getTotalVotingPowerFn: func() uint64 { + return totalPower + }, + } + ) + + for _, m := range members { + urequire.NoError(t, p.tally.castVote(m, dao.YesVote)) + } + + stats := p.Stats() + + uassert.Equal(t, totalPower, stats.YayVotes) + uassert.Equal(t, uint64(0), stats.NayVotes) + uassert.Equal(t, uint64(0), stats.AbstainVotes) + uassert.Equal(t, totalPower, stats.TotalVotingPower) + }) +} + +func TestSimpleDAO_GetProposals(t *testing.T) { + t.Parallel() + + t.Run("no proposals", func(t *testing.T) { + t.Parallel() + + s := New(nil) + + uassert.Equal(t, 0, s.Size()) + proposals := s.Proposals(0, 0) + + uassert.Equal(t, 0, len(proposals)) + }) + + t.Run("proper pagination", func(t *testing.T) { + t.Parallel() + + var ( + numProposals = 20 + halfRange = numProposals / 2 + + s = New(nil) + proposals = generateProposals(t, numProposals) + ) + + // Add initial proposals + for _, proposal := range proposals { + _, err := s.addProposal(proposal) + + urequire.NoError(t, err) + } + + uassert.Equal(t, numProposals, s.Size()) + + fetchedProposals := s.Proposals(0, uint64(halfRange)) + urequire.Equal(t, halfRange, len(fetchedProposals)) + + for index, fetchedProposal := range fetchedProposals { + equalProposals(t, proposals[index], fetchedProposal) + } + + // Fetch the other half + fetchedProposals = s.Proposals(uint64(halfRange), uint64(halfRange)) + urequire.Equal(t, halfRange, len(fetchedProposals)) + + for index, fetchedProposal := range fetchedProposals { + equalProposals(t, proposals[index+halfRange], fetchedProposal) + } + }) +} + +func TestSimpleDAO_GetProposalByID(t *testing.T) { + t.Parallel() + + t.Run("missing proposal", func(t *testing.T) { + t.Parallel() + + s := New(nil) + + _, err := s.ProposalByID(0) + uassert.ErrorIs(t, err, ErrMissingProposal) + }) + + t.Run("proposal found", func(t *testing.T) { + t.Parallel() + + var ( + s = New(nil) + proposal = generateProposals(t, 1)[0] + ) + + // Add the initial proposal + _, err := s.addProposal(proposal) + urequire.NoError(t, err) + + // Fetch the proposal + fetchedProposal, err := s.ProposalByID(0) + urequire.NoError(t, err) + + equalProposals(t, proposal, fetchedProposal) + }) +} diff --git a/examples/gno.land/p/demo/simpledao/votestore.gno b/examples/gno.land/p/demo/simpledao/votestore.gno new file mode 100644 index 00000000000..35a6564a1e3 --- /dev/null +++ b/examples/gno.land/p/demo/simpledao/votestore.gno @@ -0,0 +1,55 @@ +package simpledao + +import ( + "errors" + + "gno.land/p/demo/avl" + "gno.land/p/demo/dao" + "gno.land/p/demo/membstore" +) + +var ErrAlreadyVoted = errors.New("vote already cast") + +// tally is a simple vote tally system +type tally struct { + // tally cache to keep track of active + // yes / no / abstain votes + yays uint64 + nays uint64 + abstains uint64 + + voters *avl.Tree // std.Address -> dao.VoteOption +} + +// newTally creates a new tally system instance +func newTally() *tally { + return &tally{ + voters: avl.NewTree(), + } +} + +// castVote casts a single vote in the name of the given member +func (t *tally) castVote(member membstore.Member, option dao.VoteOption) error { + // Check if the member voted already + address := member.Address.String() + + _, voted := t.voters.Get(address) + if voted { + return ErrAlreadyVoted + } + + // Update the tally + switch option { + case dao.YesVote: + t.yays += member.VotingPower + case dao.AbstainVote: + t.abstains += member.VotingPower + default: + t.nays += member.VotingPower + } + + // Save the voting status + t.voters.Set(address, option) + + return nil +} diff --git a/examples/gno.land/p/demo/uassert/uassert.gno b/examples/gno.land/p/demo/uassert/uassert.gno index 2776e93dca9..f9c0ab3efc8 100644 --- a/examples/gno.land/p/demo/uassert/uassert.gno +++ b/examples/gno.land/p/demo/uassert/uassert.gno @@ -266,7 +266,7 @@ func NotEqual(t TestingT, expected, actual interface{}, msgs ...string) bool { if av, ok := actual.(string); ok { notEqual = ev != av ok_ = true - es, as = ev, as + es, as = ev, av } case std.Address: if av, ok := actual.(std.Address); ok { diff --git a/examples/gno.land/p/demo/uint256/arithmetic_test.gno b/examples/gno.land/p/demo/uint256/arithmetic_test.gno index 9f45a507754..079d89fa794 100644 --- a/examples/gno.land/p/demo/uint256/arithmetic_test.gno +++ b/examples/gno.land/p/demo/uint256/arithmetic_test.gno @@ -1,6 +1,8 @@ package uint256 -import "testing" +import ( + "testing" +) type binOp2Test struct { x, y, want string @@ -16,30 +18,45 @@ func TestAdd(t *testing.T) { {"18446744073709551615", "18446744073709551615", "36893488147419103230"}, // uint64 overflow } - for _, tc := range tests { - x, err := FromDecimal(tc.x) - if err != nil { - t.Error(err) - continue - } + for _, tt := range tests { + x := MustFromDecimal(tt.x) + y := MustFromDecimal(tt.y) - y, err := FromDecimal(tc.y) - if err != nil { - t.Error(err) - continue - } + want := MustFromDecimal(tt.want) + got := new(Uint).Add(x, y) - want, err := FromDecimal(tc.want) - if err != nil { - t.Error(err) - continue + if got.Neq(want) { + t.Errorf("Add(%s, %s) = %v, want %v", tt.x, tt.y, got.ToString(), want.ToString()) } + } +} - got := &Uint{} - got.Add(x, y) +func TestAddOverflow(t *testing.T) { + tests := []struct { + x, y string + want string + overflow bool + }{ + {"0", "1", "1", false}, + {"1", "0", "1", false}, + {"1", "1", "2", false}, + {"10", "10", "20", false}, + {"18446744073709551615", "18446744073709551615", "36893488147419103230", false}, // uint64 overflow, but not Uint256 overflow + {"115792089237316195423570985008687907853269984665640564039457584007913129639935", "1", "0", true}, // 2^256 - 1 + 1, should overflow + {"57896044618658097711785492504343953926634992332820282019728792003956564819967", "57896044618658097711785492504343953926634992332820282019728792003956564819968", "115792089237316195423570985008687907853269984665640564039457584007913129639935", false}, // (2^255 - 1) + 2^255, no overflow + {"57896044618658097711785492504343953926634992332820282019728792003956564819967", "57896044618658097711785492504343953926634992332820282019728792003956564819969", "0", true}, // (2^255 - 1) + (2^255 + 1), should overflow + } - if got.Neq(want) { - t.Errorf("Add(%s, %s) = %v, want %v", tc.x, tc.y, got.ToString(), want.ToString()) + for _, tt := range tests { + x := MustFromDecimal(tt.x) + y := MustFromDecimal(tt.y) + want, _ := FromDecimal(tt.want) + + got, overflow := new(Uint).AddOverflow(x, y) + + if got.Cmp(want) != 0 || overflow != tt.overflow { + t.Errorf("AddOverflow(%s, %s) = (%s, %v), want (%s, %v)", + tt.x, tt.y, got.ToString(), overflow, tt.want, tt.overflow) } } } @@ -50,33 +67,53 @@ func TestSub(t *testing.T) { {"1", "1", "0"}, {"10", "10", "0"}, {"31337", "1337", "30000"}, - {"2", "3", "115792089237316195423570985008687907853269984665640564039457584007913129639935"}, // underflow + {"2", "3", twoPow256Sub1}, // underflow } for _, tc := range tests { - x, err := FromDecimal(tc.x) - if err != nil { - t.Error(err) - continue - } + x := MustFromDecimal(tc.x) + y := MustFromDecimal(tc.y) - y, err := FromDecimal(tc.y) - if err != nil { - t.Error(err) - continue - } + want := MustFromDecimal(tc.want) - want, err := FromDecimal(tc.want) - if err != nil { - t.Error(err) - continue + got := new(Uint).Sub(x, y) + + if got.Neq(want) { + t.Errorf( + "Sub(%s, %s) = %v, want %v", + tc.x, tc.y, got.ToString(), want.ToString(), + ) } + } +} - got := &Uint{} - got.Sub(x, y) +func TestSubOverflow(t *testing.T) { + tests := []struct { + x, y string + want string + overflow bool + }{ + {"1", "0", "1", false}, + {"1", "1", "0", false}, + {"10", "10", "0", false}, + {"31337", "1337", "30000", false}, + {"0", "1", "115792089237316195423570985008687907853269984665640564039457584007913129639935", true}, // 0 - 1, should underflow + {"57896044618658097711785492504343953926634992332820282019728792003956564819968", "1", "57896044618658097711785492504343953926634992332820282019728792003956564819967", false}, // 2^255 - 1, no underflow + {"57896044618658097711785492504343953926634992332820282019728792003956564819968", "57896044618658097711785492504343953926634992332820282019728792003956564819969", "115792089237316195423570985008687907853269984665640564039457584007913129639935", true}, // 2^255 - (2^255 + 1), should underflow + } - if got.Neq(want) { - t.Errorf("Sub(%s, %s) = %v, want %v", tc.x, tc.y, got.ToString(), want.ToString()) + for _, tc := range tests { + x := MustFromDecimal(tc.x) + y := MustFromDecimal(tc.y) + want := MustFromDecimal(tc.want) + + got, overflow := new(Uint).SubOverflow(x, y) + + if got.Cmp(want) != 0 || overflow != tc.overflow { + t.Errorf( + "SubOverflow(%s, %s) = (%s, %v), want (%s, %v)", + tc.x, tc.y, got.ToString(), overflow, tc.want, tc.overflow, + ) } } } @@ -89,30 +126,50 @@ func TestMul(t *testing.T) { {"18446744073709551615", "2", "36893488147419103230"}, // uint64 overflow } - for _, tc := range tests { - x, err := FromDecimal(tc.x) - if err != nil { - t.Error(err) - continue - } + for _, tt := range tests { + x := MustFromDecimal(tt.x) + y := MustFromDecimal(tt.y) + want := MustFromDecimal(tt.want) + got := new(Uint).Mul(x, y) - y, err := FromDecimal(tc.y) - if err != nil { - t.Error(err) - continue + if got.Neq(want) { + t.Errorf("Mul(%s, %s) = %v, want %v", tt.x, tt.y, got.ToString(), want.ToString()) } + } +} - want, err := FromDecimal(tc.want) - if err != nil { - t.Error(err) - continue - } +func TestMulOverflow(t *testing.T) { + tests := []struct { + x string + y string + wantZ string + wantOver bool + }{ + {"0x1", "0x1", "0x1", false}, + {"0x0", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x0", false}, + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x2", "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", true}, + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x1", true}, + {"0x8000000000000000000000000000000000000000000000000000000000000000", "0x2", "0x0", true}, + {"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x2", "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", false}, + {"0x100000000000000000", "0x100000000000000000", "0x10000000000000000000000000000000000", false}, + {"0x10000000000000000000000000000000", "0x10000000000000000000000000000000", "0x100000000000000000000000000000000000000000000000000000000000000", false}, + } - got := &Uint{} - got.Mul(x, y) + for _, tt := range tests { + x := MustFromHex(tt.x) + y := MustFromHex(tt.y) + wantZ := MustFromHex(tt.wantZ) - if got.Neq(want) { - t.Errorf("Mul(%s, %s) = %v, want %v", tc.x, tc.y, got.ToString(), want.ToString()) + gotZ, gotOver := new(Uint).MulOverflow(x, y) + + if gotZ.Neq(wantZ) { + t.Errorf( + "MulOverflow(%s, %s) = %s, want %s", + tt.x, tt.y, gotZ.ToString(), wantZ.ToString(), + ) + } + if gotOver != tt.wantOver { + t.Errorf("MulOverflow(%s, %s) = %v, want %v", tt.x, tt.y, gotOver, tt.wantOver) } } } @@ -123,32 +180,19 @@ func TestDiv(t *testing.T) { {"31337", "0", "0"}, {"0", "31337", "0"}, {"1", "1", "1"}, + {"1000000000000000000", "3", "333333333333333333"}, + {twoPow256Sub1, "2", "57896044618658097711785492504343953926634992332820282019728792003956564819967"}, } - for _, tc := range tests { - x, err := FromDecimal(tc.x) - if err != nil { - t.Error(err) - continue - } - - y, err := FromDecimal(tc.y) - if err != nil { - t.Error(err) - continue - } - - want, err := FromDecimal(tc.want) - if err != nil { - t.Error(err) - continue - } + for _, tt := range tests { + x := MustFromDecimal(tt.x) + y := MustFromDecimal(tt.y) + want := MustFromDecimal(tt.want) - got := &Uint{} - got.Div(x, y) + got := new(Uint).Div(x, y) if got.Neq(want) { - t.Errorf("Div(%s, %s) = %v, want %v", tc.x, tc.y, got.ToString(), want.ToString()) + t.Errorf("Div(%s, %s) = %v, want %v", tt.x, tt.y, got.ToString(), want.ToString()) } } } @@ -160,32 +204,56 @@ func TestMod(t *testing.T) { {"0", "31337", "0"}, {"2", "31337", "2"}, {"1", "1", "0"}, + {"115792089237316195423570985008687907853269984665640564039457584007913129639935", "2", "1"}, // 2^256 - 1 mod 2 + {"115792089237316195423570985008687907853269984665640564039457584007913129639935", "3", "0"}, // 2^256 - 1 mod 3 + {"115792089237316195423570985008687907853269984665640564039457584007913129639935", "57896044618658097711785492504343953926634992332820282019728792003956564819968", "57896044618658097711785492504343953926634992332820282019728792003956564819967"}, // 2^256 - 1 mod 2^255 } - for _, tc := range tests { - x, err := FromDecimal(tc.x) - if err != nil { - t.Error(err) - continue - } + for _, tt := range tests { + x := MustFromDecimal(tt.x) + y := MustFromDecimal(tt.y) + want := MustFromDecimal(tt.want) - y, err := FromDecimal(tc.y) - if err != nil { - t.Error(err) - continue - } + got := new(Uint).Mod(x, y) - want, err := FromDecimal(tc.want) - if err != nil { - t.Error(err) - continue + if got.Neq(want) { + t.Errorf("Mod(%s, %s) = %v, want %v", tt.x, tt.y, got.ToString(), want.ToString()) } + } +} - got := &Uint{} - got.Mod(x, y) +func TestMulMod(t *testing.T) { + tests := []struct { + x string + y string + m string + want string + }{ + {"0x1", "0x1", "0x2", "0x1"}, + {"0x10", "0x10", "0x7", "0x4"}, + {"0x100", "0x100", "0x17", "0x9"}, + {"0x31337", "0x31337", "0x31338", "0x1"}, + {"0x0", "0x31337", "0x31338", "0x0"}, + {"0x31337", "0x0", "0x31338", "0x0"}, + {"0x2", "0x3", "0x5", "0x1"}, + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x0"}, + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", "0x1"}, + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xffffffffffffffffffffffffffffffff", "0x0"}, + } + + for _, tt := range tests { + x := MustFromHex(tt.x) + y := MustFromHex(tt.y) + m := MustFromHex(tt.m) + want := MustFromHex(tt.want) + + got := new(Uint).MulMod(x, y, m) if got.Neq(want) { - t.Errorf("Mod(%s, %s) = %v, want %v", tc.x, tc.y, got.ToString(), want.ToString()) + t.Errorf( + "MulMod(%s, %s, %s) = %s, want %s", + tt.x, tt.y, tt.m, got.ToString(), want.ToString(), + ) } } } @@ -206,30 +274,11 @@ func TestDivMod(t *testing.T) { {"2", "31337", "0", "2"}, } - for _, tc := range tests { - x, err := FromDecimal(tc.x) - if err != nil { - t.Error(err) - continue - } - - y, err := FromDecimal(tc.y) - if err != nil { - t.Error(err) - continue - } - - wantDiv, err := FromDecimal(tc.wantDiv) - if err != nil { - t.Error(err) - continue - } - - wantMod, err := FromDecimal(tc.wantMod) - if err != nil { - t.Error(err) - continue - } + for _, tt := range tests { + x := MustFromDecimal(tt.x) + y := MustFromDecimal(tt.y) + wantDiv := MustFromDecimal(tt.wantDiv) + wantMod := MustFromDecimal(tt.wantMod) gotDiv := new(Uint) gotMod := new(Uint) @@ -237,13 +286,13 @@ func TestDivMod(t *testing.T) { for i := range gotDiv.arr { if gotDiv.arr[i] != wantDiv.arr[i] { - t.Errorf("DivMod(%s, %s) got Div %v, want Div %v", tc.x, tc.y, gotDiv, wantDiv) + t.Errorf("DivMod(%s, %s) got Div %v, want Div %v", tt.x, tt.y, gotDiv, wantDiv) break } } for i := range gotMod.arr { if gotMod.arr[i] != wantMod.arr[i] { - t.Errorf("DivMod(%s, %s) got Mod %v, want Mod %v", tc.x, tc.y, gotMod, wantMod) + t.Errorf("DivMod(%s, %s) got Mod %v, want Mod %v", tt.x, tt.y, gotMod, wantMod) break } } @@ -259,27 +308,17 @@ func TestNeg(t *testing.T) { {"115792089237316195423570985008687907853269984665640564039457584007913129608599", "31337"}, {"0", "0"}, {"2", "115792089237316195423570985008687907853269984665640564039457584007913129639934"}, - {"1", "115792089237316195423570985008687907853269984665640564039457584007913129639935"}, + {"1", twoPow256Sub1}, } - for _, tc := range tests { - x, err := FromDecimal(tc.x) - if err != nil { - t.Error(err) - continue - } - - want, err := FromDecimal(tc.want) - if err != nil { - t.Error(err) - continue - } + for _, tt := range tests { + x := MustFromDecimal(tt.x) + want := MustFromDecimal(tt.want) - got := &Uint{} - got.Neg(x) + got := new(Uint).Neg(x) if got.Neq(want) { - t.Errorf("Neg(%s) = %v, want %v", tc.x, got.ToString(), want.ToString()) + t.Errorf("Neg(%s) = %v, want %v", tt.x, got.ToString(), want.ToString()) } } } @@ -297,30 +336,57 @@ func TestExp(t *testing.T) { {"2", "256", "0"}, // overflow } - for _, tc := range tests { - x, err := FromDecimal(tc.x) - if err != nil { - t.Error(err) - continue - } + for _, tt := range tests { + x := MustFromDecimal(tt.x) + y := MustFromDecimal(tt.y) + want := MustFromDecimal(tt.want) - y, err := FromDecimal(tc.y) - if err != nil { - t.Error(err) - continue - } + got := new(Uint).Exp(x, y) - want, err := FromDecimal(tc.want) - if err != nil { - t.Error(err) - continue + if got.Neq(want) { + t.Errorf( + "Exp(%s, %s) = %v, want %v", + tt.x, tt.y, got.ToString(), want.ToString(), + ) } + } +} + +func TestExp_LargeExponent(t *testing.T) { + tests := []struct { + name string + base string + exponent string + expected string + }{ + { + name: "2^129", + base: "2", + exponent: "680564733841876926926749214863536422912", + expected: "0", + }, + { + name: "2^193", + base: "2", + exponent: "12379400392853802746563808384000000000000000000", + expected: "0", + }, + } - got := &Uint{} - got.Exp(x, y) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + base := MustFromDecimal(tt.base) + exponent := MustFromDecimal(tt.exponent) + expected := MustFromDecimal(tt.expected) - if got.Neq(want) { - t.Errorf("Exp(%s, %s) = %v, want %v", tc.x, tc.y, got.ToString(), want.ToString()) - } + result := new(Uint).Exp(base, exponent) + + if result.Neq(expected) { + t.Errorf( + "Test %s failed. Expected %s, got %s", + tt.name, expected.ToString(), result.ToString(), + ) + } + }) } } diff --git a/examples/gno.land/p/demo/uint256/bitwise_test.gno b/examples/gno.land/p/demo/uint256/bitwise_test.gno index aba89edfabf..3561629fd94 100644 --- a/examples/gno.land/p/demo/uint256/bitwise_test.gno +++ b/examples/gno.land/p/demo/uint256/bitwise_test.gno @@ -37,11 +37,14 @@ func TestOr(t *testing.T) { }, } - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - res := new(Uint).Or(&tc.x, &tc.y) - if *res != tc.want { - t.Errorf("Or(%s, %s) = %s, want %s", tc.x.ToString(), tc.y.ToString(), res.ToString(), (tc.want).ToString()) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + res := new(Uint).Or(&tt.x, &tt.y) + if *res != tt.want { + t.Errorf( + "Or(%s, %s) = %s, want %s", + tt.x.ToString(), tt.y.ToString(), res.ToString(), (tt.want).ToString(), + ) } }) } @@ -93,11 +96,14 @@ func TestAnd(t *testing.T) { }, } - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - res := new(Uint).And(&tc.x, &tc.y) - if *res != tc.want { - t.Errorf("And(%s, %s) = %s, want %s", tc.x.ToString(), tc.y.ToString(), res.ToString(), (tc.want).ToString()) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + res := new(Uint).And(&tt.x, &tt.y) + if *res != tt.want { + t.Errorf( + "And(%s, %s) = %s, want %s", + tt.x.ToString(), tt.y.ToString(), res.ToString(), (tt.want).ToString(), + ) } }) } @@ -126,11 +132,14 @@ func TestNot(t *testing.T) { }, } - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - res := new(Uint).Not(&tc.x) - if *res != tc.want { - t.Errorf("Not(%s) = %s, want %s", tc.x.ToString(), res.ToString(), (tc.want).ToString()) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + res := new(Uint).Not(&tt.x) + if *res != tt.want { + t.Errorf( + "Not(%s) = %s, want %s", + tt.x.ToString(), res.ToString(), (tt.want).ToString(), + ) } }) } @@ -182,11 +191,14 @@ func TestAndNot(t *testing.T) { }, } - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - res := new(Uint).AndNot(&tc.x, &tc.y) - if *res != tc.want { - t.Errorf("AndNot(%s, %s) = %s, want %s", tc.x.ToString(), tc.y.ToString(), res.ToString(), (tc.want).ToString()) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + res := new(Uint).AndNot(&tt.x, &tt.y) + if *res != tt.want { + t.Errorf( + "AndNot(%s, %s) = %s, want %s", + tt.x.ToString(), tt.y.ToString(), res.ToString(), (tt.want).ToString(), + ) } }) } @@ -238,11 +250,14 @@ func TestXor(t *testing.T) { }, } - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - res := new(Uint).Xor(&tc.x, &tc.y) - if *res != tc.want { - t.Errorf("Xor(%s, %s) = %s, want %s", tc.x.ToString(), tc.y.ToString(), res.ToString(), (tc.want).ToString()) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + res := new(Uint).Xor(&tt.x, &tt.y) + if *res != tt.want { + t.Errorf( + "Xor(%s, %s) = %s, want %s", + tt.x.ToString(), tt.y.ToString(), res.ToString(), (tt.want).ToString(), + ) } }) } @@ -272,26 +287,31 @@ func TestLsh(t *testing.T) { {"31337", 193, "393411074163624830192644266310117284962799025126338899061243904"}, {"31337", 255, "57896044618658097711785492504343953926634992332820282019728792003956564819968"}, {"31337", 256, "0"}, - } + // 64 < n < 128 + {"1", 65, "36893488147419103232"}, + {"31337", 100, "39724366859352024754702188346867712"}, - for _, tc := range tests { - x, err := FromDecimal(tc.x) - if err != nil { - t.Error(err) - continue - } + // 128 < n < 192 + {"1", 129, "680564733841876926926749214863536422912"}, + {"31337", 150, "44725660946326664792723507424638829088826130956288"}, - want, err := FromDecimal(tc.want) - if err != nil { - t.Error(err) - continue - } + // 192 < n < 256 + {"1", 193, "12554203470773361527671578846415332832204710888928069025792"}, + {"31337", 200, "50356617492943978264658466087695012475238275216171379079839219712"}, - got := &Uint{} - got.Lsh(x, tc.y) + // n > 256 + {"1", 257, "0"}, + {"31337", 300, "0"}, + } + + for _, tt := range tests { + x := MustFromDecimal(tt.x) + want := MustFromDecimal(tt.want) + + got := new(Uint).Lsh(x, tt.y) if got.Neq(want) { - t.Errorf("Lsh(%s, %d) = %s, want %s", tc.x, tc.y, got.ToString(), want.ToString()) + t.Errorf("Lsh(%s, %d) = %s, want %s", tt.x, tt.y, got.ToString(), want.ToString()) } } } @@ -319,26 +339,85 @@ func TestRsh(t *testing.T) { {"196705537081812415096322133155058642481399512563169449530621952", 192, "31337"}, {"10663428532201448629551770073089320442396672", 128, "31337"}, {"578065619037836218990592", 64, "31337"}, + {twoPow256Sub1, 256, "0"}, + // outliers + {"340282366920938463463374607431768211455", 129, "0"}, + {"18446744073709551615", 65, "0"}, + {twoPow256Sub1, 1, "57896044618658097711785492504343953926634992332820282019728792003956564819967"}, + + // n > 256 + {"1", 257, "0"}, + {"31337", 300, "0"}, } - for _, tc := range tests { - x, err := FromDecimal(tc.x) - if err != nil { - t.Error(err) - continue - } + for _, tt := range tests { + x := MustFromDecimal(tt.x) + + want := MustFromDecimal(tt.want) + got := new(Uint).Rsh(x, tt.y) - want, err := FromDecimal(tc.want) - if err != nil { - t.Error(err) - continue + if got.Neq(want) { + t.Errorf("Rsh(%s, %d) = %s, want %s", tt.x, tt.y, got.ToString(), want.ToString()) } + } +} + +func TestSRsh(t *testing.T) { + tests := []struct { + x string + y uint + want string + }{ + // Positive numbers (behaves like Rsh) + {"0x0", 0, "0x0"}, + {"0x0", 1, "0x0"}, + {"0x1", 0, "0x1"}, + {"0x1", 1, "0x0"}, + {"0x31337", 0, "0x31337"}, + {"0x31337", 4, "0x3133"}, + {"0x31337", 8, "0x313"}, + {"0x31337", 16, "0x3"}, + {"0x10000000000000000", 64, "0x1"}, // 2^64 >> 64 - got := &Uint{} - got.Rsh(x, tc.y) + // // Numbers with MSB set (negative numbers in two's complement) + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 0, "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 1, "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 4, "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 64, "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 128, "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 192, "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 255, "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, - if got.Neq(want) { - t.Errorf("Rsh(%s, %d) = %s, want %s", tc.x, tc.y, got.ToString(), want.ToString()) + // Large positive number close to max value + {"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 1, "0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + {"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 2, "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + {"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 64, "0x7fffffffffffffffffffffffffffffffffffffffffffffff"}, + {"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 128, "0x7fffffffffffffffffffffffffffffff"}, + {"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 192, "0x7fffffffffffffff"}, + {"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 255, "0x0"}, + + // Specific cases + {"0x8000000000000000000000000000000000000000000000000000000000000000", 1, "0xc000000000000000000000000000000000000000000000000000000000000000"}, + {"0x8000000000000000000000000000000000000000000000000000000000000001", 1, "0xc000000000000000000000000000000000000000000000000000000000000000"}, + + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 65, "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 127, "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 129, "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 193, "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, + + // n > 256 + {"0x1", 257, "0x0"}, + {"0x31337", 300, "0x0"}, + } + + for _, tt := range tests { + x := MustFromHex(tt.x) + want := MustFromHex(tt.want) + + got := new(Uint).SRsh(x, tt.y) + + if !got.Eq(want) { + t.Errorf("SRsh(%s, %d) = %s, want %s", tt.x, tt.y, got.ToString(), want.ToString()) } } } diff --git a/examples/gno.land/p/demo/uint256/cmp_test.gno b/examples/gno.land/p/demo/uint256/cmp_test.gno index 930079f70f0..51c9e70d9a7 100644 --- a/examples/gno.land/p/demo/uint256/cmp_test.gno +++ b/examples/gno.land/p/demo/uint256/cmp_test.gno @@ -5,6 +5,39 @@ import ( "testing" ) +func TestSign(t *testing.T) { + tests := []struct { + input *Uint + expected int + }{ + { + input: NewUint(0), + expected: 0, + }, + { + input: NewUint(1), + expected: 1, + }, + { + input: NewUint(0x7fffffffffffffff), + expected: 1, + }, + { + input: NewUint(0x8000000000000000), + expected: 1, + }, + } + + for _, tt := range tests { + t.Run(tt.input.ToString(), func(t *testing.T) { + result := tt.input.Sign() + if result != tt.expected { + t.Errorf("Sign() = %d; want %d", result, tt.expected) + } + }) + } +} + func TestCmp(t *testing.T) { tests := []struct { x, y string @@ -20,17 +53,8 @@ func TestCmp(t *testing.T) { } for _, tc := range tests { - x, err := FromDecimal(tc.x) - if err != nil { - t.Error(err) - continue - } - - y, err := FromDecimal(tc.y) - if err != nil { - t.Error(err) - continue - } + x := MustFromDecimal(tc.x) + y := MustFromDecimal(tc.y) got := x.Cmp(y) if got != tc.want { @@ -49,16 +73,12 @@ func TestIsZero(t *testing.T) { {"10", false}, } - for _, tc := range tests { - x, err := FromDecimal(tc.x) - if err != nil { - t.Error(err) - continue - } + for _, tt := range tests { + x := MustFromDecimal(tt.x) got := x.IsZero() - if got != tc.want { - t.Errorf("IsZero(%s) = %v, want %v", tc.x, got, tc.want) + if got != tt.want { + t.Errorf("IsZero(%s) = %v, want %v", tt.x, got, tt.want) } } } @@ -77,31 +97,53 @@ func TestLtUint64(t *testing.T) { } for _, tc := range tests { - var x *Uint - var err error - - if strings.HasPrefix(tc.x, "0x") { - x, err = FromHex(tc.x) - if err != nil { - t.Error(err) - continue - } - } else { - x, err = FromDecimal(tc.x) - if err != nil { - t.Error(err) - continue - } - } + x := parseTestString(t, tc.x) got := x.LtUint64(tc.y) - if got != tc.want { t.Errorf("LtUint64(%s, %d) = %v, want %v", tc.x, tc.y, got, tc.want) } } } +func TestUint_GtUint64(t *testing.T) { + tests := []struct { + name string + z string + n uint64 + want bool + }{ + { + name: "z > n", + z: "1", + n: 0, + want: true, + }, + { + name: "z < n", + z: "18446744073709551615", + n: 0xFFFFFFFFFFFFFFFF, + want: false, + }, + { + name: "z == n", + z: "18446744073709551615", + n: 0xFFFFFFFFFFFFFFFF, + want: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + z := MustFromDecimal(tt.z) + + if got := z.GtUint64(tt.n); got != tt.want { + t.Errorf("Uint.GtUint64() = %v, want %v", got, tt.want) + } + }) + } +} + func TestSGT(t *testing.T) { x := MustFromHex("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe") y := MustFromHex("0x0") @@ -127,37 +169,83 @@ func TestEq(t *testing.T) { {"0xffffffffffffffff", "18446744073709551615", true}, {"0x10000000000000000", "18446744073709551616", true}, {"0", "0", true}, - {"115792089237316195423570985008687907853269984665640564039457584007913129639935", "115792089237316195423570985008687907853269984665640564039457584007913129639935", true}, + {twoPow256Sub1, twoPow256Sub1, true}, } - for i, tc := range tests { - var x *Uint - var err error + for _, tt := range tests { + x := parseTestString(t, tt.x) - if strings.HasPrefix(tc.x, "0x") { - x, err = FromHex(tc.x) - if err != nil { - t.Error(err) - continue - } - } else { - x, err = FromDecimal(tc.x) - if err != nil { - t.Error(err) - continue - } + y, err := FromDecimal(tt.y) + if err != nil { + t.Error(err) + continue } - y, err := FromDecimal(tc.y) + got := x.Eq(y) + + if got != tt.want { + t.Errorf("Eq(%s, %s) = %v, want %v", tt.x, tt.y, got, tt.want) + } + } +} + +func TestUint_Lte(t *testing.T) { + tests := []struct { + z, x string + want bool + }{ + {"10", "20", true}, + {"20", "10", false}, + {"10", "10", true}, + {"0", "0", true}, + } + + for _, tt := range tests { + z, err := FromDecimal(tt.z) if err != nil { t.Error(err) continue } + x, err := FromDecimal(tt.x) + if err != nil { + t.Error(err) + continue + } + if got := z.Lte(x); got != tt.want { + t.Errorf("Uint.Lte(%v, %v) = %v, want %v", tt.z, tt.x, got, tt.want) + } + } +} - got := x.Eq(y) +func TestUint_Gte(t *testing.T) { + tests := []struct { + z, x string + want bool + }{ + {"20", "10", true}, + {"10", "20", false}, + {"10", "10", true}, + {"0", "0", true}, + } - if got != tc.want { - t.Errorf("Eq(%s, %s) = %v, want %v", tc.x, tc.y, got, tc.want) + for _, tt := range tests { + z := parseTestString(t, tt.z) + x := parseTestString(t, tt.x) + + if got := z.Gte(x); got != tt.want { + t.Errorf("Uint.Gte(%v, %v) = %v, want %v", tt.z, tt.x, got, tt.want) } } } + +func parseTestString(_ *testing.T, s string) *Uint { + var x *Uint + + if strings.HasPrefix(s, "0x") { + x = MustFromHex(s) + } else { + x = MustFromDecimal(s) + } + + return x +} diff --git a/examples/gno.land/p/demo/uint256/conversion_test.gno b/examples/gno.land/p/demo/uint256/conversion_test.gno index ee3aad0f819..0ea20158be4 100644 --- a/examples/gno.land/p/demo/uint256/conversion_test.gno +++ b/examples/gno.land/p/demo/uint256/conversion_test.gno @@ -14,18 +14,18 @@ func TestIsUint64(t *testing.T) { {"0x10000000000000000", false}, } - for _, tc := range tests { - x := MustFromHex(tc.x) + for _, tt := range tests { + x := MustFromHex(tt.x) got := x.IsUint64() - if got != tc.want { - t.Errorf("IsUint64(%s) = %v, want %v", tc.x, got, tc.want) + if got != tt.want { + t.Errorf("IsUint64(%s) = %v, want %v", tt.x, got, tt.want) } } } func TestDec(t *testing.T) { - testCases := []struct { + tests := []struct { name string z Uint want string @@ -43,16 +43,133 @@ func TestDec(t *testing.T) { { name: "max possible value", z: Uint{arr: [4]uint64{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)}}, - want: "115792089237316195423570985008687907853269984665640564039457584007913129639935", + want: twoPow256Sub1, }, } - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - result := tc.z.Dec() - if result != tc.want { - t.Errorf("Dec(%v) = %s, want %s", tc.z, result, tc.want) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := tt.z.Dec() + if result != tt.want { + t.Errorf("Dec(%v) = %s, want %s", tt.z, result, tt.want) } }) } } + +func TestUint_Scan(t *testing.T) { + tests := []struct { + name string + input interface{} + want *Uint + wantErr bool + }{ + { + name: "nil", + input: nil, + want: NewUint(0), + }, + { + name: "valid scientific notation", + input: "1e4", + want: NewUint(10000), + }, + { + name: "valid decimal string", + input: "12345", + want: NewUint(12345), + }, + { + name: "valid byte slice", + input: []byte("12345"), + want: NewUint(12345), + }, + { + name: "invalid string", + input: "invalid", + wantErr: true, + }, + { + name: "out of range", + input: "115792089237316195423570985008687907853269984665640564039457584007913129639936", // 2^256 + wantErr: true, + }, + { + name: "unsupported type", + input: 123, + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + z := new(Uint) + err := z.Scan(tt.input) + + if tt.wantErr { + if err == nil { + t.Errorf("Scan() error = %v, wantErr %v", err, tt.wantErr) + } + } else { + if err != nil { + t.Errorf("Scan() error = %v, wantErr %v", err, tt.wantErr) + } + if !z.Eq(tt.want) { + t.Errorf("Scan() = %v, want %v", z, tt.want) + } + } + }) + } +} + +func TestSetBytes(t *testing.T) { + tests := []struct { + input []byte + expected string + }{ + {[]byte{}, "0"}, + {[]byte{0x01}, "1"}, + {[]byte{0x12, 0x34}, "4660"}, + {[]byte{0x12, 0x34, 0x56}, "1193046"}, + {[]byte{0x12, 0x34, 0x56, 0x78}, "305419896"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a}, "78187493530"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc}, "20015998343868"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde}, "5124095576030430"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0}, "1311768467463790320"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12}, "335812727670730321938"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34}, "85968058283706962416180"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56}, "22007822920628982378542166"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78}, "5634002667681019488906794616"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a}, "1442304682926340989160139421850"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc}, "369229998829143293224995691993788"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde}, "94522879700260683065598897150409950"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0}, "24197857203266734864793317670504947440"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12}, "6194651444036284125387089323649266544658"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34}, "1585830769673288736099094866854212235432500"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56}, "405972677036361916441368285914678332270720086"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78}, "103929005321308650608990281194157653061304342136"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a}, "26605825362255014555901511985704359183693911586970"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc}, "6811091292737283726310787068340315951025641366264508"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde}, "1743639370940744633935561489495120883462564189763714270"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0}, "446371678960830626287503741310750946166416432579510853360"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12}, "114271149813972640329600957775552242218602606740354778460178"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34}, "29253414352376995924377845190541374007962267325530823285805620"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56}, "7488874074208510956640728368778591746038340435335890761166238806"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78}, "1917151762997378804900026462407319486985815151445988034858557134456"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a}, "490790851327328974054406774376273788668368678770172936923790626420890"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc}, "125642457939796217357928134240326089899102381765164271852490400363748028"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde}, "32164469232587831643629602365523479014170209731882053594237542493119495390"}, + {[]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0}, "8234104123542484900769178205574010627627573691361805720124810878238590820080"}, + // over 32 bytes (last 32 bytes are used) + {append([]byte{0xff}, []byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0}...), "8234104123542484900769178205574010627627573691361805720124810878238590820080"}, + } + + for _, test := range tests { + z := new(Uint) + z.SetBytes(test.input) + expected := MustFromDecimal(test.expected) + if z.Cmp(expected) != 0 { + t.Errorf("SetBytes(%x) = %s, expected %s", test.input, z.ToString(), test.expected) + } + } +} diff --git a/examples/gno.land/p/demo/uint256/uint256.gno b/examples/gno.land/p/demo/uint256/uint256.gno index 80da0ba882b..3d183362992 100644 --- a/examples/gno.land/p/demo/uint256/uint256.gno +++ b/examples/gno.land/p/demo/uint256/uint256.gno @@ -5,6 +5,7 @@ package uint256 import ( "errors" "math/bits" + "strconv" ) const ( @@ -143,10 +144,10 @@ func (z *Uint) fromDecimal(bs string) error { if remaining <= 0 { return nil // Done } else if remaining > 19 { - num, err = parseUint(bs[remaining-19:remaining], 10, 64) + num, err = strconv.ParseUint(bs[remaining-19:remaining], 10, 64) } else { // Final round - num, err = parseUint(bs, 10, 64) + num, err = strconv.ParseUint(bs, 10, 64) } if err != nil { return err diff --git a/examples/gno.land/p/demo/uint256/uint256_test.gno b/examples/gno.land/p/demo/uint256/uint256_test.gno new file mode 100644 index 00000000000..0089af15c66 --- /dev/null +++ b/examples/gno.land/p/demo/uint256/uint256_test.gno @@ -0,0 +1,127 @@ +package uint256 + +import ( + "testing" +) + +func TestSetAllOne(t *testing.T) { + z := Zero() + z.SetAllOne() + if z.ToString() != twoPow256Sub1 { + t.Errorf("Expected all ones, got %s", z.ToString()) + } +} + +func TestByte(t *testing.T) { + tests := []struct { + input string + position uint64 + expected byte + }{ + {"0x1000000000000000000000000000000000000000000000000000000000000000", 0, 16}, + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 0, 255}, + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 31, 255}, + } + + for i, tt := range tests { + z, _ := FromHex(tt.input) + n := NewUint(tt.position) + result := z.Byte(n) + + if result.arr[0] != uint64(tt.expected) { + t.Errorf("Test case %d failed. Input: %s, Position: %d, Expected: %d, Got: %d", + i, tt.input, tt.position, tt.expected, result.arr[0]) + } + + // check other array elements are 0 + if result.arr[1] != 0 || result.arr[2] != 0 || result.arr[3] != 0 { + t.Errorf("Test case %d failed. Non-zero values in upper bytes", i) + } + } + + // overflow + z, _ := FromHex("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + n := NewUint(32) + result := z.Byte(n) + + if !result.IsZero() { + t.Errorf("Expected zero for position >= 32, got %v", result) + } +} + +func TestBitLen(t *testing.T) { + tests := []struct { + input string + expected int + }{ + {"0x0", 0}, + {"0x1", 1}, + {"0xff", 8}, + {"0x100", 9}, + {"0xffff", 16}, + {"0x10000", 17}, + {"0xffffffffffffffff", 64}, + {"0x10000000000000000", 65}, + {"0xffffffffffffffffffffffffffffffff", 128}, + {"0x100000000000000000000000000000000", 129}, + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 256}, + } + + for i, tt := range tests { + z, _ := FromHex(tt.input) + result := z.BitLen() + + if result != tt.expected { + t.Errorf("Test case %d failed. Input: %s, Expected: %d, Got: %d", + i, tt.input, tt.expected, result) + } + } +} + +func TestByteLen(t *testing.T) { + tests := []struct { + input string + expected int + }{ + {"0x0", 0}, + {"0x1", 1}, + {"0xff", 1}, + {"0x100", 2}, + {"0xffff", 2}, + {"0x10000", 3}, + {"0xffffffffffffffff", 8}, + {"0x10000000000000000", 9}, + {"0xffffffffffffffffffffffffffffffff", 16}, + {"0x100000000000000000000000000000000", 17}, + {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 32}, + } + + for i, tt := range tests { + z, _ := FromHex(tt.input) + result := z.ByteLen() + + if result != tt.expected { + t.Errorf("Test case %d failed. Input: %s, Expected: %d, Got: %d", + i, tt.input, tt.expected, result) + } + } +} + +func TestClone(t *testing.T) { + tests := []struct { + input string + expected string + }{ + {"0x1", "1"}, + {"0x100", "256"}, + {"0x10000000000000000", "18446744073709551616"}, + } + + for _, tt := range tests { + z, _ := FromHex(tt.input) + result := z.Clone() + if result.ToString() != tt.expected { + t.Errorf("Test %s failed. Expected %s, got %s", tt.input, tt.expected, result.ToString()) + } + } +} diff --git a/examples/gno.land/p/demo/uint256/utils.gno b/examples/gno.land/p/demo/uint256/utils.gno index 969728f3369..bcc7bb283e0 100644 --- a/examples/gno.land/p/demo/uint256/utils.gno +++ b/examples/gno.land/p/demo/uint256/utils.gno @@ -1,63 +1,5 @@ package uint256 -// lower(c) is a lower-case letter if and only if -// c is either that lower-case letter or the equivalent upper-case letter. -// Instead of writing c == 'x' || c == 'X' one can write lower(c) == 'x'. -// Note that lower of non-letters can produce other non-letters. -func lower(c byte) byte { - return c | ('x' - 'X') -} - -// underscoreOK reports whether the underscores in s are allowed. -// Checking them in this one function lets all the parsers skip over them simply. -// Underscore must appear only between digits or between a base prefix and a digit. -func underscoreOK(s string) bool { - // saw tracks the last character (class) we saw: - // ^ for beginning of number, - // 0 for a digit or base prefix, - // _ for an underscore, - // ! for none of the above. - saw := '^' - i := 0 - - // Optional sign. - if len(s) >= 1 && (s[0] == '-' || s[0] == '+') { - s = s[1:] - } - - // Optional base prefix. - hex := false - if len(s) >= 2 && s[0] == '0' && (lower(s[1]) == 'b' || lower(s[1]) == 'o' || lower(s[1]) == 'x') { - i = 2 - saw = '0' // base prefix counts as a digit for "underscore as digit separator" - hex = lower(s[1]) == 'x' - } - - // Number proper. - for ; i < len(s); i++ { - // Digits are always okay. - if '0' <= s[i] && s[i] <= '9' || hex && 'a' <= lower(s[i]) && lower(s[i]) <= 'f' { - saw = '0' - continue - } - // Underscore must follow digit. - if s[i] == '_' { - if saw != '0' { - return false - } - saw = '_' - continue - } - // Underscore must also be followed by digit. - if saw == '_' { - return false - } - // Saw non-digit, non-underscore. - saw = '!' - } - return saw != '_' -} - func checkNumberS(input string) error { const fn = "UnmarshalText" l := len(input) @@ -76,105 +18,3 @@ func checkNumberS(input string) error { } return nil } - -// ParseUint is like ParseUint but for unsigned numbers. -// -// A sign prefix is not permitted. -func parseUint(s string, base int, bitSize int) (uint64, error) { - const fnParseUint = "ParseUint" - - if s == "" { - return 0, errSyntax(fnParseUint, s) - } - - base0 := base == 0 - - s0 := s - switch { - case 2 <= base && base <= 36: - // valid base; nothing to do - - case base == 0: - // Look for octal, hex prefix. - base = 10 - if s[0] == '0' { - switch { - case len(s) >= 3 && lower(s[1]) == 'b': - base = 2 - s = s[2:] - case len(s) >= 3 && lower(s[1]) == 'o': - base = 8 - s = s[2:] - case len(s) >= 3 && lower(s[1]) == 'x': - base = 16 - s = s[2:] - default: - base = 8 - s = s[1:] - } - } - - default: - return 0, errInvalidBase(fnParseUint, base) - } - - if bitSize == 0 { - bitSize = uintSize - } else if bitSize < 0 || bitSize > 64 { - return 0, errInvalidBitSize(fnParseUint, bitSize) - } - - // Cutoff is the smallest number such that cutoff*base > maxUint64. - // Use compile-time constants for common cases. - var cutoff uint64 - switch base { - case 10: - cutoff = MaxUint64/10 + 1 - case 16: - cutoff = MaxUint64/16 + 1 - default: - cutoff = MaxUint64/uint64(base) + 1 - } - - maxVal := uint64(1)<= byte(base) { - return 0, errSyntax(fnParseUint, s0) - } - - if n >= cutoff { - // n*base overflows - return maxVal, errRange(fnParseUint, s0) - } - n *= uint64(base) - - n1 := n + uint64(d) - if n1 < n || n1 > maxVal { - // n+d overflows - return maxVal, errRange(fnParseUint, s0) - } - n = n1 - } - - if underscores && !underscoreOK(s0) { - return 0, errSyntax(fnParseUint, s0) - } - - return n, nil -} diff --git a/examples/gno.land/p/gov/executor/callback.gno b/examples/gno.land/p/gov/executor/callback.gno new file mode 100644 index 00000000000..5d46a97cd69 --- /dev/null +++ b/examples/gno.land/p/gov/executor/callback.gno @@ -0,0 +1,39 @@ +package executor + +import ( + "errors" + "std" +) + +var errInvalidCaller = errors.New("invalid executor caller") + +// NewCallbackExecutor creates a new callback executor with the provided callback function +func NewCallbackExecutor(callback func() error, path string) *CallbackExecutor { + return &CallbackExecutor{ + callback: callback, + daoPkgPath: path, + } +} + +// CallbackExecutor is an implementation of the dao.Executor interface, +// based on a specific callback. +// The given callback should verify the validity of the govdao call +type CallbackExecutor struct { + callback func() error // the callback to be executed + daoPkgPath string // the active pkg path of the govdao +} + +// Execute runs the executor's callback function. +func (exec *CallbackExecutor) Execute() error { + // Verify the caller is an adequate Realm + caller := std.CurrentRealm().PkgPath() + if caller != exec.daoPkgPath { + return errInvalidCaller + } + + if exec.callback != nil { + return exec.callback() + } + + return nil +} diff --git a/examples/gno.land/p/gov/executor/context.gno b/examples/gno.land/p/gov/executor/context.gno new file mode 100644 index 00000000000..158e3b1e0be --- /dev/null +++ b/examples/gno.land/p/gov/executor/context.gno @@ -0,0 +1,75 @@ +package executor + +import ( + "errors" + "std" + + "gno.land/p/demo/context" +) + +type propContextKey string + +func (k propContextKey) String() string { return string(k) } + +const ( + statusContextKey = propContextKey("govdao-prop-status") + approvedStatus = "approved" +) + +var errNotApproved = errors.New("not approved by govdao") + +// CtxExecutor is an implementation of the dao.Executor interface, +// based on the given context. +// It utilizes the given context to assert the validity of the govdao call +type CtxExecutor struct { + callbackCtx func(ctx context.Context) error // the callback ctx fn, if any + daoPkgPath string // the active pkg path of the govdao +} + +// NewCtxExecutor creates a new executor with the provided callback function. +func NewCtxExecutor(callback func(ctx context.Context) error, path string) *CtxExecutor { + return &CtxExecutor{ + callbackCtx: callback, + daoPkgPath: path, + } +} + +// Execute runs the executor's callback function +func (exec *CtxExecutor) Execute() error { + // Verify the caller is an adequate Realm + caller := std.CurrentRealm().PkgPath() + if caller != exec.daoPkgPath { + return errInvalidCaller + } + + // Create the context + ctx := context.WithValue( + context.Empty(), + statusContextKey, + approvedStatus, + ) + + return exec.callbackCtx(ctx) +} + +// IsApprovedByGovdaoContext asserts that the govdao approved the context +func IsApprovedByGovdaoContext(ctx context.Context) bool { + v := ctx.Value(statusContextKey) + if v == nil { + return false + } + + vs, ok := v.(string) + + return ok && vs == approvedStatus +} + +// AssertContextApprovedByGovDAO asserts the given context +// was approved by GOVDAO +func AssertContextApprovedByGovDAO(ctx context.Context) { + if IsApprovedByGovdaoContext(ctx) { + return + } + + panic(errNotApproved) +} diff --git a/examples/gno.land/p/gov/proposal/gno.mod b/examples/gno.land/p/gov/executor/gno.mod similarity index 80% rename from examples/gno.land/p/gov/proposal/gno.mod rename to examples/gno.land/p/gov/executor/gno.mod index 3f6ef34a759..99f2ab3610b 100644 --- a/examples/gno.land/p/gov/proposal/gno.mod +++ b/examples/gno.land/p/gov/executor/gno.mod @@ -1,4 +1,4 @@ -module gno.land/p/gov/proposal +module gno.land/p/gov/executor require ( gno.land/p/demo/context v0.0.0-latest diff --git a/examples/gno.land/p/gov/executor/proposal_test.gno b/examples/gno.land/p/gov/executor/proposal_test.gno new file mode 100644 index 00000000000..3a70fc40596 --- /dev/null +++ b/examples/gno.land/p/gov/executor/proposal_test.gno @@ -0,0 +1,180 @@ +package executor + +import ( + "errors" + "std" + "testing" + + "gno.land/p/demo/context" + "gno.land/p/demo/uassert" + "gno.land/p/demo/urequire" +) + +func TestExecutor_Callback(t *testing.T) { + t.Parallel() + + t.Run("govdao not caller", func(t *testing.T) { + t.Parallel() + + var ( + called = false + + cb = func() error { + called = true + + return nil + } + ) + + // Create the executor + e := NewCallbackExecutor(cb, "gno.land/r/gov/dao") + + // Execute as not the /r/gov/dao caller + uassert.ErrorIs(t, e.Execute(), errInvalidCaller) + uassert.False(t, called, "expected proposal to not execute") + }) + + t.Run("execution successful", func(t *testing.T) { + t.Parallel() + + var ( + called = false + + cb = func() error { + called = true + + return nil + } + ) + + // Create the executor + daoPkgPath := "gno.land/r/gov/dao" + e := NewCallbackExecutor(cb, daoPkgPath) + + // Execute as the /r/gov/dao caller + r := std.NewCodeRealm(daoPkgPath) + std.TestSetRealm(r) + + uassert.NoError(t, e.Execute()) + uassert.True(t, called, "expected proposal to execute") + }) + + t.Run("execution unsuccessful", func(t *testing.T) { + t.Parallel() + + var ( + called = false + expectedErr = errors.New("unexpected") + + cb = func() error { + called = true + + return expectedErr + } + ) + + // Create the executor + daoPkgPath := "gno.land/r/gov/dao" + e := NewCallbackExecutor(cb, daoPkgPath) + + // Execute as the /r/gov/dao caller + r := std.NewCodeRealm(daoPkgPath) + std.TestSetRealm(r) + + uassert.ErrorIs(t, e.Execute(), expectedErr) + uassert.True(t, called, "expected proposal to execute") + }) +} + +func TestExecutor_Context(t *testing.T) { + t.Parallel() + + t.Run("govdao not caller", func(t *testing.T) { + t.Parallel() + + var ( + called = false + + cb = func(ctx context.Context) error { + if !IsApprovedByGovdaoContext(ctx) { + t.Fatal("not govdao caller") + } + + called = true + + return nil + } + ) + + // Create the executor + e := NewCtxExecutor(cb, "gno.land/r/gov/dao") + + // Execute as not the /r/gov/dao caller + uassert.ErrorIs(t, e.Execute(), errInvalidCaller) + uassert.False(t, called, "expected proposal to not execute") + }) + + t.Run("execution successful", func(t *testing.T) { + t.Parallel() + + var ( + called = false + + cb = func(ctx context.Context) error { + if !IsApprovedByGovdaoContext(ctx) { + t.Fatal("not govdao caller") + } + + called = true + + return nil + } + ) + + // Create the executor + daoPkgPath := "gno.land/r/gov/dao" + e := NewCtxExecutor(cb, daoPkgPath) + + // Execute as the /r/gov/dao caller + r := std.NewCodeRealm(daoPkgPath) + std.TestSetRealm(r) + + urequire.NoError(t, e.Execute()) + uassert.True(t, called, "expected proposal to execute") + }) + + t.Run("execution unsuccessful", func(t *testing.T) { + t.Parallel() + + var ( + called = false + expectedErr = errors.New("unexpected") + + cb = func(ctx context.Context) error { + if !IsApprovedByGovdaoContext(ctx) { + t.Fatal("not govdao caller") + } + + called = true + + return expectedErr + } + ) + + // Create the executor + daoPkgPath := "gno.land/r/gov/dao" + e := NewCtxExecutor(cb, daoPkgPath) + + // Execute as the /r/gov/dao caller + r := std.NewCodeRealm(daoPkgPath) + std.TestSetRealm(r) + + uassert.NotPanics(t, func() { + err := e.Execute() + + uassert.ErrorIs(t, err, expectedErr) + }) + + uassert.True(t, called, "expected proposal to execute") + }) +} diff --git a/examples/gno.land/p/gov/proposal/proposal.gno b/examples/gno.land/p/gov/proposal/proposal.gno deleted file mode 100644 index ca1767228c9..00000000000 --- a/examples/gno.land/p/gov/proposal/proposal.gno +++ /dev/null @@ -1,106 +0,0 @@ -// Package proposal provides a structure for executing proposals. -package proposal - -import ( - "errors" - "std" - - "gno.land/p/demo/context" -) - -var errNotGovDAO = errors.New("only r/gov/dao can be the caller") - -// NewExecutor creates a new executor with the provided callback function. -func NewExecutor(callback func() error) Executor { - return &executorImpl{ - callback: callback, - done: false, - } -} - -// NewCtxExecutor creates a new executor with the provided callback function. -func NewCtxExecutor(callback func(ctx context.Context) error) Executor { - return &executorImpl{ - callbackCtx: callback, - done: false, - } -} - -// executorImpl is an implementation of the Executor interface. -type executorImpl struct { - callback func() error - callbackCtx func(ctx context.Context) error - done bool - success bool -} - -// Execute runs the executor's callback function. -func (exec *executorImpl) Execute() error { - if exec.done { - return ErrAlreadyDone - } - - // Verify the executor is r/gov/dao - assertCalledByGovdao() - - var err error - if exec.callback != nil { - err = exec.callback() - } else if exec.callbackCtx != nil { - ctx := context.WithValue(context.Empty(), statusContextKey, approvedStatus) - err = exec.callbackCtx(ctx) - } - exec.done = true - exec.success = err == nil - - return err -} - -// IsDone returns whether the executor has been executed. -func (exec *executorImpl) IsDone() bool { - return exec.done -} - -// IsSuccessful returns whether the execution was successful. -func (exec *executorImpl) IsSuccessful() bool { - return exec.success -} - -// IsExpired returns whether the execution had expired or not. -// This implementation never expires. -func (exec *executorImpl) IsExpired() bool { - return false -} - -func IsApprovedByGovdaoContext(ctx context.Context) bool { - v := ctx.Value(statusContextKey) - if v == nil { - return false - } - vs, ok := v.(string) - return ok && vs == approvedStatus -} - -func AssertContextApprovedByGovDAO(ctx context.Context) { - if !IsApprovedByGovdaoContext(ctx) { - panic("not approved by govdao") - } -} - -// assertCalledByGovdao asserts that the calling Realm is /r/gov/dao -func assertCalledByGovdao() { - caller := std.CurrentRealm().PkgPath() - - if caller != daoPkgPath { - panic(errNotGovDAO) - } -} - -type propContextKey string - -func (k propContextKey) String() string { return string(k) } - -const ( - statusContextKey = propContextKey("govdao-prop-status") - approvedStatus = "approved" -) diff --git a/examples/gno.land/p/gov/proposal/proposal_test.gno b/examples/gno.land/p/gov/proposal/proposal_test.gno deleted file mode 100644 index 536871e644d..00000000000 --- a/examples/gno.land/p/gov/proposal/proposal_test.gno +++ /dev/null @@ -1,156 +0,0 @@ -package proposal - -import ( - "errors" - "std" - "testing" - - "gno.land/p/demo/uassert" - "gno.land/p/demo/urequire" -) - -func TestExecutor(t *testing.T) { - t.Parallel() - - verifyProposalFailed := func(e Executor) { - uassert.True(t, e.IsDone(), "expected proposal to be done") - uassert.False(t, e.IsSuccessful(), "expected proposal to fail") - } - - verifyProposalSucceeded := func(e Executor) { - uassert.True(t, e.IsDone(), "expected proposal to be done") - uassert.True(t, e.IsSuccessful(), "expected proposal to be successful") - } - - t.Run("govdao not caller", func(t *testing.T) { - t.Parallel() - - var ( - called = false - - cb = func() error { - called = true - - return nil - } - ) - - // Create the executor - e := NewExecutor(cb) - - urequire.False(t, e.IsDone(), "expected status to be NotExecuted") - - // Execute as not the /r/gov/dao caller - uassert.PanicsWithMessage(t, errNotGovDAO.Error(), func() { - _ = e.Execute() - }) - - uassert.False(t, called, "expected proposal to not execute") - }) - - t.Run("execution successful", func(t *testing.T) { - t.Parallel() - - var ( - called = false - - cb = func() error { - called = true - - return nil - } - ) - - // Create the executor - e := NewExecutor(cb) - - urequire.False(t, e.IsDone(), "expected status to be NotExecuted") - - // Execute as the /r/gov/dao caller - r := std.NewCodeRealm(daoPkgPath) - std.TestSetRealm(r) - - uassert.NotPanics(t, func() { - err := e.Execute() - - uassert.NoError(t, err) - }) - - uassert.True(t, called, "expected proposal to execute") - - // Make sure the execution params are correct - verifyProposalSucceeded(e) - }) - - t.Run("execution unsuccessful", func(t *testing.T) { - t.Parallel() - - var ( - called = false - expectedErr = errors.New("unexpected") - - cb = func() error { - called = true - - return expectedErr - } - ) - - // Create the executor - e := NewExecutor(cb) - - // Execute as the /r/gov/dao caller - r := std.NewCodeRealm(daoPkgPath) - std.TestSetRealm(r) - - uassert.NotPanics(t, func() { - err := e.Execute() - - uassert.ErrorIs(t, err, expectedErr) - }) - - uassert.True(t, called, "expected proposal to execute") - - // Make sure the execution params are correct - verifyProposalFailed(e) - }) - - t.Run("proposal already executed", func(t *testing.T) { - t.Parallel() - - var ( - called = false - - cb = func() error { - called = true - - return nil - } - ) - - // Create the executor - e := NewExecutor(cb) - - urequire.False(t, e.IsDone(), "expected status to be NotExecuted") - - // Execute as the /r/gov/dao caller - r := std.NewCodeRealm(daoPkgPath) - std.TestSetRealm(r) - - uassert.NotPanics(t, func() { - uassert.NoError(t, e.Execute()) - }) - - uassert.True(t, called, "expected proposal to execute") - - // Make sure the execution params are correct - verifyProposalSucceeded(e) - - // Attempt to execute the proposal again - uassert.NotPanics(t, func() { - err := e.Execute() - - uassert.ErrorIs(t, err, ErrAlreadyDone) - }) - }) -} diff --git a/examples/gno.land/p/gov/proposal/types.gno b/examples/gno.land/p/gov/proposal/types.gno deleted file mode 100644 index 6cd2da9ccfe..00000000000 --- a/examples/gno.land/p/gov/proposal/types.gno +++ /dev/null @@ -1,37 +0,0 @@ -// Package proposal defines types for proposal execution. -package proposal - -import "errors" - -// Executor represents a minimal closure-oriented proposal design. -// It is intended to be used by a govdao governance proposal (v1, v2, etc). -type Executor interface { - // Execute executes the given proposal, and returns any error encountered - // during the execution - Execute() error - - // IsDone returns a flag indicating if the proposal was executed - IsDone() bool - - // IsSuccessful returns a flag indicating if the proposal was executed - // and is successful - IsSuccessful() bool // IsDone() && !err - - // IsExpired returns whether the execution had expired or not. - IsExpired() bool -} - -// ErrAlreadyDone is the error returned when trying to execute an already -// executed proposal. -var ErrAlreadyDone = errors.New("already executed") - -// Status enum. -type Status string - -const ( - NotExecuted Status = "not_executed" - Succeeded Status = "succeeded" - Failed Status = "failed" -) - -const daoPkgPath = "gno.land/r/gov/dao" // TODO: make sure this is configurable through r/sys/vars diff --git a/examples/gno.land/p/moul/helplink/gno.mod b/examples/gno.land/p/moul/helplink/gno.mod new file mode 100644 index 00000000000..1b106749260 --- /dev/null +++ b/examples/gno.land/p/moul/helplink/gno.mod @@ -0,0 +1,6 @@ +module gno.land/p/moul/helplink + +require ( + gno.land/p/demo/urequire v0.0.0-latest + gno.land/p/moul/txlink v0.0.0-latest +) diff --git a/examples/gno.land/p/moul/helplink/helplink.gno b/examples/gno.land/p/moul/helplink/helplink.gno new file mode 100644 index 00000000000..b9ac8e102b9 --- /dev/null +++ b/examples/gno.land/p/moul/helplink/helplink.gno @@ -0,0 +1,79 @@ +// Package helplink provides utilities for creating help page links compatible +// with Gnoweb, Gnobro, and other clients that support the Gno contracts' +// flavored Markdown format. +// +// This package simplifies the generation of dynamic, context-sensitive help +// links, enabling users to navigate relevant documentation seamlessly within +// the Gno ecosystem. +// +// For a more lightweight alternative, consider using p/moul/txlink. +// +// The primary functions — Func, FuncURL, and Home — are intended for use with +// the "relative realm". When specifying a custom Realm, you can create links +// that utilize either the current realm path or a fully qualified path to +// another realm. +package helplink + +import ( + "strings" + + "gno.land/p/moul/txlink" +) + +const chainDomain = "gno.land" // XXX: std.ChainDomain (#2911) + +// Func returns a markdown link for the specific function with optional +// key-value arguments, for the current realm. +func Func(title string, fn string, args ...string) string { + return Realm("").Func(title, fn, args...) +} + +// FuncURL returns a URL for the specified function with optional key-value +// arguments, for the current realm. +func FuncURL(fn string, args ...string) string { + return Realm("").FuncURL(fn, args...) +} + +// Home returns the URL for the help homepage of the current realm. +func Home() string { + return Realm("").Home() +} + +// Realm represents a specific realm for generating help links. +type Realm string + +// prefix returns the URL prefix for the realm. +func (r Realm) prefix() string { + // relative + if r == "" { + return "" + } + + // local realm -> /realm + realm := string(r) + if strings.Contains(realm, chainDomain) { + return strings.TrimPrefix(realm, chainDomain) + } + + // remote realm -> https://remote.land/realm + return "https://" + string(r) +} + +// Func returns a markdown link for the specified function with optional +// key-value arguments. +func (r Realm) Func(title string, fn string, args ...string) string { + // XXX: escape title + return "[" + title + "](" + r.FuncURL(fn, args...) + ")" +} + +// FuncURL returns a URL for the specified function with optional key-value +// arguments. +func (r Realm) FuncURL(fn string, args ...string) string { + tlr := txlink.Realm(r) + return tlr.URL(fn, args...) +} + +// Home returns the base help URL for the specified realm. +func (r Realm) Home() string { + return r.prefix() + "?help" +} diff --git a/examples/gno.land/p/moul/helplink/helplink_test.gno b/examples/gno.land/p/moul/helplink/helplink_test.gno new file mode 100644 index 00000000000..07111158a98 --- /dev/null +++ b/examples/gno.land/p/moul/helplink/helplink_test.gno @@ -0,0 +1,78 @@ +package helplink + +import ( + "testing" + + "gno.land/p/demo/urequire" +) + +func TestFunc(t *testing.T) { + tests := []struct { + title string + fn string + args []string + want string + realm Realm + }{ + {"Example", "foo", []string{"bar", "1", "baz", "2"}, "[Example](?help&__func=foo&bar=1&baz=2)", ""}, + {"Realm Example", "foo", []string{"bar", "1", "baz", "2"}, "[Realm Example](/r/lorem/ipsum?help&__func=foo&bar=1&baz=2)", "gno.land/r/lorem/ipsum"}, + {"Single Arg", "testFunc", []string{"key", "value"}, "[Single Arg](?help&__func=testFunc&key=value)", ""}, + {"No Args", "noArgsFunc", []string{}, "[No Args](?help&__func=noArgsFunc)", ""}, + {"Odd Args", "oddArgsFunc", []string{"key"}, "[Odd Args](?help&__func=oddArgsFunc)", ""}, + } + + for _, tt := range tests { + t.Run(tt.title, func(t *testing.T) { + got := tt.realm.Func(tt.title, tt.fn, tt.args...) + urequire.Equal(t, tt.want, got) + }) + } +} + +func TestFuncURL(t *testing.T) { + tests := []struct { + fn string + args []string + want string + realm Realm + }{ + {"foo", []string{"bar", "1", "baz", "2"}, "?help&__func=foo&bar=1&baz=2", ""}, + {"testFunc", []string{"key", "value"}, "?help&__func=testFunc&key=value", ""}, + {"noArgsFunc", []string{}, "?help&__func=noArgsFunc", ""}, + {"oddArgsFunc", []string{"key"}, "?help&__func=oddArgsFunc", ""}, + {"foo", []string{"bar", "1", "baz", "2"}, "/r/lorem/ipsum?help&__func=foo&bar=1&baz=2", "gno.land/r/lorem/ipsum"}, + {"testFunc", []string{"key", "value"}, "/r/lorem/ipsum?help&__func=testFunc&key=value", "gno.land/r/lorem/ipsum"}, + {"noArgsFunc", []string{}, "/r/lorem/ipsum?help&__func=noArgsFunc", "gno.land/r/lorem/ipsum"}, + {"oddArgsFunc", []string{"key"}, "/r/lorem/ipsum?help&__func=oddArgsFunc", "gno.land/r/lorem/ipsum"}, + {"foo", []string{"bar", "1", "baz", "2"}, "https://gno.world/r/lorem/ipsum?help&__func=foo&bar=1&baz=2", "gno.world/r/lorem/ipsum"}, + {"testFunc", []string{"key", "value"}, "https://gno.world/r/lorem/ipsum?help&__func=testFunc&key=value", "gno.world/r/lorem/ipsum"}, + {"noArgsFunc", []string{}, "https://gno.world/r/lorem/ipsum?help&__func=noArgsFunc", "gno.world/r/lorem/ipsum"}, + {"oddArgsFunc", []string{"key"}, "https://gno.world/r/lorem/ipsum?help&__func=oddArgsFunc", "gno.world/r/lorem/ipsum"}, + } + + for _, tt := range tests { + title := tt.fn + t.Run(title, func(t *testing.T) { + got := tt.realm.FuncURL(tt.fn, tt.args...) + urequire.Equal(t, tt.want, got) + }) + } +} + +func TestHome(t *testing.T) { + tests := []struct { + realm Realm + want string + }{ + {"", "?help"}, + {"gno.land/r/lorem/ipsum", "/r/lorem/ipsum?help"}, + {"gno.world/r/lorem/ipsum", "https://gno.world/r/lorem/ipsum?help"}, + } + + for _, tt := range tests { + t.Run(string(tt.realm), func(t *testing.T) { + got := tt.realm.Home() + urequire.Equal(t, tt.want, got) + }) + } +} diff --git a/examples/gno.land/p/moul/txlink/gno.mod b/examples/gno.land/p/moul/txlink/gno.mod new file mode 100644 index 00000000000..6110464316f --- /dev/null +++ b/examples/gno.land/p/moul/txlink/gno.mod @@ -0,0 +1,3 @@ +module gno.land/p/moul/txlink + +require gno.land/p/demo/urequire v0.0.0-latest diff --git a/examples/gno.land/p/moul/txlink/txlink.gno b/examples/gno.land/p/moul/txlink/txlink.gno new file mode 100644 index 00000000000..26656e67f29 --- /dev/null +++ b/examples/gno.land/p/moul/txlink/txlink.gno @@ -0,0 +1,74 @@ +// Package txlink provides utilities for creating transaction-related links +// compatible with Gnoweb, Gnobro, and other clients within the Gno ecosystem. +// +// This package is optimized for generating lightweight transaction links with +// flexible arguments, allowing users to build dynamic links that integrate +// seamlessly with various Gno clients. +// +// The primary function, URL, is designed to produce markdown links for +// transaction functions in the current "relative realm". By specifying a custom +// Realm, you can generate links that either use the current realm path or a +// fully qualified path for another realm. +// +// This package is a streamlined alternative to helplink, providing similar +// functionality for transaction links without the full feature set of helplink. +package txlink + +import ( + "std" + "strings" +) + +const chainDomain = "gno.land" // XXX: std.ChainDomain (#2911) + +// URL returns a URL for the specified function with optional key-value +// arguments, for the current realm. +func URL(fn string, args ...string) string { + return Realm("").URL(fn, args...) +} + +// Realm represents a specific realm for generating tx links. +type Realm string + +// prefix returns the URL prefix for the realm. +func (r Realm) prefix() string { + // relative + if r == "" { + curPath := std.CurrentRealm().PkgPath() + return strings.TrimPrefix(curPath, chainDomain) + } + + // local realm -> /realm + realm := string(r) + if strings.Contains(realm, chainDomain) { + return strings.TrimPrefix(realm, chainDomain) + } + + // remote realm -> https://remote.land/realm + return "https://" + string(r) +} + +// URL returns a URL for the specified function with optional key-value +// arguments. +func (r Realm) URL(fn string, args ...string) string { + // Start with the base query + url := r.prefix() + "?help&__func=" + fn + + // Check if args length is even + if len(args)%2 != 0 { + // If not even, we can choose to handle the error here. + // For example, we can just return the URL without appending + // more args. + return url + } + + // Append key-value pairs to the URL + for i := 0; i < len(args); i += 2 { + key := args[i] + value := args[i+1] + // XXX: escape keys and args + url += "&" + key + "=" + value + } + + return url +} diff --git a/examples/gno.land/p/moul/txlink/txlink_test.gno b/examples/gno.land/p/moul/txlink/txlink_test.gno new file mode 100644 index 00000000000..7a460889148 --- /dev/null +++ b/examples/gno.land/p/moul/txlink/txlink_test.gno @@ -0,0 +1,37 @@ +package txlink + +import ( + "testing" + + "gno.land/p/demo/urequire" +) + +func TestURL(t *testing.T) { + tests := []struct { + fn string + args []string + want string + realm Realm + }{ + {"foo", []string{"bar", "1", "baz", "2"}, "?help&__func=foo&bar=1&baz=2", ""}, + {"testFunc", []string{"key", "value"}, "?help&__func=testFunc&key=value", ""}, + {"noArgsFunc", []string{}, "?help&__func=noArgsFunc", ""}, + {"oddArgsFunc", []string{"key"}, "?help&__func=oddArgsFunc", ""}, + {"foo", []string{"bar", "1", "baz", "2"}, "/r/lorem/ipsum?help&__func=foo&bar=1&baz=2", "gno.land/r/lorem/ipsum"}, + {"testFunc", []string{"key", "value"}, "/r/lorem/ipsum?help&__func=testFunc&key=value", "gno.land/r/lorem/ipsum"}, + {"noArgsFunc", []string{}, "/r/lorem/ipsum?help&__func=noArgsFunc", "gno.land/r/lorem/ipsum"}, + {"oddArgsFunc", []string{"key"}, "/r/lorem/ipsum?help&__func=oddArgsFunc", "gno.land/r/lorem/ipsum"}, + {"foo", []string{"bar", "1", "baz", "2"}, "https://gno.world/r/lorem/ipsum?help&__func=foo&bar=1&baz=2", "gno.world/r/lorem/ipsum"}, + {"testFunc", []string{"key", "value"}, "https://gno.world/r/lorem/ipsum?help&__func=testFunc&key=value", "gno.world/r/lorem/ipsum"}, + {"noArgsFunc", []string{}, "https://gno.world/r/lorem/ipsum?help&__func=noArgsFunc", "gno.world/r/lorem/ipsum"}, + {"oddArgsFunc", []string{"key"}, "https://gno.world/r/lorem/ipsum?help&__func=oddArgsFunc", "gno.world/r/lorem/ipsum"}, + } + + for _, tt := range tests { + title := tt.fn + t.Run(title, func(t *testing.T) { + got := tt.realm.URL(tt.fn, tt.args...) + urequire.Equal(t, tt.want, got) + }) + } +} diff --git a/examples/gno.land/r/demo/banktest/z_0_filetest.gno b/examples/gno.land/r/demo/banktest/z_0_filetest.gno index 4ea76bbe17a..61289dfe071 100644 --- a/examples/gno.land/r/demo/banktest/z_0_filetest.gno +++ b/examples/gno.land/r/demo/banktest/z_0_filetest.gno @@ -1,6 +1,11 @@ +// Empty line between the directives is important for them to be parsed +// independently. :facepalm: + +// PKGPATH: gno.land/r/demo/bank1 + // SEND: 100000000ugnot -package main +package bank1 import ( "std" @@ -11,7 +16,7 @@ import ( func main() { // set up main address and banktest addr. banktestAddr := std.DerivePkgAddr("gno.land/r/demo/banktest") - mainaddr := std.DerivePkgAddr("main") + mainaddr := std.DerivePkgAddr("gno.land/r/demo/bank1") std.TestSetOrigCaller(mainaddr) std.TestSetOrigPkgAddr(banktestAddr) @@ -42,7 +47,7 @@ func main() { // main after: 250000000ugnot // ## recent activity // -// * g17rgsdnfxzza0sdfsdma37sdwxagsz378833ca4 100000000ugnot sent, 50000000ugnot returned, at 2009-02-13 11:31pm UTC +// * g1tnpdmvrmtgql8fmxgsq9rwtst5hsxahk3f05dk 100000000ugnot sent, 50000000ugnot returned, at 2009-02-13 11:31pm UTC // // ## total deposits // 50000000ugnot diff --git a/examples/gno.land/r/demo/banktest/z_1_filetest.gno b/examples/gno.land/r/demo/banktest/z_1_filetest.gno index 8f9f7647036..39682d26330 100644 --- a/examples/gno.land/r/demo/banktest/z_1_filetest.gno +++ b/examples/gno.land/r/demo/banktest/z_1_filetest.gno @@ -1,4 +1,9 @@ -package main +// Empty line between the directives is important for them to be parsed +// independently. :facepalm: + +// PKGPATH: gno.land/r/demo/bank1 + +package bank1 import ( "std" diff --git a/examples/gno.land/r/demo/banktest/z_2_filetest.gno b/examples/gno.land/r/demo/banktest/z_2_filetest.gno index a0280e0d75b..2dc9c84e767 100644 --- a/examples/gno.land/r/demo/banktest/z_2_filetest.gno +++ b/examples/gno.land/r/demo/banktest/z_2_filetest.gno @@ -1,4 +1,9 @@ -package main +// Empty line between the directives is important for them to be parsed +// independently. :facepalm: + +// PKGPATH: gno.land/r/demo/bank1 + +package bank1 import ( "std" @@ -10,7 +15,7 @@ func main() { banktestAddr := std.DerivePkgAddr("gno.land/r/demo/banktest") // print main balance before. - mainaddr := std.DerivePkgAddr("main") + mainaddr := std.DerivePkgAddr("gno.land/r/demo/bank1") std.TestSetOrigCaller(mainaddr) banker := std.GetBanker(std.BankerTypeReadonly) @@ -39,7 +44,7 @@ func main() { // main after: 255000000ugnot // ## recent activity // -// * g17rgsdnfxzza0sdfsdma37sdwxagsz378833ca4 100000000ugnot sent, 55000000ugnot returned, at 2009-02-13 11:31pm UTC +// * g1tnpdmvrmtgql8fmxgsq9rwtst5hsxahk3f05dk 100000000ugnot sent, 55000000ugnot returned, at 2009-02-13 11:31pm UTC // // ## total deposits // 45000000ugnot diff --git a/examples/gno.land/r/demo/banktest/z_3_filetest.gno b/examples/gno.land/r/demo/banktest/z_3_filetest.gno index ca8717dfcc9..7b6758c3e4f 100644 --- a/examples/gno.land/r/demo/banktest/z_3_filetest.gno +++ b/examples/gno.land/r/demo/banktest/z_3_filetest.gno @@ -1,4 +1,9 @@ -package main +// Empty line between the directives is important for them to be parsed +// independently. :facepalm: + +// PKGPATH: gno.land/r/demo/bank1 + +package bank1 import ( "std" @@ -7,7 +12,7 @@ import ( func main() { banktestAddr := std.DerivePkgAddr("gno.land/r/demo/banktest") - mainaddr := std.DerivePkgAddr("main") + mainaddr := std.DerivePkgAddr("gno.land/r/demo/bank1") std.TestSetOrigCaller(mainaddr) banker := std.GetBanker(std.BankerTypeRealmSend) @@ -17,4 +22,4 @@ func main() { } // Error: -// can only send coins from realm that created banker "g17rgsdnfxzza0sdfsdma37sdwxagsz378833ca4", not "g1dv3435088tlrgggf745kaud0ptrkc9v42k8llz" +// can only send coins from realm that created banker "g1tnpdmvrmtgql8fmxgsq9rwtst5hsxahk3f05dk", not "g1dv3435088tlrgggf745kaud0ptrkc9v42k8llz" diff --git a/examples/gno.land/r/demo/boards/board.gno b/examples/gno.land/r/demo/boards/board.gno index a9cf56c2a91..79b27da84b2 100644 --- a/examples/gno.land/r/demo/boards/board.gno +++ b/examples/gno.land/r/demo/boards/board.gno @@ -6,6 +6,7 @@ import ( "time" "gno.land/p/demo/avl" + "gno.land/p/moul/txlink" ) //---------------------------------------- @@ -134,7 +135,5 @@ func (board *Board) GetURLFromThreadAndReplyID(threadID, replyID PostID) string } func (board *Board) GetPostFormURL() string { - return "/r/demo/boards?help&__func=CreateThread" + - "&bid=" + board.id.String() + - "&body.type=textarea" + return txlink.URL("CreateThread", "bid", board.id.String()) } diff --git a/examples/gno.land/r/demo/boards/gno.mod b/examples/gno.land/r/demo/boards/gno.mod index 434ad019883..24fea7ce853 100644 --- a/examples/gno.land/r/demo/boards/gno.mod +++ b/examples/gno.land/r/demo/boards/gno.mod @@ -2,5 +2,6 @@ module gno.land/r/demo/boards require ( gno.land/p/demo/avl v0.0.0-latest + gno.land/p/moul/txlink v0.0.0-latest gno.land/r/demo/users v0.0.0-latest ) diff --git a/examples/gno.land/r/demo/boards/post.gno b/examples/gno.land/r/demo/boards/post.gno index f35cf23628c..95d4b2977ba 100644 --- a/examples/gno.land/r/demo/boards/post.gno +++ b/examples/gno.land/r/demo/boards/post.gno @@ -6,6 +6,7 @@ import ( "time" "gno.land/p/demo/avl" + "gno.land/p/moul/txlink" ) //---------------------------------------- @@ -155,27 +156,26 @@ func (post *Post) GetURL() string { } func (post *Post) GetReplyFormURL() string { - return "/r/demo/boards?help&__func=CreateReply" + - "&bid=" + post.board.id.String() + - "&threadid=" + post.threadID.String() + - "&postid=" + post.id.String() + - "&body.type=textarea" + return txlink.URL("CreateReply", + "bid", post.board.id.String(), + "threadid", post.threadID.String(), + "postid", post.id.String(), + ) } func (post *Post) GetRepostFormURL() string { - return "/r/demo/boards?help&__func=CreateRepost" + - "&bid=" + post.board.id.String() + - "&postid=" + post.id.String() + - "&title.type=textarea" + - "&body.type=textarea" + - "&dstBoardID.type=textarea" + return txlink.URL("CreateRepost", + "bid", post.board.id.String(), + "postid", post.id.String(), + ) } func (post *Post) GetDeleteFormURL() string { - return "/r/demo/boards?help&__func=DeletePost" + - "&bid=" + post.board.id.String() + - "&threadid=" + post.threadID.String() + - "&postid=" + post.id.String() + return txlink.URL("DeletePost", + "bid", post.board.id.String(), + "threadid", post.threadID.String(), + "postid", post.id.String(), + ) } func (post *Post) RenderSummary() string { diff --git a/examples/gno.land/r/demo/boards/z_0_filetest.gno b/examples/gno.land/r/demo/boards/z_0_filetest.gno index e20964d50b7..cdf136be590 100644 --- a/examples/gno.land/r/demo/boards/z_0_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_0_filetest.gno @@ -24,7 +24,7 @@ func main() { } // Output: -// \[[post](/r/demo/boards?help&__func=CreateThread&bid=1&body.type=textarea)] +// \[[post](/r/demo/boards?help&__func=CreateThread&bid=1)] // // ---------------------------------------- // ## [First Post (title)](/r/demo/boards:test_board/1) diff --git a/examples/gno.land/r/demo/boards/z_10_c_filetest.gno b/examples/gno.land/r/demo/boards/z_10_c_filetest.gno index 8555af0b576..cc8d188f727 100644 --- a/examples/gno.land/r/demo/boards/z_10_c_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_10_c_filetest.gno @@ -35,14 +35,14 @@ func main() { // # First Post in (title) // // Body of the first post. (body) -// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=1&body.type=textarea)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=1&title.type=textarea&body.type=textarea&dstBoardID.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=1)] +// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=1)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=1)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=1)] // // > First reply of the First post // > -// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1/2) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=2&body.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=2)] +// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1/2) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=2)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=2)] // // ---------------------------------------------------- // # First Post in (title) // // Body of the first post. (body) -// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=1&body.type=textarea)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=1&title.type=textarea&body.type=textarea&dstBoardID.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=1)] +// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=1)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=1)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=1)] diff --git a/examples/gno.land/r/demo/boards/z_10_filetest.gno b/examples/gno.land/r/demo/boards/z_10_filetest.gno index 548b5865f65..0a4626003d1 100644 --- a/examples/gno.land/r/demo/boards/z_10_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_10_filetest.gno @@ -33,7 +33,7 @@ func main() { // # First Post in (title) // // Body of the first post. (body) -// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=1&body.type=textarea)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=1&title.type=textarea&body.type=textarea&dstBoardID.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=1)] +// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=1)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=1)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=1)] // // ---------------------------------------------------- // thread does not exist with id: 1 diff --git a/examples/gno.land/r/demo/boards/z_11_d_filetest.gno b/examples/gno.land/r/demo/boards/z_11_d_filetest.gno index c114e769ab1..04dd6bfb547 100644 --- a/examples/gno.land/r/demo/boards/z_11_d_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_11_d_filetest.gno @@ -35,18 +35,18 @@ func main() { // # First Post in (title) // // Body of the first post. (body) -// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=1&body.type=textarea)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=1&title.type=textarea&body.type=textarea&dstBoardID.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=1)] +// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=1)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=1)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=1)] // // > First reply of the First post // > -// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1/2) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=2&body.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=2)] +// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1/2) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=2)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=2)] // // ---------------------------------------------------- // # First Post in (title) // // Body of the first post. (body) -// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=1&body.type=textarea)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=1&title.type=textarea&body.type=textarea&dstBoardID.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=1)] +// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=1)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=1)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=1)] // // > Edited: First reply of the First post // > -// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1/2) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=2&body.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=2)] +// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1/2) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=2)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=2)] diff --git a/examples/gno.land/r/demo/boards/z_11_filetest.gno b/examples/gno.land/r/demo/boards/z_11_filetest.gno index 4cbdeeca4c3..0974991b814 100644 --- a/examples/gno.land/r/demo/boards/z_11_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_11_filetest.gno @@ -33,10 +33,10 @@ func main() { // # First Post in (title) // // Body of the first post. (body) -// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=1&body.type=textarea)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=1&title.type=textarea&body.type=textarea&dstBoardID.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=1)] +// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=1)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=1)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=1)] // // ---------------------------------------------------- // # Edited: First Post in (title) // // Edited: Body of the first post. (body) -// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=1&body.type=textarea)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=1&title.type=textarea&body.type=textarea&dstBoardID.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=1)] +// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=1)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=1)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=1)] diff --git a/examples/gno.land/r/demo/boards/z_12_filetest.gno b/examples/gno.land/r/demo/boards/z_12_filetest.gno index 4ea75b27753..8ae1c99ffbb 100644 --- a/examples/gno.land/r/demo/boards/z_12_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_12_filetest.gno @@ -30,7 +30,7 @@ func main() { // Output: // 1 -// \[[post](/r/demo/boards?help&__func=CreateThread&bid=2&body.type=textarea)] +// \[[post](/r/demo/boards?help&__func=CreateThread&bid=2)] // // ---------------------------------------- // Repost: Check this out diff --git a/examples/gno.land/r/demo/boards/z_2_filetest.gno b/examples/gno.land/r/demo/boards/z_2_filetest.gno index f0d53204e38..037a855eab1 100644 --- a/examples/gno.land/r/demo/boards/z_2_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_2_filetest.gno @@ -32,7 +32,7 @@ func main() { // # Second Post (title) // // Body of the second post. (body) -// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=2&body.type=textarea)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=2&title.type=textarea&body.type=textarea&dstBoardID.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=2)] +// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=2)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=2)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=2)] // // > Reply of the second post -// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/3) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=3&body.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=3)] +// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/3) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=3)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=3)] diff --git a/examples/gno.land/r/demo/boards/z_3_filetest.gno b/examples/gno.land/r/demo/boards/z_3_filetest.gno index 021ae10b825..79770aa1cec 100644 --- a/examples/gno.land/r/demo/boards/z_3_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_3_filetest.gno @@ -34,7 +34,7 @@ func main() { // # Second Post (title) // // Body of the second post. (body) -// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=2&body.type=textarea)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=2&title.type=textarea&body.type=textarea&dstBoardID.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=2)] +// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=2)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=2)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=2)] // // > Reply of the second post -// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/3) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=3&body.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=3)] +// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/3) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=3)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=3)] diff --git a/examples/gno.land/r/demo/boards/z_4_filetest.gno b/examples/gno.land/r/demo/boards/z_4_filetest.gno index f0620c28c9d..61e4681f202 100644 --- a/examples/gno.land/r/demo/boards/z_4_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_4_filetest.gno @@ -37,13 +37,13 @@ func main() { // # Second Post (title) // // Body of the second post. (body) -// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=2&body.type=textarea)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=2&title.type=textarea&body.type=textarea&dstBoardID.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=2)] +// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=2)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=2)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=2)] // // > Reply of the second post -// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/3) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=3&body.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=3)] +// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/3) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=3)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=3)] // // > Second reply of the second post -// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/4) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=4&body.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=4)] +// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/4) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=4)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=4)] // Realm: // switchrealm["gno.land/r/demo/users"] diff --git a/examples/gno.land/r/demo/boards/z_5_c_filetest.gno b/examples/gno.land/r/demo/boards/z_5_c_filetest.gno index 176b1d89015..440daa6238d 100644 --- a/examples/gno.land/r/demo/boards/z_5_c_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_5_c_filetest.gno @@ -33,7 +33,7 @@ func main() { // # First Post (title) // // Body of the first post. (body) -// \- [g1w3jhxapjta047h6lta047h6lta047h6laqcyu4](/r/demo/users:g1w3jhxapjta047h6lta047h6lta047h6laqcyu4), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=1&body.type=textarea)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=1&title.type=textarea&body.type=textarea&dstBoardID.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=1)] +// \- [g1w3jhxapjta047h6lta047h6lta047h6laqcyu4](/r/demo/users:g1w3jhxapjta047h6lta047h6lta047h6laqcyu4), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=1)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=1)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=1)] // // > Reply of the first post -// > \- [g1w3jhxapjta047h6lta047h6lta047h6laqcyu4](/r/demo/users:g1w3jhxapjta047h6lta047h6lta047h6laqcyu4), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1/2) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=2&body.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=2)] +// > \- [g1w3jhxapjta047h6lta047h6lta047h6laqcyu4](/r/demo/users:g1w3jhxapjta047h6lta047h6lta047h6laqcyu4), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/1/2) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=1&postid=2)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=1&postid=2)] diff --git a/examples/gno.land/r/demo/boards/z_5_filetest.gno b/examples/gno.land/r/demo/boards/z_5_filetest.gno index c326d961c91..9d30d9aaa72 100644 --- a/examples/gno.land/r/demo/boards/z_5_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_5_filetest.gno @@ -33,11 +33,11 @@ func main() { // # Second Post (title) // // Body of the second post. (body) -// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=2&body.type=textarea)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=2&title.type=textarea&body.type=textarea&dstBoardID.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=2)] +// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=2)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=2)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=2)] // // > Reply of the second post -// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/3) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=3&body.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=3)] +// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/3) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=3)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=3)] // // > Second reply of the second post // > -// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/4) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=4&body.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=4)] +// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/4) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=4)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=4)] diff --git a/examples/gno.land/r/demo/boards/z_6_filetest.gno b/examples/gno.land/r/demo/boards/z_6_filetest.gno index b7de2d08bf9..fb7f9a31772 100644 --- a/examples/gno.land/r/demo/boards/z_6_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_6_filetest.gno @@ -35,15 +35,15 @@ func main() { // # Second Post (title) // // Body of the second post. (body) -// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=2&body.type=textarea)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=2&title.type=textarea&body.type=textarea&dstBoardID.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=2)] +// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=2)] \[[repost](/r/demo/boards?help&__func=CreateRepost&bid=1&postid=2)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=2)] // // > Reply of the second post -// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/3) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=3&body.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=3)] +// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/3) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=3)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=3)] // > // > > First reply of the first reply // > > -// > > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/5) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=5&body.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=5)] +// > > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/5) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=5)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=5)] // // > Second reply of the second post // > -// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/4) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=4&body.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=4)] +// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/4) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=4)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=4)] diff --git a/examples/gno.land/r/demo/boards/z_7_filetest.gno b/examples/gno.land/r/demo/boards/z_7_filetest.gno index f1d41aa1723..7df06fd760a 100644 --- a/examples/gno.land/r/demo/boards/z_7_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_7_filetest.gno @@ -22,7 +22,7 @@ func main() { } // Output: -// \[[post](/r/demo/boards?help&__func=CreateThread&bid=1&body.type=textarea)] +// \[[post](/r/demo/boards?help&__func=CreateThread&bid=1)] // // ---------------------------------------- // ## [First Post (title)](/r/demo/boards:test_board/1) diff --git a/examples/gno.land/r/demo/boards/z_8_filetest.gno b/examples/gno.land/r/demo/boards/z_8_filetest.gno index 18ad64083f4..02ce2c4fcef 100644 --- a/examples/gno.land/r/demo/boards/z_8_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_8_filetest.gno @@ -35,10 +35,10 @@ func main() { // _[see thread](/r/demo/boards:test_board/2)_ // // Reply of the second post -// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/3) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=3&body.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=3)] +// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/3) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=3)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=3)] // // _[see all 1 replies](/r/demo/boards:test_board/2/3)_ // // > First reply of the first reply // > -// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/5) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=5&body.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=5)] +// > \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/5) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=5)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=5)] diff --git a/examples/gno.land/r/demo/boards/z_9_filetest.gno b/examples/gno.land/r/demo/boards/z_9_filetest.gno index 10a1444fd35..823318a5e48 100644 --- a/examples/gno.land/r/demo/boards/z_9_filetest.gno +++ b/examples/gno.land/r/demo/boards/z_9_filetest.gno @@ -34,4 +34,4 @@ func main() { // # First Post in (title) // // Body of the first post. (body) -// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:second_board/1/1) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=2&threadid=1&postid=1&body.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=2&threadid=1&postid=1)] +// \- [@gnouser](/r/demo/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:second_board/1/1) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=2&threadid=1&postid=1)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=2&threadid=1&postid=1)] diff --git a/examples/gno.land/r/demo/disperse/z_0_filetest.gno b/examples/gno.land/r/demo/disperse/z_0_filetest.gno index 62a34cfdf26..e54b34ae3bf 100644 --- a/examples/gno.land/r/demo/disperse/z_0_filetest.gno +++ b/examples/gno.land/r/demo/disperse/z_0_filetest.gno @@ -1,3 +1,5 @@ +// PKGPATH: gno.land/r/demo/main + // SEND: 200ugnot package main @@ -10,7 +12,7 @@ import ( func main() { disperseAddr := std.DerivePkgAddr("gno.land/r/demo/disperse") - mainaddr := std.DerivePkgAddr("main") + mainaddr := std.DerivePkgAddr("gno.land/r/demo/main") std.TestSetOrigPkgAddr(disperseAddr) std.TestSetOrigCaller(mainaddr) diff --git a/examples/gno.land/r/demo/disperse/z_1_filetest.gno b/examples/gno.land/r/demo/disperse/z_1_filetest.gno index 1e042d320f6..62018fe965e 100644 --- a/examples/gno.land/r/demo/disperse/z_1_filetest.gno +++ b/examples/gno.land/r/demo/disperse/z_1_filetest.gno @@ -1,3 +1,5 @@ +// PKGPATH: gno.land/r/demo/main + // SEND: 300ugnot package main @@ -10,7 +12,7 @@ import ( func main() { disperseAddr := std.DerivePkgAddr("gno.land/r/demo/disperse") - mainaddr := std.DerivePkgAddr("main") + mainaddr := std.DerivePkgAddr("gno.land/r/demo/main") std.TestSetOrigPkgAddr(disperseAddr) std.TestSetOrigCaller(mainaddr) diff --git a/examples/gno.land/r/demo/disperse/z_2_filetest.gno b/examples/gno.land/r/demo/disperse/z_2_filetest.gno index 163bb2fc1ab..79e8d81e2b1 100644 --- a/examples/gno.land/r/demo/disperse/z_2_filetest.gno +++ b/examples/gno.land/r/demo/disperse/z_2_filetest.gno @@ -1,3 +1,5 @@ +// PKGPATH: gno.land/r/demo/main + // SEND: 300ugnot package main @@ -10,7 +12,7 @@ import ( func main() { disperseAddr := std.DerivePkgAddr("gno.land/r/demo/disperse") - mainaddr := std.DerivePkgAddr("main") + mainaddr := std.DerivePkgAddr("gno.land/r/demo/main") std.TestSetOrigPkgAddr(disperseAddr) std.TestSetOrigCaller(mainaddr) diff --git a/examples/gno.land/r/demo/disperse/z_3_filetest.gno b/examples/gno.land/r/demo/disperse/z_3_filetest.gno index eabed52fb38..7cb7ffbe71d 100644 --- a/examples/gno.land/r/demo/disperse/z_3_filetest.gno +++ b/examples/gno.land/r/demo/disperse/z_3_filetest.gno @@ -1,3 +1,5 @@ +// PKGPATH: gno.land/r/demo/main + // SEND: 300ugnot package main @@ -11,7 +13,7 @@ import ( func main() { disperseAddr := std.DerivePkgAddr("gno.land/r/demo/disperse") - mainaddr := std.DerivePkgAddr("main") + mainaddr := std.DerivePkgAddr("gno.land/r/demo/main") beneficiary1 := std.Address("g1dmt3sa5ucvecxuhf3j6ne5r0e3z4x7h6c03xc0") beneficiary2 := std.Address("g1akeqsvhucjt8gf5yupyzjxsjd29wv8fayng37c") diff --git a/examples/gno.land/r/demo/disperse/z_4_filetest.gno b/examples/gno.land/r/demo/disperse/z_4_filetest.gno index ebf4bed4473..4dafb780e83 100644 --- a/examples/gno.land/r/demo/disperse/z_4_filetest.gno +++ b/examples/gno.land/r/demo/disperse/z_4_filetest.gno @@ -1,3 +1,5 @@ +// PKGPATH: gno.land/r/demo/main + // SEND: 300ugnot package main @@ -11,7 +13,7 @@ import ( func main() { disperseAddr := std.DerivePkgAddr("gno.land/r/demo/disperse") - mainaddr := std.DerivePkgAddr("main") + mainaddr := std.DerivePkgAddr("gno.land/r/demo/main") beneficiary1 := std.Address("g1dmt3sa5ucvecxuhf3j6ne5r0e3z4x7h6c03xc0") beneficiary2 := std.Address("g1akeqsvhucjt8gf5yupyzjxsjd29wv8fayng37c") diff --git a/examples/gno.land/r/demo/event/z1_filetest.gno b/examples/gno.land/r/demo/event/z1_filetest.gno new file mode 100644 index 00000000000..b138aa4351c --- /dev/null +++ b/examples/gno.land/r/demo/event/z1_filetest.gno @@ -0,0 +1,34 @@ +package main + +import "gno.land/r/demo/event" + +func main() { + event.Emit("foo") + event.Emit("bar") +} + +// Events: +// [ +// { +// "type": "TAG", +// "attrs": [ +// { +// "key": "key", +// "value": "foo" +// } +// ], +// "pkg_path": "gno.land/r/demo/event", +// "func": "Emit" +// }, +// { +// "type": "TAG", +// "attrs": [ +// { +// "key": "key", +// "value": "bar" +// } +// ], +// "pkg_path": "gno.land/r/demo/event", +// "func": "Emit" +// } +// ] diff --git a/examples/gno.land/r/gnoland/blog/admin.gno b/examples/gno.land/r/gnoland/blog/admin.gno index 08b0911cf24..9c94a265fca 100644 --- a/examples/gno.land/r/gnoland/blog/admin.gno +++ b/examples/gno.land/r/gnoland/blog/admin.gno @@ -5,8 +5,8 @@ import ( "strings" "gno.land/p/demo/avl" - "gno.land/p/demo/context" - "gno.land/p/gov/proposal" + "gno.land/p/demo/dao" + "gno.land/r/gov/dao/bridge" ) var ( @@ -41,10 +41,14 @@ func AdminRemoveModerator(addr std.Address) { moderatorList.Set(addr.String(), false) // FIXME: delete instead? } -func DaoAddPost(ctx context.Context, slug, title, body, publicationDate, authors, tags string) { - proposal.AssertContextApprovedByGovDAO(ctx) - caller := std.DerivePkgAddr("gno.land/r/gov/dao") - addPost(caller, slug, title, body, publicationDate, authors, tags) +func NewPostExecutor(slug, title, body, publicationDate, authors, tags string) dao.Executor { + callback := func() error { + addPost(std.PrevRealm().Addr(), slug, title, body, publicationDate, authors, tags) + + return nil + } + + return bridge.GovDAO().NewGovDAOExecutor(callback) } func ModAddPost(slug, title, body, publicationDate, authors, tags string) { diff --git a/examples/gno.land/r/gnoland/blog/gno.mod b/examples/gno.land/r/gnoland/blog/gno.mod index 17c17e0cfa6..8a4c5851b4c 100644 --- a/examples/gno.land/r/gnoland/blog/gno.mod +++ b/examples/gno.land/r/gnoland/blog/gno.mod @@ -3,6 +3,6 @@ module gno.land/r/gnoland/blog require ( gno.land/p/demo/avl v0.0.0-latest gno.land/p/demo/blog v0.0.0-latest - gno.land/p/demo/context v0.0.0-latest - gno.land/p/gov/proposal v0.0.0-latest + gno.land/p/demo/dao v0.0.0-latest + gno.land/r/gov/dao/bridge v0.0.0-latest ) diff --git a/examples/gno.land/r/gnoland/events/events.gno b/examples/gno.land/r/gnoland/events/events.gno index 0984edf75a9..baf9ba3d4af 100644 --- a/examples/gno.land/r/gnoland/events/events.gno +++ b/examples/gno.land/r/gnoland/events/events.gno @@ -73,8 +73,7 @@ func AddEvent(name, description, link, location, startTime, endTime string) (str sort.Sort(events) std.Emit(EventAdded, - "id", - e.id, + "id", e.id, ) return id, nil @@ -92,8 +91,7 @@ func DeleteEvent(id string) { events = append(events[:idx], events[idx+1:]...) std.Emit(EventDeleted, - "id", - e.id, + "id", e.id, ) } @@ -142,8 +140,7 @@ func EditEvent(id string, name, description, link, location, startTime, endTime } std.Emit(EventEdited, - "id", - e.id, + "id", e.id, ) } diff --git a/examples/gno.land/r/gnoland/events/events_test.gno b/examples/gno.land/r/gnoland/events/events_test.gno index 357857352d8..1d79b754ee4 100644 --- a/examples/gno.land/r/gnoland/events/events_test.gno +++ b/examples/gno.land/r/gnoland/events/events_test.gno @@ -85,7 +85,8 @@ func TestAddEventErrors(t *testing.T) { } func TestDeleteEvent(t *testing.T) { - events = nil // remove elements from previous tests - see issue #1982 + std.TestSetOrigCaller(su) + std.TestSetRealm(suRealm) e1Start := parsedTimeNow.Add(time.Hour * 24 * 5) e1End := e1Start.Add(time.Hour * 4) @@ -107,7 +108,8 @@ func TestDeleteEvent(t *testing.T) { } func TestEditEvent(t *testing.T) { - events = nil // remove elements from previous tests - see issue #1982 + std.TestSetOrigCaller(su) + std.TestSetRealm(suRealm) e1Start := parsedTimeNow.Add(time.Hour * 24 * 5) e1End := e1Start.Add(time.Hour * 4) @@ -136,7 +138,8 @@ func TestEditEvent(t *testing.T) { } func TestInvalidEdit(t *testing.T) { - events = nil // remove elements from previous tests - see issue #1982 + std.TestSetOrigCaller(su) + std.TestSetRealm(suRealm) uassert.PanicsWithMessage(t, ErrNoSuchID.Error(), func() { EditEvent("123123", "", "", "", "", "", "") @@ -162,9 +165,11 @@ func TestParseTimes(t *testing.T) { } func TestRenderEventWidget(t *testing.T) { - events = nil // remove elements from previous tests - see issue #1982 + std.TestSetOrigCaller(su) + std.TestSetRealm(suRealm) // No events yet + events = nil out, err := RenderEventWidget(1) uassert.NoError(t, err) uassert.Equal(t, out, "No events.") diff --git a/examples/gno.land/r/gnoland/ghverify/contract.gno b/examples/gno.land/r/gnoland/ghverify/contract.gno index b40c9ef1448..3b8f7fcbbe1 100644 --- a/examples/gno.land/r/gnoland/ghverify/contract.gno +++ b/examples/gno.land/r/gnoland/ghverify/contract.gno @@ -83,6 +83,11 @@ func RequestVerification(githubHandle string) { ); err != nil { panic(err) } + std.Emit( + "verification_requested", + "from", gnoAddress, + "handle", githubHandle, + ) } // GnorkleEntrypoint is the entrypoint to the gnorkle oracle handler. @@ -139,7 +144,7 @@ func Render(_ string) string { result += `"` + handle + `": "` + address.(string) + `"` appendComma = true - return true + return false }) return result + "}" diff --git a/examples/gno.land/r/gnoland/ghverify/contract_test.gno b/examples/gno.land/r/gnoland/ghverify/contract_test.gno index d9c399942ae..5c0be0afcb1 100644 --- a/examples/gno.land/r/gnoland/ghverify/contract_test.gno +++ b/examples/gno.land/r/gnoland/ghverify/contract_test.gno @@ -9,7 +9,8 @@ import ( func TestVerificationLifecycle(t *testing.T) { defaultAddress := std.GetOrigCaller() - userAddress := std.Address(testutils.TestAddress("user")) + user1Address := std.Address(testutils.TestAddress("user 1")) + user2Address := std.Address(testutils.TestAddress("user 2")) // Verify request returns no feeds. result := GnorkleEntrypoint("request") @@ -18,7 +19,7 @@ func TestVerificationLifecycle(t *testing.T) { } // Make a verification request with the created user. - std.TestSetOrigCaller(userAddress) + std.TestSetOrigCaller(user1Address) RequestVerification("deelawn") // A subsequent request from the same address should panic because there is @@ -42,26 +43,32 @@ func TestVerificationLifecycle(t *testing.T) { t.Fatalf("expected empty request result, got %s", result) } + // Make a verification request with the created user. + std.TestSetOrigCaller(user2Address) + RequestVerification("omarsy") + // Set the caller back to the whitelisted user and verify that the feed data // returned matches what should have been created by the `RequestVerification` // invocation. std.TestSetOrigCaller(defaultAddress) result = GnorkleEntrypoint("request") - expResult := `[{"id":"` + string(userAddress) + `","type":"0","value_type":"string","tasks":[{"gno_address":"` + - string(userAddress) + `","github_handle":"deelawn"}]}]` + expResult := `[{"id":"` + string(user1Address) + `","type":"0","value_type":"string","tasks":[{"gno_address":"` + + string(user1Address) + `","github_handle":"deelawn"}]},` + + `{"id":"` + string(user2Address) + `","type":"0","value_type":"string","tasks":[{"gno_address":"` + + string(user2Address) + `","github_handle":"omarsy"}]}]` if result != expResult { t.Fatalf("expected request result %s, got %s", expResult, result) } // Try to trigger feed ingestion from the non-authorized user. - std.TestSetOrigCaller(userAddress) + std.TestSetOrigCaller(user1Address) func() { defer func() { if r := recover(); r != nil { errMsg = r.(error).Error() } }() - GnorkleEntrypoint("ingest," + string(userAddress) + ",OK") + GnorkleEntrypoint("ingest," + string(user1Address) + ",OK") }() if errMsg != "caller not whitelisted" { t.Fatalf("expected caller not whitelisted, got %s", errMsg) @@ -69,15 +76,15 @@ func TestVerificationLifecycle(t *testing.T) { // Set the caller back to the whitelisted user and transfer contract ownership. std.TestSetOrigCaller(defaultAddress) - SetOwner(userAddress) + SetOwner(defaultAddress) // Now trigger the feed ingestion from the user and new owner and only whitelisted address. - std.TestSetOrigCaller(userAddress) - GnorkleEntrypoint("ingest," + string(userAddress) + ",OK") + GnorkleEntrypoint("ingest," + string(user1Address) + ",OK") + GnorkleEntrypoint("ingest," + string(user2Address) + ",OK") // Verify the ingestion autocommitted the value and triggered the post handler. data := Render("") - expResult = `{"deelawn": "` + string(userAddress) + `"}` + expResult = `{"deelawn": "` + string(user1Address) + `","omarsy": "` + string(user2Address) + `"}` if data != expResult { t.Fatalf("expected render data %s, got %s", expResult, data) } @@ -89,10 +96,10 @@ func TestVerificationLifecycle(t *testing.T) { } // Check that the accessor functions are working as expected. - if handle := GetHandleByAddress(string(userAddress)); handle != "deelawn" { + if handle := GetHandleByAddress(string(user1Address)); handle != "deelawn" { t.Fatalf("expected deelawn, got %s", handle) } - if address := GetAddressByHandle("deelawn"); address != string(userAddress) { - t.Fatalf("expected %s, got %s", string(userAddress), address) + if address := GetAddressByHandle("deelawn"); address != string(user1Address) { + t.Fatalf("expected %s, got %s", string(user1Address), address) } } diff --git a/examples/gno.land/r/gnoland/home/home.gno b/examples/gno.land/r/gnoland/home/home.gno index 93f9a68f39a..57570902f5a 100644 --- a/examples/gno.land/r/gnoland/home/home.gno +++ b/examples/gno.land/r/gnoland/home/home.gno @@ -193,7 +193,7 @@ func packageStaffPicks() ui.Element { ui.BulletList{ ui.Link{URL: "r/sys/names"}, ui.Link{URL: "r/sys/rewards"}, - ui.Link{URL: "r/sys/validators"}, + ui.Link{URL: "/r/sys/validators/v2"}, }, }, { ui.H4("[r/demo](https://github.com/gnolang/gno/tree/master/examples/gno.land/r/demo)"), diff --git a/examples/gno.land/r/gnoland/home/home_filetest.gno b/examples/gno.land/r/gnoland/home/home_filetest.gno index 2260dc3a409..89721fd8d08 100644 --- a/examples/gno.land/r/gnoland/home/home_filetest.gno +++ b/examples/gno.land/r/gnoland/home/home_filetest.gno @@ -117,7 +117,7 @@ func main() { // // - [r/sys/names](r/sys/names) // - [r/sys/rewards](r/sys/rewards) -// - [r/sys/validators](r/sys/validators) +// - [/r/sys/validators/v2](/r/sys/validators/v2) // // //
diff --git a/examples/gno.land/r/gnoland/pages/page_contribute.gno b/examples/gno.land/r/gnoland/pages/page_contribute.gno index 3cdef10d9dc..0855dc327cd 100644 --- a/examples/gno.land/r/gnoland/pages/page_contribute.gno +++ b/examples/gno.land/r/gnoland/pages/page_contribute.gno @@ -45,7 +45,7 @@ Don't fear your work being "stolen": if a submission is the result of multiple p - If you, for instance, cannot complete the entirety of the task or, as a non-developer, can only contribute a part of the specification/implementation, you may still be awarded a bounty for your input in the contribution. - If Alice makes a PR that aside from implementing what's required, also undertakes creating useful tools among the way, she may qualify for an "outstanding contribution"; and may be awarded up to 25% more of the original bounty's value. Or she may also ask if the team would be willing to offer a different bounty for the implementation of the tools. -Participants in the gno.land Bounty Program must meet the legal Terms and Conditions referenced [here](https://docs.google.com/document/d/1aXrZ6japdAykB5FLmHCCeBZTo-2tbZQHSQi79ITaTK0). +Participants in the gno.land Bounty Program must meet the legal Terms and Conditions referenced [here](https://docs.google.com/document/d/e/2PACX-1vSUF-JwIXGscrNsc5QBD7Pa6i83mXUGogAEIf1wkeb_w42UgL3Lj6jFKMlNTdwEMUnhsLkjRlhe25K4/pub). ### Bounty sizes @@ -80,7 +80,7 @@ _[3XL]_ \* | $ 32000 The gno.land grants program is to encourage and support the growth of the gno.land contributor community, and build out the usability of the platform and smart contract library. The program provides financial resources to contributors to explore the Gno tech stack, and build dApps, tooling, infrastructure, products, and smart contract libraries in gno.land. - +For more details on gno.land grants, suggested topics, and how to apply, visit our grants [repository](https://github.com/gnolang/grants). ## Join Game of Realms diff --git a/examples/gno.land/r/gnoland/valopers/gno.mod b/examples/gno.land/r/gnoland/valopers/v2/gno.mod similarity index 56% rename from examples/gno.land/r/gnoland/valopers/gno.mod rename to examples/gno.land/r/gnoland/valopers/v2/gno.mod index 2d24fb27952..099a8406db4 100644 --- a/examples/gno.land/r/gnoland/valopers/gno.mod +++ b/examples/gno.land/r/gnoland/valopers/v2/gno.mod @@ -1,11 +1,12 @@ -module gno.land/r/gnoland/valopers +module gno.land/r/gnoland/valopers/v2 require ( gno.land/p/demo/avl v0.0.0-latest + gno.land/p/demo/dao v0.0.0-latest gno.land/p/demo/testutils v0.0.0-latest gno.land/p/demo/uassert v0.0.0-latest gno.land/p/demo/ufmt v0.0.0-latest gno.land/p/sys/validators v0.0.0-latest - gno.land/r/gov/dao v0.0.0-latest - gno.land/r/sys/validators v0.0.0-latest + gno.land/r/gov/dao/bridge v0.0.0-latest + gno.land/r/sys/validators/v2 v0.0.0-latest ) diff --git a/examples/gno.land/r/gnoland/valopers/init.gno b/examples/gno.land/r/gnoland/valopers/v2/init.gno similarity index 100% rename from examples/gno.land/r/gnoland/valopers/init.gno rename to examples/gno.land/r/gnoland/valopers/v2/init.gno diff --git a/examples/gno.land/r/gnoland/valopers/valopers.gno b/examples/gno.land/r/gnoland/valopers/v2/valopers.gno similarity index 90% rename from examples/gno.land/r/gnoland/valopers/valopers.gno rename to examples/gno.land/r/gnoland/valopers/v2/valopers.gno index 74cec941e0d..d88ea4b872f 100644 --- a/examples/gno.land/r/gnoland/valopers/valopers.gno +++ b/examples/gno.land/r/gnoland/valopers/v2/valopers.gno @@ -6,10 +6,11 @@ import ( "std" "gno.land/p/demo/avl" + "gno.land/p/demo/dao" "gno.land/p/demo/ufmt" pVals "gno.land/p/sys/validators" - govdao "gno.land/r/gov/dao" - "gno.land/r/sys/validators" + "gno.land/r/gov/dao/bridge" + validators "gno.land/r/sys/validators/v2" ) const ( @@ -25,6 +26,7 @@ var valopers *avl.Tree // Address -> Valoper // Valoper represents a validator operator profile type Valoper struct { Name string // the display name of the valoper + Moniker string // the moniker of the valoper Description string // the description of the valoper Address std.Address // The bech32 gno address of the validator @@ -101,7 +103,7 @@ func Render(_ string) string { // Render renders a single valoper with their information func (v Valoper) Render() string { - output := ufmt.Sprintf("## %s\n", v.Name) + output := ufmt.Sprintf("## %s (%s)\n", v.Name, v.Moniker) output += ufmt.Sprintf("%s\n\n", v.Description) output += ufmt.Sprintf("- Address: %s\n", v.Address.String()) output += ufmt.Sprintf("- PubKey: %s\n", v.PubKey) @@ -168,14 +170,19 @@ func GovDAOProposal(address std.Address) { // Create the executor executor := validators.NewPropExecutor(changesFn) - // Craft the proposal comment - comment := ufmt.Sprintf( - "Proposal to add valoper %s (Address: %s; PubKey: %s) to the valset", + // Craft the proposal description + description := ufmt.Sprintf( + "Add valoper %s (Address: %s; PubKey: %s) to the valset", valoper.Name, valoper.Address.String(), valoper.PubKey, ) + prop := dao.ProposalRequest{ + Description: description, + Executor: executor, + } + // Create the govdao proposal - govdao.Propose(comment, executor) + bridge.GovDAO().Propose(prop) } diff --git a/examples/gno.land/r/gnoland/valopers/valopers_test.gno b/examples/gno.land/r/gnoland/valopers/v2/valopers_test.gno similarity index 97% rename from examples/gno.land/r/gnoland/valopers/valopers_test.gno rename to examples/gno.land/r/gnoland/valopers/v2/valopers_test.gno index 89544c46ee5..b5940738769 100644 --- a/examples/gno.land/r/gnoland/valopers/valopers_test.gno +++ b/examples/gno.land/r/gnoland/valopers/v2/valopers_test.gno @@ -38,6 +38,7 @@ func TestValopers_Register(t *testing.T) { v := Valoper{ Address: testutils.TestAddress("valoper"), Name: "new valoper", + Moniker: "val-1", PubKey: "pub key", } @@ -50,6 +51,7 @@ func TestValopers_Register(t *testing.T) { uassert.Equal(t, v.Address, valoper.Address) uassert.Equal(t, v.Name, valoper.Name) + uassert.Equal(t, v.Moniker, valoper.Moniker) uassert.Equal(t, v.PubKey, valoper.PubKey) }) }) diff --git a/examples/gno.land/r/gov/dao/bridge/bridge.gno b/examples/gno.land/r/gov/dao/bridge/bridge.gno new file mode 100644 index 00000000000..ba47978f33f --- /dev/null +++ b/examples/gno.land/r/gov/dao/bridge/bridge.gno @@ -0,0 +1,39 @@ +package bridge + +import ( + "std" + + "gno.land/p/demo/ownable" +) + +const initialOwner = std.Address("g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq") // @moul + +var b *Bridge + +// Bridge is the active GovDAO +// implementation bridge +type Bridge struct { + *ownable.Ownable + + dao DAO +} + +// init constructs the initial GovDAO implementation +func init() { + b = &Bridge{ + Ownable: ownable.NewWithAddress(initialOwner), + dao: &govdaoV2{}, + } +} + +// SetDAO sets the currently active GovDAO implementation +func SetDAO(dao DAO) { + b.AssertCallerIsOwner() + + b.dao = dao +} + +// GovDAO returns the current GovDAO implementation +func GovDAO() DAO { + return b.dao +} diff --git a/examples/gno.land/r/gov/dao/bridge/bridge_test.gno b/examples/gno.land/r/gov/dao/bridge/bridge_test.gno new file mode 100644 index 00000000000..38b5d4be257 --- /dev/null +++ b/examples/gno.land/r/gov/dao/bridge/bridge_test.gno @@ -0,0 +1,64 @@ +package bridge + +import ( + "testing" + + "std" + + "gno.land/p/demo/dao" + "gno.land/p/demo/ownable" + "gno.land/p/demo/testutils" + "gno.land/p/demo/uassert" + "gno.land/p/demo/urequire" +) + +func TestBridge_DAO(t *testing.T) { + var ( + proposalID = uint64(10) + mockDAO = &mockDAO{ + proposeFn: func(_ dao.ProposalRequest) uint64 { + return proposalID + }, + } + ) + + b.dao = mockDAO + + uassert.Equal(t, proposalID, GovDAO().Propose(dao.ProposalRequest{})) +} + +func TestBridge_SetDAO(t *testing.T) { + t.Run("invalid owner", func(t *testing.T) { + // Attempt to set a new DAO implementation + uassert.PanicsWithMessage(t, ownable.ErrUnauthorized.Error(), func() { + SetDAO(&mockDAO{}) + }) + }) + + t.Run("valid owner", func(t *testing.T) { + var ( + addr = testutils.TestAddress("owner") + + proposalID = uint64(10) + mockDAO = &mockDAO{ + proposeFn: func(_ dao.ProposalRequest) uint64 { + return proposalID + }, + } + ) + + std.TestSetOrigCaller(addr) + + b.Ownable = ownable.NewWithAddress(addr) + + urequire.NotPanics(t, func() { + SetDAO(mockDAO) + }) + + uassert.Equal( + t, + mockDAO.Propose(dao.ProposalRequest{}), + GovDAO().Propose(dao.ProposalRequest{}), + ) + }) +} diff --git a/examples/gno.land/r/gov/dao/bridge/doc.gno b/examples/gno.land/r/gov/dao/bridge/doc.gno new file mode 100644 index 00000000000..f812b3c0787 --- /dev/null +++ b/examples/gno.land/r/gov/dao/bridge/doc.gno @@ -0,0 +1,4 @@ +// Package bridge represents a GovDAO implementation wrapper, used by other Realms and Packages to +// always fetch the most active GovDAO implementation, instead of directly referencing it, and having to +// update it each time the GovDAO implementation changes +package bridge diff --git a/examples/gno.land/r/gov/dao/bridge/gno.mod b/examples/gno.land/r/gov/dao/bridge/gno.mod new file mode 100644 index 00000000000..3382557573a --- /dev/null +++ b/examples/gno.land/r/gov/dao/bridge/gno.mod @@ -0,0 +1,11 @@ +module gno.land/r/gov/dao/bridge + +require ( + gno.land/p/demo/dao v0.0.0-latest + gno.land/p/demo/membstore v0.0.0-latest + gno.land/p/demo/ownable v0.0.0-latest + gno.land/p/demo/testutils v0.0.0-latest + gno.land/p/demo/uassert v0.0.0-latest + gno.land/p/demo/urequire v0.0.0-latest + gno.land/r/gov/dao/v2 v0.0.0-latest +) diff --git a/examples/gno.land/r/gov/dao/bridge/mock_test.gno b/examples/gno.land/r/gov/dao/bridge/mock_test.gno new file mode 100644 index 00000000000..05ac430b4c4 --- /dev/null +++ b/examples/gno.land/r/gov/dao/bridge/mock_test.gno @@ -0,0 +1,68 @@ +package bridge + +import ( + "gno.land/p/demo/dao" + "gno.land/p/demo/membstore" +) + +type ( + proposeDelegate func(dao.ProposalRequest) uint64 + voteOnProposalDelegate func(uint64, dao.VoteOption) + executeProposalDelegate func(uint64) + getPropStoreDelegate func() dao.PropStore + getMembStoreDelegate func() membstore.MemberStore + newGovDAOExecutorDelegate func(func() error) dao.Executor +) + +type mockDAO struct { + proposeFn proposeDelegate + voteOnProposalFn voteOnProposalDelegate + executeProposalFn executeProposalDelegate + getPropStoreFn getPropStoreDelegate + getMembStoreFn getMembStoreDelegate + newGovDAOExecutorFn newGovDAOExecutorDelegate +} + +func (m *mockDAO) Propose(request dao.ProposalRequest) uint64 { + if m.proposeFn != nil { + return m.proposeFn(request) + } + + return 0 +} + +func (m *mockDAO) VoteOnProposal(id uint64, option dao.VoteOption) { + if m.voteOnProposalFn != nil { + m.voteOnProposalFn(id, option) + } +} + +func (m *mockDAO) ExecuteProposal(id uint64) { + if m.executeProposalFn != nil { + m.executeProposalFn(id) + } +} + +func (m *mockDAO) GetPropStore() dao.PropStore { + if m.getPropStoreFn != nil { + return m.getPropStoreFn() + } + + return nil +} + +func (m *mockDAO) GetMembStore() membstore.MemberStore { + if m.getMembStoreFn != nil { + return m.getMembStoreFn() + } + + return nil +} + +func (m *mockDAO) NewGovDAOExecutor(cb func() error) dao.Executor { + if m.newGovDAOExecutorFn != nil { + return m.newGovDAOExecutorFn(cb) + } + + return nil +} diff --git a/examples/gno.land/r/gov/dao/bridge/types.gno b/examples/gno.land/r/gov/dao/bridge/types.gno new file mode 100644 index 00000000000..27ea8fb62d4 --- /dev/null +++ b/examples/gno.land/r/gov/dao/bridge/types.gno @@ -0,0 +1,17 @@ +package bridge + +import ( + "gno.land/p/demo/dao" + "gno.land/p/demo/membstore" +) + +// DAO abstracts the commonly used DAO interface +type DAO interface { + Propose(dao.ProposalRequest) uint64 + VoteOnProposal(uint64, dao.VoteOption) + ExecuteProposal(uint64) + GetPropStore() dao.PropStore + GetMembStore() membstore.MemberStore + + NewGovDAOExecutor(func() error) dao.Executor +} diff --git a/examples/gno.land/r/gov/dao/bridge/v2.gno b/examples/gno.land/r/gov/dao/bridge/v2.gno new file mode 100644 index 00000000000..216419cf31d --- /dev/null +++ b/examples/gno.land/r/gov/dao/bridge/v2.gno @@ -0,0 +1,42 @@ +package bridge + +import ( + "gno.land/p/demo/dao" + "gno.land/p/demo/membstore" + govdao "gno.land/r/gov/dao/v2" +) + +// govdaoV2 is a wrapper for interacting with the /r/gov/dao/v2 Realm +type govdaoV2 struct{} + +func (g *govdaoV2) Propose(request dao.ProposalRequest) uint64 { + return govdao.Propose(request) +} + +func (g *govdaoV2) VoteOnProposal(id uint64, option dao.VoteOption) { + govdao.VoteOnProposal(id, option) +} + +func (g *govdaoV2) ExecuteProposal(id uint64) { + govdao.ExecuteProposal(id) +} + +func (g *govdaoV2) GetPropStore() dao.PropStore { + return govdao.GetPropStore() +} + +func (g *govdaoV2) GetMembStore() membstore.MemberStore { + return govdao.GetMembStore() +} + +func (g *govdaoV2) NewGovDAOExecutor(cb func() error) dao.Executor { + return govdao.NewGovDAOExecutor(cb) +} + +func (g *govdaoV2) NewMemberPropExecutor(cb func() []membstore.Member) dao.Executor { + return govdao.NewMemberPropExecutor(cb) +} + +func (g *govdaoV2) NewMembStoreImplExecutor(cb func() membstore.MemberStore) dao.Executor { + return govdao.NewMembStoreImplExecutor(cb) +} diff --git a/examples/gno.land/r/gov/dao/dao.gno b/examples/gno.land/r/gov/dao/dao.gno deleted file mode 100644 index 632935dafed..00000000000 --- a/examples/gno.land/r/gov/dao/dao.gno +++ /dev/null @@ -1,207 +0,0 @@ -package govdao - -import ( - "std" - "strconv" - - "gno.land/p/demo/ufmt" - pproposal "gno.land/p/gov/proposal" -) - -var ( - proposals = make([]*proposal, 0) - members = make([]std.Address, 0) // XXX: these should be pointers to avoid data duplication. Not possible due to VM bugs -) - -const ( - msgMissingExecutor = "missing proposal executor" - msgPropExecuted = "prop already executed" - msgPropExpired = "prop is expired" - msgPropInactive = "prop is not active anymore" - msgPropActive = "prop is still active" - msgPropNotAccepted = "prop is not accepted" - - msgCallerNotAMember = "caller is not member of govdao" - msgProposalNotFound = "proposal not found" -) - -type proposal struct { - author std.Address - comment string - executor pproposal.Executor - voter Voter - executed bool - voters []std.Address // XXX: these should be pointers to avoid data duplication. Not possible due to VM bugs. -} - -func (p proposal) Status() Status { - if p.executor.IsExpired() { - return Expired - } - - if p.executor.IsDone() { - return Succeeded - } - - if !p.voter.IsFinished(members) { - return Active - } - - if p.voter.IsAccepted(members) { - return Accepted - } - - return NotAccepted -} - -// Propose is designed to be called by another contract or with -// `maketx run`, not by a `maketx call`. -func Propose(comment string, executor pproposal.Executor) int { - // XXX: require payment? - if executor == nil { - panic(msgMissingExecutor) - } - caller := std.GetOrigCaller() // XXX: CHANGE THIS WHEN MSGRUN PERSIST CODE ESCAPING THE main() SCOPE! IT IS UNSAFE! - AssertIsMember(caller) - - prop := &proposal{ - comment: comment, - executor: executor, - author: caller, - voter: NewPercentageVoter(66), // at least 2/3 must say yes - } - - proposals = append(proposals, prop) - - return len(proposals) - 1 -} - -func VoteOnProposal(idx int, option string) { - assertProposalExists(idx) - caller := std.GetOrigCaller() // XXX: CHANGE THIS WHEN MSGRUN PERSIST CODE ESCAPING THE main() SCOPE! IT IS UNSAFE! - AssertIsMember(caller) - - prop := getProposal(idx) - - if prop.executed { - panic(msgPropExecuted) - } - - if prop.executor.IsExpired() { - panic(msgPropExpired) - } - - if prop.voter.IsFinished(members) { - panic(msgPropInactive) - } - - prop.voter.Vote(members, caller, option) -} - -func ExecuteProposal(idx int) { - assertProposalExists(idx) - prop := getProposal(idx) - - if prop.executed { - panic(msgPropExecuted) - } - - if prop.executor.IsExpired() { - panic(msgPropExpired) - } - - if !prop.voter.IsFinished(members) { - panic(msgPropActive) - } - - if !prop.voter.IsAccepted(members) { - panic(msgPropNotAccepted) - } - - prop.executor.Execute() - prop.voters = members - prop.executed = true -} - -func IsMember(addr std.Address) bool { - if len(members) == 0 { // special case for initial execution - return true - } - - for _, v := range members { - if v == addr { - return true - } - } - - return false -} - -func AssertIsMember(addr std.Address) { - if !IsMember(addr) { - panic(msgCallerNotAMember) - } -} - -func Render(path string) string { - if path == "" { - if len(proposals) == 0 { - return "No proposals found :(" // corner case - } - - output := "" - for idx, prop := range proposals { - output += ufmt.Sprintf("- [%d](/r/gov/dao:%d) - %s (**%s**)(by %s)\n", idx, idx, prop.comment, string(prop.Status()), prop.author) - } - - return output - } - - // else display the proposal - idx, err := strconv.Atoi(path) - if err != nil { - return "404" - } - - if !proposalExists(idx) { - return "404" - } - prop := getProposal(idx) - - vs := members - if prop.executed { - vs = prop.voters - } - - output := "" - output += ufmt.Sprintf("# Prop #%d", idx) - output += "\n\n" - output += prop.comment - output += "\n\n" - output += ufmt.Sprintf("Status: %s", string(prop.Status())) - output += "\n\n" - output += ufmt.Sprintf("Voting status: %s", prop.voter.Status(vs)) - output += "\n\n" - output += ufmt.Sprintf("Author: %s", string(prop.author)) - output += "\n\n" - - return output -} - -func getProposal(idx int) *proposal { - if idx > len(proposals)-1 { - panic(msgProposalNotFound) - } - - return proposals[idx] -} - -func proposalExists(idx int) bool { - return idx >= 0 && idx <= len(proposals) -} - -func assertProposalExists(idx int) { - if !proposalExists(idx) { - panic("invalid proposal id") - } -} diff --git a/examples/gno.land/r/gov/dao/dao_test.gno b/examples/gno.land/r/gov/dao/dao_test.gno deleted file mode 100644 index 96eaba7f5e9..00000000000 --- a/examples/gno.land/r/gov/dao/dao_test.gno +++ /dev/null @@ -1,192 +0,0 @@ -package govdao - -import ( - "std" - "testing" - - "gno.land/p/demo/testutils" - "gno.land/p/demo/urequire" - pproposal "gno.land/p/gov/proposal" -) - -func TestPackage(t *testing.T) { - u1 := testutils.TestAddress("u1") - u2 := testutils.TestAddress("u2") - u3 := testutils.TestAddress("u3") - - members = append(members, u1) - members = append(members, u2) - members = append(members, u3) - - nu1 := testutils.TestAddress("random1") - - out := Render("") - - expected := "No proposals found :(" - urequire.Equal(t, expected, out) - - var called bool - ex := pproposal.NewExecutor(func() error { - called = true - return nil - }) - - std.TestSetOrigCaller(u1) - pid := Propose("dummy proposal", ex) - - // try to vote not being a member - std.TestSetOrigCaller(nu1) - - urequire.PanicsWithMessage(t, msgCallerNotAMember, func() { - VoteOnProposal(pid, "YES") - }) - - // try to vote several times - std.TestSetOrigCaller(u1) - urequire.NotPanics(t, func() { - VoteOnProposal(pid, "YES") - }) - urequire.PanicsWithMessage(t, msgAlreadyVoted, func() { - VoteOnProposal(pid, "YES") - }) - - out = Render("0") - expected = `# Prop #0 - -dummy proposal - -Status: active - -Voting status: YES: 1, NO: 0, percent: 33, members: 3 - -Author: g1w5c47h6lta047h6lta047h6lta047h6ly5kscr - -` - - urequire.Equal(t, expected, out) - - std.TestSetOrigCaller(u2) - urequire.PanicsWithMessage(t, msgWrongVotingValue, func() { - VoteOnProposal(pid, "INCORRECT") - }) - urequire.NotPanics(t, func() { - VoteOnProposal(pid, "NO") - }) - - out = Render("0") - expected = `# Prop #0 - -dummy proposal - -Status: active - -Voting status: YES: 1, NO: 1, percent: 33, members: 3 - -Author: g1w5c47h6lta047h6lta047h6lta047h6ly5kscr - -` - - urequire.Equal(t, expected, out) - - std.TestSetOrigCaller(u3) - urequire.NotPanics(t, func() { - VoteOnProposal(pid, "YES") - }) - - out = Render("0") - expected = `# Prop #0 - -dummy proposal - -Status: accepted - -Voting status: YES: 2, NO: 1, percent: 66, members: 3 - -Author: g1w5c47h6lta047h6lta047h6lta047h6ly5kscr - -` - - urequire.Equal(t, expected, out) - - // Add a new member, so non-executed proposals will change the voting status - u4 := testutils.TestAddress("u4") - members = append(members, u4) - - out = Render("0") - expected = `# Prop #0 - -dummy proposal - -Status: active - -Voting status: YES: 2, NO: 1, percent: 50, members: 4 - -Author: g1w5c47h6lta047h6lta047h6lta047h6ly5kscr - -` - - urequire.Equal(t, expected, out) - - std.TestSetOrigCaller(u4) - urequire.NotPanics(t, func() { - VoteOnProposal(pid, "YES") - }) - - out = Render("0") - expected = `# Prop #0 - -dummy proposal - -Status: accepted - -Voting status: YES: 3, NO: 1, percent: 75, members: 4 - -Author: g1w5c47h6lta047h6lta047h6lta047h6ly5kscr - -` - - urequire.Equal(t, expected, out) - - ExecuteProposal(pid) - urequire.True(t, called) - - out = Render("0") - expected = `# Prop #0 - -dummy proposal - -Status: succeeded - -Voting status: YES: 3, NO: 1, percent: 75, members: 4 - -Author: g1w5c47h6lta047h6lta047h6lta047h6ly5kscr - -` - - urequire.Equal(t, expected, out) - - // Add a new member and try to vote an already executed proposal - u5 := testutils.TestAddress("u5") - members = append(members, u5) - std.TestSetOrigCaller(u5) - urequire.PanicsWithMessage(t, msgPropExecuted, func() { - ExecuteProposal(pid) - }) - - // even if we added a new member the executed proposal is showing correctly the members that voted on it - out = Render("0") - expected = `# Prop #0 - -dummy proposal - -Status: succeeded - -Voting status: YES: 3, NO: 1, percent: 75, members: 4 - -Author: g1w5c47h6lta047h6lta047h6lta047h6ly5kscr - -` - - urequire.Equal(t, expected, out) - -} diff --git a/examples/gno.land/r/gov/dao/memberset.gno b/examples/gno.land/r/gov/dao/memberset.gno deleted file mode 100644 index 3abd52ae99d..00000000000 --- a/examples/gno.land/r/gov/dao/memberset.gno +++ /dev/null @@ -1,40 +0,0 @@ -package govdao - -import ( - "std" - - pproposal "gno.land/p/gov/proposal" -) - -const daoPkgPath = "gno.land/r/gov/dao" - -const ( - errNoChangesProposed = "no set changes proposed" - errNotGovDAO = "caller not govdao executor" -) - -func NewPropExecutor(changesFn func() []std.Address) pproposal.Executor { - if changesFn == nil { - panic(errNoChangesProposed) - } - - callback := func() error { - // Make sure the GovDAO executor runs the valset changes - assertGovDAOCaller() - - for _, addr := range changesFn() { - members = append(members, addr) - } - - return nil - } - - return pproposal.NewExecutor(callback) -} - -// assertGovDAOCaller verifies the caller is the GovDAO executor -func assertGovDAOCaller() { - if std.CurrentRealm().PkgPath() != daoPkgPath { - panic(errNotGovDAO) - } -} diff --git a/examples/gno.land/r/gov/dao/prop2_filetest.gno b/examples/gno.land/r/gov/dao/prop2_filetest.gno deleted file mode 100644 index 047709cc45f..00000000000 --- a/examples/gno.land/r/gov/dao/prop2_filetest.gno +++ /dev/null @@ -1,120 +0,0 @@ -package main - -import ( - "std" - "time" - - "gno.land/p/demo/context" - "gno.land/p/gov/proposal" - gnoblog "gno.land/r/gnoland/blog" - govdao "gno.land/r/gov/dao" -) - -func init() { - membersFn := func() []std.Address { - return []std.Address{ - std.Address("g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm"), - } - } - - mExec := govdao.NewPropExecutor(membersFn) - - comment := "adding someone to vote" - - id := govdao.Propose(comment, mExec) - - govdao.ExecuteProposal(id) - - executor := proposal.NewCtxExecutor(func(ctx context.Context) error { - gnoblog.DaoAddPost( - ctx, - "hello-from-govdao", // slug - "Hello from GovDAO!", // title - "This post was published by a GovDAO proposal.", // body - time.Now().Format(time.RFC3339), // publidation date - "moul", // authors - "govdao,example", // tags - ) - return nil - }) - - // Create a proposal. - // XXX: payment - comment = "post a new blogpost about govdao" - govdao.Propose(comment, executor) -} - -func main() { - println("--") - println(govdao.Render("")) - println("--") - println(govdao.Render("1")) - println("--") - govdao.VoteOnProposal(1, "YES") - println("--") - println(govdao.Render("1")) - println("--") - println(gnoblog.Render("")) - println("--") - govdao.ExecuteProposal(1) - println("--") - println(govdao.Render("1")) - println("--") - println(gnoblog.Render("")) -} - -// Output: -// -- -// - [0](/r/gov/dao:0) - adding someone to vote (**succeeded**)(by g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm) -// - [1](/r/gov/dao:1) - post a new blogpost about govdao (**active**)(by g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm) -// -// -- -// # Prop #1 -// -// post a new blogpost about govdao -// -// Status: active -// -// Voting status: YES: 0, NO: 0, percent: 0, members: 1 -// -// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm -// -// -// -- -// -- -// # Prop #1 -// -// post a new blogpost about govdao -// -// Status: accepted -// -// Voting status: YES: 1, NO: 0, percent: 100, members: 1 -// -// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm -// -// -// -- -// # Gnoland's Blog -// -// No posts. -// -- -// -- -// # Prop #1 -// -// post a new blogpost about govdao -// -// Status: succeeded -// -// Voting status: YES: 1, NO: 0, percent: 100, members: 1 -// -// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm -// -// -// -- -// # Gnoland's Blog -// -//
-// -// ### [Hello from GovDAO!](/r/gnoland/blog:p/hello-from-govdao) -// 13 Feb 2009 -//
diff --git a/examples/gno.land/r/gov/dao/types.gno b/examples/gno.land/r/gov/dao/types.gno deleted file mode 100644 index 123fc489075..00000000000 --- a/examples/gno.land/r/gov/dao/types.gno +++ /dev/null @@ -1,32 +0,0 @@ -package govdao - -import ( - "std" -) - -// Status enum. -type Status string - -var ( - Accepted Status = "accepted" - Active Status = "active" - NotAccepted Status = "not accepted" - Expired Status = "expired" - Succeeded Status = "succeeded" -) - -// Voter defines the needed methods for a voting system -type Voter interface { - - // IsAccepted indicates if the voting process had been accepted - IsAccepted(voters []std.Address) bool - - // IsFinished indicates if the voting process is finished - IsFinished(voters []std.Address) bool - - // Vote adds a new vote to the voting system - Vote(voters []std.Address, caller std.Address, flag string) - - // Status returns a human friendly string describing how the voting process is going - Status(voters []std.Address) string -} diff --git a/examples/gno.land/r/gov/dao/v2/dao.gno b/examples/gno.land/r/gov/dao/v2/dao.gno new file mode 100644 index 00000000000..c37eda80bff --- /dev/null +++ b/examples/gno.land/r/gov/dao/v2/dao.gno @@ -0,0 +1,121 @@ +package govdao + +import ( + "std" + "strconv" + + "gno.land/p/demo/dao" + "gno.land/p/demo/membstore" + "gno.land/p/demo/simpledao" + "gno.land/p/demo/ufmt" +) + +var ( + d *simpledao.SimpleDAO // the current active DAO implementation + members membstore.MemberStore // the member store +) + +func init() { + var ( + // Example initial member set (just test addresses) + set = []membstore.Member{ + { + Address: std.Address("g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm"), + VotingPower: 10, + }, + } + ) + + // Set the member store + members = membstore.NewMembStore(membstore.WithInitialMembers(set)) + + // Set the DAO implementation + d = simpledao.New(members) +} + +// Propose is designed to be called by another contract or with +// `maketx run`, not by a `maketx call`. +func Propose(request dao.ProposalRequest) uint64 { + idx, err := d.Propose(request) + if err != nil { + panic(err) + } + + return idx +} + +// VoteOnProposal casts a vote for the given proposal +func VoteOnProposal(id uint64, option dao.VoteOption) { + if err := d.VoteOnProposal(id, option); err != nil { + panic(err) + } +} + +// ExecuteProposal executes the proposal +func ExecuteProposal(id uint64) { + if err := d.ExecuteProposal(id); err != nil { + panic(err) + } +} + +// GetPropStore returns the active proposal store +func GetPropStore() dao.PropStore { + return d +} + +// GetMembStore returns the active member store +func GetMembStore() membstore.MemberStore { + return members +} + +func Render(path string) string { + if path == "" { + numProposals := d.Size() + + if numProposals == 0 { + return "No proposals found :(" // corner case + } + + output := "" + + offset := uint64(0) + if numProposals >= 10 { + offset = uint64(numProposals) - 10 + } + + // Fetch the last 10 proposals + for idx, prop := range d.Proposals(offset, uint64(10)) { + output += ufmt.Sprintf( + "- [Proposal #%d](%s:%d) - (**%s**)(by %s)\n", + idx, + "/r/gov/dao/v2", + idx, + prop.Status().String(), + prop.Author().String(), + ) + } + + return output + } + + // Display the detailed proposal + idx, err := strconv.Atoi(path) + if err != nil { + return "404: Invalid proposal ID" + } + + // Fetch the proposal + prop, err := d.ProposalByID(uint64(idx)) + if err != nil { + return ufmt.Sprintf("unable to fetch proposal, %s", err.Error()) + } + + // Render the proposal + output := "" + output += ufmt.Sprintf("# Prop #%d", idx) + output += "\n\n" + output += prop.Render() + output += "\n\n" + + return output +} diff --git a/examples/gno.land/r/gov/dao/v2/gno.mod b/examples/gno.land/r/gov/dao/v2/gno.mod new file mode 100644 index 00000000000..bc379bf18df --- /dev/null +++ b/examples/gno.land/r/gov/dao/v2/gno.mod @@ -0,0 +1,10 @@ +module gno.land/r/gov/dao/v2 + +require ( + gno.land/p/demo/combinederr v0.0.0-latest + gno.land/p/demo/dao v0.0.0-latest + gno.land/p/demo/membstore v0.0.0-latest + gno.land/p/demo/simpledao v0.0.0-latest + gno.land/p/demo/ufmt v0.0.0-latest + gno.land/p/gov/executor v0.0.0-latest +) diff --git a/examples/gno.land/r/gov/dao/v2/poc.gno b/examples/gno.land/r/gov/dao/v2/poc.gno new file mode 100644 index 00000000000..30d8a403f6e --- /dev/null +++ b/examples/gno.land/r/gov/dao/v2/poc.gno @@ -0,0 +1,92 @@ +package govdao + +import ( + "errors" + "std" + + "gno.land/p/demo/combinederr" + "gno.land/p/demo/dao" + "gno.land/p/demo/membstore" + "gno.land/p/gov/executor" +) + +var errNoChangesProposed = errors.New("no set changes proposed") + +// NewGovDAOExecutor creates the govdao wrapped callback executor +func NewGovDAOExecutor(cb func() error) dao.Executor { + if cb == nil { + panic(errNoChangesProposed) + } + + return executor.NewCallbackExecutor( + cb, + std.CurrentRealm().PkgPath(), + ) +} + +// NewMemberPropExecutor returns the GOVDAO member change executor +func NewMemberPropExecutor(changesFn func() []membstore.Member) dao.Executor { + if changesFn == nil { + panic(errNoChangesProposed) + } + + callback := func() error { + errs := &combinederr.CombinedError{} + cbMembers := changesFn() + + for _, member := range cbMembers { + switch { + case !members.IsMember(member.Address): + // Addition request + err := members.AddMember(member) + + errs.Add(err) + case member.VotingPower == 0: + // Remove request + err := members.UpdateMember(member.Address, membstore.Member{ + Address: member.Address, + VotingPower: 0, // 0 indicated removal + }) + + errs.Add(err) + default: + // Update request + err := members.UpdateMember(member.Address, member) + + errs.Add(err) + } + } + + // Check if there were any execution errors + if errs.Size() == 0 { + return nil + } + + return errs + } + + return NewGovDAOExecutor(callback) +} + +func NewMembStoreImplExecutor(changeFn func() membstore.MemberStore) dao.Executor { + if changeFn == nil { + panic(errNoChangesProposed) + } + + callback := func() error { + setMembStoreImpl(changeFn()) + + return nil + } + + return NewGovDAOExecutor(callback) +} + +// setMembStoreImpl sets a new dao.MembStore implementation +func setMembStoreImpl(impl membstore.MemberStore) { + if impl == nil { + panic("invalid member store") + } + + members = impl +} diff --git a/examples/gno.land/r/gov/dao/prop1_filetest.gno b/examples/gno.land/r/gov/dao/v2/prop1_filetest.gno similarity index 63% rename from examples/gno.land/r/gov/dao/prop1_filetest.gno rename to examples/gno.land/r/gov/dao/v2/prop1_filetest.gno index 49a200fd561..69e55ef1ab6 100644 --- a/examples/gno.land/r/gov/dao/prop1_filetest.gno +++ b/examples/gno.land/r/gov/dao/v2/prop1_filetest.gno @@ -10,26 +10,13 @@ package main import ( "std" + "gno.land/p/demo/dao" pVals "gno.land/p/sys/validators" - govdao "gno.land/r/gov/dao" - "gno.land/r/sys/validators" + govdao "gno.land/r/gov/dao/v2" + validators "gno.land/r/sys/validators/v2" ) -const daoPkgPath = "gno.land/r/gov/dao" - func init() { - membersFn := func() []std.Address { - return []std.Address{ - std.Address("g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm"), - } - } - - mExec := govdao.NewPropExecutor(membersFn) - - comment := "adding someone to vote" - id := govdao.Propose(comment, mExec) - govdao.ExecuteProposal(id) - changesFn := func() []pVals.Validator { return []pVals.Validator{ { @@ -54,74 +41,84 @@ func init() { // complete governance proposal process. executor := validators.NewPropExecutor(changesFn) - // Create a proposal. - // XXX: payment - comment = "manual valset changes proposal example" - govdao.Propose(comment, executor) + // Create a proposal + description := "manual valset changes proposal example" + + prop := dao.ProposalRequest{ + Description: description, + Executor: executor, + } + + govdao.Propose(prop) } func main() { println("--") println(govdao.Render("")) println("--") - println(govdao.Render("1")) + println(govdao.Render("0")) println("--") - govdao.VoteOnProposal(1, "YES") + govdao.VoteOnProposal(0, dao.YesVote) println("--") - println(govdao.Render("1")) + println(govdao.Render("0")) println("--") println(validators.Render("")) println("--") - govdao.ExecuteProposal(1) + govdao.ExecuteProposal(0) println("--") - println(govdao.Render("1")) + println(govdao.Render("0")) println("--") println(validators.Render("")) } // Output: // -- -// - [0](/r/gov/dao:0) - adding someone to vote (**succeeded**)(by g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm) -// - [1](/r/gov/dao:1) - manual valset changes proposal example (**active**)(by g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm) +// - [Proposal #0](/r/gov/dao/v2:0) - (**active**)(by g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm) // // -- -// # Prop #1 +// # Prop #0 +// +// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm // // manual valset changes proposal example // // Status: active // -// Voting status: YES: 0, NO: 0, percent: 0, members: 1 +// Voting stats: YAY 0 (0%), NAY 0 (0%), ABSTAIN 0 (0%), HAVEN'T VOTED 10 (100%) // -// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm +// Threshold met: false // // // -- // -- -// # Prop #1 +// # Prop #0 +// +// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm // // manual valset changes proposal example // // Status: accepted // -// Voting status: YES: 1, NO: 0, percent: 100, members: 1 +// Voting stats: YAY 10 (100%), NAY 0 (0%), ABSTAIN 0 (0%), HAVEN'T VOTED 0 (0%) // -// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm +// Threshold met: true // // // -- // No valset changes to apply. // -- // -- -// # Prop #1 +// # Prop #0 +// +// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm // // manual valset changes proposal example // -// Status: succeeded +// Status: execution successful // -// Voting status: YES: 1, NO: 0, percent: 100, members: 1 +// Voting stats: YAY 10 (100%), NAY 0 (0%), ABSTAIN 0 (0%), HAVEN'T VOTED 0 (0%) // -// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm +// Threshold met: true // // // -- diff --git a/examples/gno.land/r/gov/dao/v2/prop2_filetest.gno b/examples/gno.land/r/gov/dao/v2/prop2_filetest.gno new file mode 100644 index 00000000000..32ddc11b67c --- /dev/null +++ b/examples/gno.land/r/gov/dao/v2/prop2_filetest.gno @@ -0,0 +1,110 @@ +package main + +import ( + "time" + + "gno.land/p/demo/dao" + gnoblog "gno.land/r/gnoland/blog" + govdao "gno.land/r/gov/dao/v2" +) + +func init() { + ex := gnoblog.NewPostExecutor( + "hello-from-govdao", // slug + "Hello from GovDAO!", // title + "This post was published by a GovDAO proposal.", // body + time.Now().Format(time.RFC3339), // publication date + "moul", // authors + "govdao,example", // tags + ) + + // Create a proposal + description := "post a new blogpost about govdao" + + prop := dao.ProposalRequest{ + Description: description, + Executor: ex, + } + + govdao.Propose(prop) +} + +func main() { + println("--") + println(govdao.Render("")) + println("--") + println(govdao.Render("0")) + println("--") + govdao.VoteOnProposal(0, "YES") + println("--") + println(govdao.Render("0")) + println("--") + println(gnoblog.Render("")) + println("--") + govdao.ExecuteProposal(0) + println("--") + println(govdao.Render("0")) + println("--") + println(gnoblog.Render("")) +} + +// Output: +// -- +// - [Proposal #0](/r/gov/dao/v2:0) - (**active**)(by g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm) +// +// -- +// # Prop #0 +// +// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm +// +// post a new blogpost about govdao +// +// Status: active +// +// Voting stats: YAY 0 (0%), NAY 0 (0%), ABSTAIN 0 (0%), HAVEN'T VOTED 10 (100%) +// +// Threshold met: false +// +// +// -- +// -- +// # Prop #0 +// +// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm +// +// post a new blogpost about govdao +// +// Status: accepted +// +// Voting stats: YAY 10 (100%), NAY 0 (0%), ABSTAIN 0 (0%), HAVEN'T VOTED 0 (0%) +// +// Threshold met: true +// +// +// -- +// # Gnoland's Blog +// +// No posts. +// -- +// -- +// # Prop #0 +// +// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm +// +// post a new blogpost about govdao +// +// Status: execution successful +// +// Voting stats: YAY 10 (100%), NAY 0 (0%), ABSTAIN 0 (0%), HAVEN'T VOTED 0 (0%) +// +// Threshold met: true +// +// +// -- +// # Gnoland's Blog +// +//
+// +// ### [Hello from GovDAO!](/r/gnoland/blog:p/hello-from-govdao) +// 13 Feb 2009 +//
diff --git a/examples/gno.land/r/gov/dao/v2/prop3_filetest.gno b/examples/gno.land/r/gov/dao/v2/prop3_filetest.gno new file mode 100644 index 00000000000..5aa9947c74b --- /dev/null +++ b/examples/gno.land/r/gov/dao/v2/prop3_filetest.gno @@ -0,0 +1,120 @@ +package main + +import ( + "std" + + "gno.land/p/demo/dao" + "gno.land/p/demo/membstore" + govdao "gno.land/r/gov/dao/v2" +) + +func init() { + memberFn := func() []membstore.Member { + return []membstore.Member{ + { + Address: std.Address("g123"), + VotingPower: 10, + }, + { + Address: std.Address("g456"), + VotingPower: 10, + }, + { + Address: std.Address("g789"), + VotingPower: 10, + }, + } + } + + // Create a proposal + description := "add new members to the govdao" + + prop := dao.ProposalRequest{ + Description: description, + Executor: govdao.NewMemberPropExecutor(memberFn), + } + + govdao.Propose(prop) +} + +func main() { + println("--") + println(govdao.GetMembStore().Size()) + println("--") + println(govdao.Render("")) + println("--") + println(govdao.Render("0")) + println("--") + govdao.VoteOnProposal(0, "YES") + println("--") + println(govdao.Render("0")) + println("--") + println(govdao.Render("")) + println("--") + govdao.ExecuteProposal(0) + println("--") + println(govdao.Render("0")) + println("--") + println(govdao.Render("")) + println("--") + println(govdao.GetMembStore().Size()) +} + +// Output: +// -- +// 1 +// -- +// - [Proposal #0](/r/gov/dao/v2:0) - (**active**)(by g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm) +// +// -- +// # Prop #0 +// +// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm +// +// add new members to the govdao +// +// Status: active +// +// Voting stats: YAY 0 (0%), NAY 0 (0%), ABSTAIN 0 (0%), HAVEN'T VOTED 10 (100%) +// +// Threshold met: false +// +// +// -- +// -- +// # Prop #0 +// +// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm +// +// add new members to the govdao +// +// Status: accepted +// +// Voting stats: YAY 10 (100%), NAY 0 (0%), ABSTAIN 0 (0%), HAVEN'T VOTED 0 (0%) +// +// Threshold met: true +// +// +// -- +// - [Proposal #0](/r/gov/dao/v2:0) - (**accepted**)(by g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm) +// +// -- +// -- +// # Prop #0 +// +// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm +// +// add new members to the govdao +// +// Status: execution successful +// +// Voting stats: YAY 10 (25%), NAY 0 (0%), ABSTAIN 0 (0%), HAVEN'T VOTED 30 (75%) +// +// Threshold met: false +// +// +// -- +// - [Proposal #0](/r/gov/dao/v2:0) - (**execution successful**)(by g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm) +// +// -- +// 4 diff --git a/examples/gno.land/r/gov/dao/voter.gno b/examples/gno.land/r/gov/dao/voter.gno deleted file mode 100644 index 99223210791..00000000000 --- a/examples/gno.land/r/gov/dao/voter.gno +++ /dev/null @@ -1,91 +0,0 @@ -package govdao - -import ( - "std" - - "gno.land/p/demo/ufmt" -) - -const ( - yay = "YES" - nay = "NO" - - msgNoMoreVotesAllowed = "no more votes allowed" - msgAlreadyVoted = "caller already voted" - msgWrongVotingValue = "voting values must be YES or NO" -) - -func NewPercentageVoter(percent int) *PercentageVoter { - if percent < 0 || percent > 100 { - panic("percent value must be between 0 and 100") - } - - return &PercentageVoter{ - percentage: percent, - } -} - -// PercentageVoter is a system based on the amount of received votes. -// When the specified treshold is reached, the voting process finishes. -type PercentageVoter struct { - percentage int - - voters []std.Address - yes int - no int -} - -func (pv *PercentageVoter) IsAccepted(voters []std.Address) bool { - if len(voters) == 0 { - return true // special case - } - - return pv.percent(voters) >= pv.percentage -} - -func (pv *PercentageVoter) IsFinished(voters []std.Address) bool { - return pv.yes+pv.no >= len(voters) -} - -func (pv *PercentageVoter) Status(voters []std.Address) string { - return ufmt.Sprintf("YES: %d, NO: %d, percent: %d, members: %d", pv.yes, pv.no, pv.percent(voters), len(voters)) -} - -func (pv *PercentageVoter) Vote(voters []std.Address, caller std.Address, flag string) { - if pv.IsFinished(voters) { - panic(msgNoMoreVotesAllowed) - } - - if pv.alreadyVoted(caller) { - panic(msgAlreadyVoted) - } - - switch flag { - case yay: - pv.yes++ - pv.voters = append(pv.voters, caller) - case nay: - pv.no++ - pv.voters = append(pv.voters, caller) - default: - panic(msgWrongVotingValue) - } -} - -func (pv *PercentageVoter) percent(voters []std.Address) int { - if len(voters) == 0 { - return 0 - } - - return int((float32(pv.yes) / float32(len(voters))) * 100) -} - -func (pv *PercentageVoter) alreadyVoted(addr std.Address) bool { - for _, v := range pv.voters { - if v == addr { - return true - } - } - - return false -} diff --git a/examples/gno.land/r/leon/config/config.gno b/examples/gno.land/r/leon/config/config.gno index cbc1e537e3f..bc800ec8263 100644 --- a/examples/gno.land/r/leon/config/config.gno +++ b/examples/gno.land/r/leon/config/config.gno @@ -8,6 +8,9 @@ import ( var ( main std.Address // leon's main address backup std.Address // backup address + + ErrInvalidAddr = errors.New("leon's config: invalid address") + ErrUnauthorized = errors.New("leon's config: unauthorized") ) func init() { @@ -24,7 +27,7 @@ func Backup() std.Address { func SetAddress(a std.Address) error { if !a.IsValid() { - return errors.New("config: invalid address") + return ErrInvalidAddr } if err := checkAuthorized(); err != nil { @@ -37,7 +40,7 @@ func SetAddress(a std.Address) error { func SetBackup(a std.Address) error { if !a.IsValid() { - return errors.New("config: invalid address") + return ErrInvalidAddr } if err := checkAuthorized(); err != nil { @@ -50,16 +53,11 @@ func SetBackup(a std.Address) error { func checkAuthorized() error { caller := std.PrevRealm().Addr() - if caller != main || caller != backup { - return errors.New("config: unauthorized") + isAuthorized := caller == main || caller == backup + + if !isAuthorized { + return ErrUnauthorized } return nil } - -func AssertAuthorized() { - caller := std.PrevRealm().Addr() - if caller != main || caller != backup { - panic("config: unauthorized") - } -} diff --git a/examples/gno.land/r/leon/home/home.gno b/examples/gno.land/r/leon/home/home.gno index 1f6a07e8959..ba688792a4c 100644 --- a/examples/gno.land/r/leon/home/home.gno +++ b/examples/gno.land/r/leon/home/home.gno @@ -34,13 +34,19 @@ TODO import r/gh } func UpdatePFP(url, caption string) { - config.AssertAuthorized() + if !isAuthorized(std.PrevRealm().Addr()) { + panic(config.ErrUnauthorized) + } + pfp = url pfpCaption = caption } func UpdateAboutMe(col1, col2 string) { - config.AssertAuthorized() + if !isAuthorized(std.PrevRealm().Addr()) { + panic(config.ErrUnauthorized) + } + abtMe[0] = col1 abtMe[1] = col2 } @@ -119,3 +125,7 @@ func renderMillipede() string { return out } + +func isAuthorized(addr std.Address) bool { + return addr == config.Address() || addr == config.Backup() +} diff --git a/examples/gno.land/r/stefann/home/gno.mod b/examples/gno.land/r/stefann/home/gno.mod new file mode 100644 index 00000000000..dd556e7f817 --- /dev/null +++ b/examples/gno.land/r/stefann/home/gno.mod @@ -0,0 +1,9 @@ +module gno.land/r/stefann/home + +require ( + gno.land/p/demo/avl v0.0.0-latest + gno.land/p/demo/ownable v0.0.0-latest + gno.land/p/demo/testutils v0.0.0-latest + gno.land/p/demo/ufmt v0.0.0-latest + gno.land/r/stefann/registry v0.0.0-latest +) diff --git a/examples/gno.land/r/stefann/home/home.gno b/examples/gno.land/r/stefann/home/home.gno new file mode 100644 index 00000000000..f40329ebf7e --- /dev/null +++ b/examples/gno.land/r/stefann/home/home.gno @@ -0,0 +1,303 @@ +package home + +import ( + "sort" + "std" + "strings" + + "gno.land/p/demo/avl" + "gno.land/p/demo/ownable" + "gno.land/p/demo/ufmt" + + "gno.land/r/stefann/registry" +) + +type City struct { + Name string + URL string +} + +type Sponsor struct { + Address std.Address + Amount std.Coins +} + +type Profile struct { + pfp string + aboutMe []string +} + +type Travel struct { + cities []City + currentCityIndex int + jarLink string +} + +type Sponsorship struct { + maxSponsors int + sponsors *avl.Tree + DonationsCount int + sponsorsCount int +} + +var ( + profile Profile + travel Travel + sponsorship Sponsorship + owner *ownable.Ownable +) + +func init() { + owner = ownable.NewWithAddress(registry.MainAddr()) + + profile = Profile{ + pfp: "https://i.ibb.co/Bc5YNCx/DSC-0095a.jpg", + aboutMe: []string{ + `### About Me`, + `Hey there! I’m Stefan, a student of Computer Science. I’m all about exploring and adventure — whether it’s diving into the latest tech or discovering a new city, I’m always up for the challenge!`, + + `### Contributions`, + `I'm just getting started, but you can follow my journey through Gno.land right [here](https://github.com/gnolang/hackerspace/issues/94) 🔗`, + }, + } + + travel = Travel{ + cities: []City{ + {Name: "Venice", URL: "https://i.ibb.co/1mcZ7b1/venice.jpg"}, + {Name: "Tokyo", URL: "https://i.ibb.co/wNDJv3H/tokyo.jpg"}, + {Name: "São Paulo", URL: "https://i.ibb.co/yWMq2Sn/sao-paulo.jpg"}, + {Name: "Toronto", URL: "https://i.ibb.co/pb95HJB/toronto.jpg"}, + {Name: "Bangkok", URL: "https://i.ibb.co/pQy3w2g/bangkok.jpg"}, + {Name: "New York", URL: "https://i.ibb.co/6JWLm0h/new-york.jpg"}, + {Name: "Paris", URL: "https://i.ibb.co/q9vf6Hs/paris.jpg"}, + {Name: "Kandersteg", URL: "https://i.ibb.co/60DzywD/kandersteg.jpg"}, + {Name: "Rothenburg", URL: "https://i.ibb.co/cr8d2rQ/rothenburg.jpg"}, + {Name: "Capetown", URL: "https://i.ibb.co/bPGn0v3/capetown.jpg"}, + {Name: "Sydney", URL: "https://i.ibb.co/TBNzqfy/sydney.jpg"}, + {Name: "Oeschinen Lake", URL: "https://i.ibb.co/QJQwp2y/oeschinen-lake.jpg"}, + {Name: "Barra Grande", URL: "https://i.ibb.co/z4RXKc1/barra-grande.jpg"}, + {Name: "London", URL: "https://i.ibb.co/CPGtvgr/london.jpg"}, + }, + currentCityIndex: 0, + jarLink: "https://TODO", // This value should be injected through UpdateJarLink after deployment. + } + + sponsorship = Sponsorship{ + maxSponsors: 5, + sponsors: avl.NewTree(), + DonationsCount: 0, + sponsorsCount: 0, + } +} + +func UpdateCities(newCities []City) { + owner.AssertCallerIsOwner() + travel.cities = newCities +} + +func AddCities(newCities ...City) { + owner.AssertCallerIsOwner() + + travel.cities = append(travel.cities, newCities...) +} + +func UpdateJarLink(newLink string) { + owner.AssertCallerIsOwner() + travel.jarLink = newLink +} + +func UpdatePFP(url string) { + owner.AssertCallerIsOwner() + profile.pfp = url +} + +func UpdateAboutMe(aboutMeStr string) { + owner.AssertCallerIsOwner() + profile.aboutMe = strings.Split(aboutMeStr, "|") +} + +func AddAboutMeRows(newRows ...string) { + owner.AssertCallerIsOwner() + + profile.aboutMe = append(profile.aboutMe, newRows...) +} + +func UpdateMaxSponsors(newMax int) { + owner.AssertCallerIsOwner() + if newMax <= 0 { + panic("maxSponsors must be greater than zero") + } + sponsorship.maxSponsors = newMax +} + +func Donate() { + address := std.GetOrigCaller() + amount := std.GetOrigSend() + + if amount.AmountOf("ugnot") == 0 { + panic("Donation must include GNOT") + } + + existingAmount, exists := sponsorship.sponsors.Get(address.String()) + if exists { + updatedAmount := existingAmount.(std.Coins).Add(amount) + sponsorship.sponsors.Set(address.String(), updatedAmount) + } else { + sponsorship.sponsors.Set(address.String(), amount) + sponsorship.sponsorsCount++ + } + + travel.currentCityIndex++ + sponsorship.DonationsCount++ + + banker := std.GetBanker(std.BankerTypeRealmSend) + ownerAddr := registry.MainAddr() + banker.SendCoins(std.CurrentRealm().Addr(), ownerAddr, banker.GetCoins(std.CurrentRealm().Addr())) +} + +type SponsorSlice []Sponsor + +func (s SponsorSlice) Len() int { + return len(s) +} + +func (s SponsorSlice) Less(i, j int) bool { + return s[i].Amount.AmountOf("ugnot") > s[j].Amount.AmountOf("ugnot") +} + +func (s SponsorSlice) Swap(i, j int) { + s[i], s[j] = s[j], s[i] +} + +func GetTopSponsors() []Sponsor { + var sponsorSlice SponsorSlice + + sponsorship.sponsors.Iterate("", "", func(key string, value interface{}) bool { + addr := std.Address(key) + amount := value.(std.Coins) + sponsorSlice = append(sponsorSlice, Sponsor{Address: addr, Amount: amount}) + return false + }) + + sort.Sort(sponsorSlice) + return sponsorSlice +} + +func GetTotalDonations() int { + total := 0 + sponsorship.sponsors.Iterate("", "", func(key string, value interface{}) bool { + total += int(value.(std.Coins).AmountOf("ugnot")) + return false + }) + return total +} + +func Render(path string) string { + out := ufmt.Sprintf("# Exploring %s!\n\n", travel.cities[travel.currentCityIndex].Name) + + out += renderAboutMe() + out += "\n\n" + out += renderTips() + + return out +} + +func renderAboutMe() string { + out := "
" + + out += "
\n\n" + + out += ufmt.Sprintf("
\n\n", travel.cities[travel.currentCityIndex%len(travel.cities)].URL) + + out += ufmt.Sprintf("my profile pic\n\n", profile.pfp) + + out += "
\n\n" + + for _, rows := range profile.aboutMe { + out += "
\n\n" + out += rows + "\n\n" + out += "
\n\n" + } + + out += "
\n\n" + + return out +} + +func renderTips() string { + out := `
` + "\n\n" + + out += `
` + "\n" + + out += `

Help Me Travel The World

` + "\n\n" + + out += renderTipsJar() + "\n" + + out += ufmt.Sprintf(`I am currently in %s,
tip the jar to send me somewhere else!
`, travel.cities[travel.currentCityIndex].Name) + + out += `
Click the jar, tip in GNOT coins, and watch my background change as I head to a new adventure!

` + "\n\n" + + out += renderSponsors() + + out += `
` + "\n\n" + + out += `
` + "\n" + + return out +} + +func formatAddress(address string) string { + if len(address) <= 8 { + return address + } + return address[:4] + "..." + address[len(address)-4:] +} + +func renderSponsors() string { + out := `

Sponsor Leaderboard

` + "\n" + + if sponsorship.sponsorsCount == 0 { + return out + `

No sponsors yet. Be the first to tip the jar!

` + "\n" + } + + topSponsors := GetTopSponsors() + numSponsors := len(topSponsors) + if numSponsors > sponsorship.maxSponsors { + numSponsors = sponsorship.maxSponsors + } + + out += `
    ` + "\n" + + for i := 0; i < numSponsors; i++ { + sponsor := topSponsors[i] + isLastItem := (i == numSponsors-1) + + padding := "10px 5px" + border := "border-bottom: 1px solid #ddd;" + + if isLastItem { + padding = "8px 5px" + border = "" + } + + out += ufmt.Sprintf( + `
  • + %d. %s + %s +
  • `, + padding, border, i+1, formatAddress(sponsor.Address.String()), sponsor.Amount.String(), + ) + } + + return out +} + +func renderTipsJar() string { + out := ufmt.Sprintf(``, travel.jarLink) + "\n" + + out += `Tips Jar` + "\n" + + out += `` + "\n" + + return out +} diff --git a/examples/gno.land/r/stefann/home/home_test.gno b/examples/gno.land/r/stefann/home/home_test.gno new file mode 100644 index 00000000000..ca146b9eb13 --- /dev/null +++ b/examples/gno.land/r/stefann/home/home_test.gno @@ -0,0 +1,291 @@ +package home + +import ( + "std" + "strings" + "testing" + + "gno.land/p/demo/avl" + "gno.land/p/demo/testutils" +) + +func TestUpdatePFP(t *testing.T) { + var owner = std.Address("g1sd5ezmxt4rwpy52u6wl3l3y085n8x0p6nllxm8") + std.TestSetOrigCaller(owner) + + profile.pfp = "" + + UpdatePFP("https://example.com/pic.png") + + if profile.pfp != "https://example.com/pic.png" { + t.Fatalf("expected pfp to be https://example.com/pic.png, got %s", profile.pfp) + } +} + +func TestUpdateAboutMe(t *testing.T) { + var owner = std.Address("g1sd5ezmxt4rwpy52u6wl3l3y085n8x0p6nllxm8") + std.TestSetOrigCaller(owner) + + profile.aboutMe = []string{} + + UpdateAboutMe("This is my new bio.|I love coding!") + + expected := []string{"This is my new bio.", "I love coding!"} + + if len(profile.aboutMe) != len(expected) { + t.Fatalf("expected aboutMe to have length %d, got %d", len(expected), len(profile.aboutMe)) + } + + for i := range profile.aboutMe { + if profile.aboutMe[i] != expected[i] { + t.Fatalf("expected aboutMe[%d] to be %s, got %s", i, expected[i], profile.aboutMe[i]) + } + } +} + +func TestUpdateCities(t *testing.T) { + var owner = std.Address("g1sd5ezmxt4rwpy52u6wl3l3y085n8x0p6nllxm8") + std.TestSetOrigCaller(owner) + + travel.cities = []City{} + + newCities := []City{ + {Name: "Berlin", URL: "https://example.com/berlin.jpg"}, + {Name: "Vienna", URL: "https://example.com/vienna.jpg"}, + } + + UpdateCities(newCities) + + if len(travel.cities) != 2 { + t.Fatalf("expected 2 cities, got %d", len(travel.cities)) + } + + if travel.cities[0].Name != "Berlin" || travel.cities[1].Name != "Vienna" { + t.Fatalf("expected cities to be updated to Berlin and Vienna, got %+v", travel.cities) + } +} + +func TestUpdateJarLink(t *testing.T) { + var owner = std.Address("g1sd5ezmxt4rwpy52u6wl3l3y085n8x0p6nllxm8") + std.TestSetOrigCaller(owner) + + travel.jarLink = "" + + UpdateJarLink("https://example.com/jar") + + if travel.jarLink != "https://example.com/jar" { + t.Fatalf("expected jarLink to be https://example.com/jar, got %s", travel.jarLink) + } +} + +func TestUpdateMaxSponsors(t *testing.T) { + var owner = std.Address("g1sd5ezmxt4rwpy52u6wl3l3y085n8x0p6nllxm8") + std.TestSetOrigCaller(owner) + + sponsorship.maxSponsors = 0 + + UpdateMaxSponsors(10) + + if sponsorship.maxSponsors != 10 { + t.Fatalf("expected maxSponsors to be 10, got %d", sponsorship.maxSponsors) + } + + defer func() { + if r := recover(); r == nil { + t.Fatalf("expected panic for setting maxSponsors to 0") + } + }() + UpdateMaxSponsors(0) +} + +func TestAddCities(t *testing.T) { + var owner = std.Address("g1sd5ezmxt4rwpy52u6wl3l3y085n8x0p6nllxm8") + std.TestSetOrigCaller(owner) + + travel.cities = []City{} + + AddCities(City{Name: "Berlin", URL: "https://example.com/berlin.jpg"}) + + if len(travel.cities) != 1 { + t.Fatalf("expected 1 city, got %d", len(travel.cities)) + } + if travel.cities[0].Name != "Berlin" || travel.cities[0].URL != "https://example.com/berlin.jpg" { + t.Fatalf("expected city to be Berlin, got %+v", travel.cities[0]) + } + + AddCities( + City{Name: "Paris", URL: "https://example.com/paris.jpg"}, + City{Name: "Tokyo", URL: "https://example.com/tokyo.jpg"}, + ) + + if len(travel.cities) != 3 { + t.Fatalf("expected 3 cities, got %d", len(travel.cities)) + } + if travel.cities[1].Name != "Paris" || travel.cities[2].Name != "Tokyo" { + t.Fatalf("expected cities to be Paris and Tokyo, got %+v", travel.cities[1:]) + } +} + +func TestAddAboutMeRows(t *testing.T) { + var owner = std.Address("g1sd5ezmxt4rwpy52u6wl3l3y085n8x0p6nllxm8") + std.TestSetOrigCaller(owner) + + profile.aboutMe = []string{} + + AddAboutMeRows("I love exploring new technologies!") + + if len(profile.aboutMe) != 1 { + t.Fatalf("expected 1 aboutMe row, got %d", len(profile.aboutMe)) + } + if profile.aboutMe[0] != "I love exploring new technologies!" { + t.Fatalf("expected first aboutMe row to be 'I love exploring new technologies!', got %s", profile.aboutMe[0]) + } + + AddAboutMeRows("Travel is my passion!", "Always learning.") + + if len(profile.aboutMe) != 3 { + t.Fatalf("expected 3 aboutMe rows, got %d", len(profile.aboutMe)) + } + if profile.aboutMe[1] != "Travel is my passion!" || profile.aboutMe[2] != "Always learning." { + t.Fatalf("expected aboutMe rows to be 'Travel is my passion!' and 'Always learning.', got %+v", profile.aboutMe[1:]) + } +} + +func TestDonate(t *testing.T) { + var user = testutils.TestAddress("user") + std.TestSetOrigCaller(user) + + sponsorship.sponsors = avl.NewTree() + sponsorship.DonationsCount = 0 + sponsorship.sponsorsCount = 0 + travel.currentCityIndex = 0 + + coinsSent := std.NewCoins(std.NewCoin("ugnot", 500)) + std.TestSetOrigSend(coinsSent, std.NewCoins()) + Donate() + + existingAmount, exists := sponsorship.sponsors.Get(string(user)) + if !exists { + t.Fatalf("expected sponsor to be added, but it was not found") + } + + if existingAmount.(std.Coins).AmountOf("ugnot") != 500 { + t.Fatalf("expected donation amount to be 500ugnot, got %d", existingAmount.(std.Coins).AmountOf("ugnot")) + } + + if sponsorship.DonationsCount != 1 { + t.Fatalf("expected DonationsCount to be 1, got %d", sponsorship.DonationsCount) + } + + if sponsorship.sponsorsCount != 1 { + t.Fatalf("expected sponsorsCount to be 1, got %d", sponsorship.sponsorsCount) + } + + if travel.currentCityIndex != 1 { + t.Fatalf("expected currentCityIndex to be 1, got %d", travel.currentCityIndex) + } + + coinsSent = std.NewCoins(std.NewCoin("ugnot", 300)) + std.TestSetOrigSend(coinsSent, std.NewCoins()) + Donate() + + existingAmount, exists = sponsorship.sponsors.Get(string(user)) + if !exists { + t.Fatalf("expected sponsor to exist after second donation, but it was not found") + } + + if existingAmount.(std.Coins).AmountOf("ugnot") != 800 { + t.Fatalf("expected total donation amount to be 800ugnot, got %d", existingAmount.(std.Coins).AmountOf("ugnot")) + } + + if sponsorship.DonationsCount != 2 { + t.Fatalf("expected DonationsCount to be 2 after second donation, got %d", sponsorship.DonationsCount) + } + + if travel.currentCityIndex != 2 { + t.Fatalf("expected currentCityIndex to be 2 after second donation, got %d", travel.currentCityIndex) + } +} + +func TestGetTopSponsors(t *testing.T) { + var user = testutils.TestAddress("user") + std.TestSetOrigCaller(user) + + sponsorship.sponsors = avl.NewTree() + sponsorship.sponsorsCount = 0 + + sponsorship.sponsors.Set("g1address1", std.NewCoins(std.NewCoin("ugnot", 300))) + sponsorship.sponsors.Set("g1address2", std.NewCoins(std.NewCoin("ugnot", 500))) + sponsorship.sponsors.Set("g1address3", std.NewCoins(std.NewCoin("ugnot", 200))) + sponsorship.sponsorsCount = 3 + + topSponsors := GetTopSponsors() + + if len(topSponsors) != 3 { + t.Fatalf("expected 3 sponsors, got %d", len(topSponsors)) + } + + if topSponsors[0].Address.String() != "g1address2" || topSponsors[0].Amount.AmountOf("ugnot") != 500 { + t.Fatalf("expected top sponsor to be g1address2 with 500ugnot, got %s with %dugnot", topSponsors[0].Address.String(), topSponsors[0].Amount.AmountOf("ugnot")) + } + + if topSponsors[1].Address.String() != "g1address1" || topSponsors[1].Amount.AmountOf("ugnot") != 300 { + t.Fatalf("expected second sponsor to be g1address1 with 300ugnot, got %s with %dugnot", topSponsors[1].Address.String(), topSponsors[1].Amount.AmountOf("ugnot")) + } + + if topSponsors[2].Address.String() != "g1address3" || topSponsors[2].Amount.AmountOf("ugnot") != 200 { + t.Fatalf("expected third sponsor to be g1address3 with 200ugnot, got %s with %dugnot", topSponsors[2].Address.String(), topSponsors[2].Amount.AmountOf("ugnot")) + } +} + +func TestGetTotalDonations(t *testing.T) { + var user = testutils.TestAddress("user") + std.TestSetOrigCaller(user) + + sponsorship.sponsors = avl.NewTree() + sponsorship.sponsorsCount = 0 + + sponsorship.sponsors.Set("g1address1", std.NewCoins(std.NewCoin("ugnot", 300))) + sponsorship.sponsors.Set("g1address2", std.NewCoins(std.NewCoin("ugnot", 500))) + sponsorship.sponsors.Set("g1address3", std.NewCoins(std.NewCoin("ugnot", 200))) + sponsorship.sponsorsCount = 3 + + totalDonations := GetTotalDonations() + + if totalDonations != 1000 { + t.Fatalf("expected total donations to be 1000ugnot, got %dugnot", totalDonations) + } +} + +func TestRender(t *testing.T) { + travel.currentCityIndex = 0 + travel.cities = []City{ + {Name: "Venice", URL: "https://example.com/venice.jpg"}, + {Name: "Paris", URL: "https://example.com/paris.jpg"}, + } + + output := Render("") + + expectedCity := "Venice" + if !strings.Contains(output, expectedCity) { + t.Fatalf("expected output to contain city name '%s', got %s", expectedCity, output) + } + + expectedURL := "https://example.com/venice.jpg" + if !strings.Contains(output, expectedURL) { + t.Fatalf("expected output to contain city URL '%s', got %s", expectedURL, output) + } + + travel.currentCityIndex = 1 + output = Render("") + + expectedCity = "Paris" + if !strings.Contains(output, expectedCity) { + t.Fatalf("expected output to contain city name '%s', got %s", expectedCity, output) + } + + expectedURL = "https://example.com/paris.jpg" + if !strings.Contains(output, expectedURL) { + t.Fatalf("expected output to contain city URL '%s', got %s", expectedURL, output) + } +} diff --git a/examples/gno.land/r/stefann/registry/gno.mod b/examples/gno.land/r/stefann/registry/gno.mod new file mode 100644 index 00000000000..5ed3e4916e2 --- /dev/null +++ b/examples/gno.land/r/stefann/registry/gno.mod @@ -0,0 +1,3 @@ +module gno.land/r/stefann/registry + +require gno.land/p/demo/ownable v0.0.0-latest diff --git a/examples/gno.land/r/stefann/registry/registry.gno b/examples/gno.land/r/stefann/registry/registry.gno new file mode 100644 index 00000000000..6f56d105e4b --- /dev/null +++ b/examples/gno.land/r/stefann/registry/registry.gno @@ -0,0 +1,51 @@ +package registry + +import ( + "errors" + "std" + + "gno.land/p/demo/ownable" +) + +var ( + mainAddr std.Address + backupAddr std.Address + owner *ownable.Ownable +) + +func init() { + mainAddr = "g1sd5ezmxt4rwpy52u6wl3l3y085n8x0p6nllxm8" + backupAddr = "g13awn2575t8s2vf3svlprc4dg0e9z5wchejdxk8" + + owner = ownable.NewWithAddress(mainAddr) +} + +func MainAddr() std.Address { + return mainAddr +} + +func BackupAddr() std.Address { + return backupAddr +} + +func SetMainAddr(addr std.Address) error { + if !addr.IsValid() { + return errors.New("config: invalid address") + } + + owner.AssertCallerIsOwner() + + mainAddr = addr + return nil +} + +func SetBackupAddr(addr std.Address) error { + if !addr.IsValid() { + return errors.New("config: invalid address") + } + + owner.AssertCallerIsOwner() + + backupAddr = addr + return nil +} diff --git a/examples/gno.land/r/sys/validators/doc.gno b/examples/gno.land/r/sys/validators/v2/doc.gno similarity index 100% rename from examples/gno.land/r/sys/validators/doc.gno rename to examples/gno.land/r/sys/validators/v2/doc.gno diff --git a/examples/gno.land/r/sys/validators/gno.mod b/examples/gno.land/r/sys/validators/v2/gno.mod similarity index 71% rename from examples/gno.land/r/sys/validators/gno.mod rename to examples/gno.land/r/sys/validators/v2/gno.mod index d9d129dd543..db94a208902 100644 --- a/examples/gno.land/r/sys/validators/gno.mod +++ b/examples/gno.land/r/sys/validators/v2/gno.mod @@ -1,12 +1,13 @@ -module gno.land/r/sys/validators +module gno.land/r/sys/validators/v2 require ( gno.land/p/demo/avl v0.0.0-latest + gno.land/p/demo/dao v0.0.0-latest gno.land/p/demo/seqid v0.0.0-latest gno.land/p/demo/testutils v0.0.0-latest gno.land/p/demo/uassert v0.0.0-latest gno.land/p/demo/ufmt v0.0.0-latest - gno.land/p/gov/proposal v0.0.0-latest gno.land/p/nt/poa v0.0.0-latest gno.land/p/sys/validators v0.0.0-latest + gno.land/r/gov/dao/bridge v0.0.0-latest ) diff --git a/examples/gno.land/r/sys/validators/gnosdk.gno b/examples/gno.land/r/sys/validators/v2/gnosdk.gno similarity index 100% rename from examples/gno.land/r/sys/validators/gnosdk.gno rename to examples/gno.land/r/sys/validators/v2/gnosdk.gno diff --git a/examples/gno.land/r/sys/validators/init.gno b/examples/gno.land/r/sys/validators/v2/init.gno similarity index 100% rename from examples/gno.land/r/sys/validators/init.gno rename to examples/gno.land/r/sys/validators/v2/init.gno diff --git a/examples/gno.land/r/sys/validators/poc.gno b/examples/gno.land/r/sys/validators/v2/poc.gno similarity index 63% rename from examples/gno.land/r/sys/validators/poc.gno rename to examples/gno.land/r/sys/validators/v2/poc.gno index e088b3b4293..760edc39d1e 100644 --- a/examples/gno.land/r/sys/validators/poc.gno +++ b/examples/gno.land/r/sys/validators/v2/poc.gno @@ -3,16 +3,12 @@ package validators import ( "std" - "gno.land/p/gov/proposal" + "gno.land/p/demo/dao" "gno.land/p/sys/validators" + "gno.land/r/gov/dao/bridge" ) -const daoPkgPath = "gno.land/r/gov/dao" - -const ( - errNoChangesProposed = "no set changes proposed" - errNotGovDAO = "caller not govdao executor" -) +const errNoChangesProposed = "no set changes proposed" // NewPropExecutor creates a new executor that wraps a changes closure // proposal. This wrapper is required to ensure the GovDAO Realm actually @@ -20,15 +16,12 @@ const ( // // Concept adapted from: // https://github.com/gnolang/gno/pull/1945 -func NewPropExecutor(changesFn func() []validators.Validator) proposal.Executor { +func NewPropExecutor(changesFn func() []validators.Validator) dao.Executor { if changesFn == nil { panic(errNoChangesProposed) } callback := func() error { - // Make sure the GovDAO executor runs the valset changes - assertGovDAOCaller() - for _, change := range changesFn() { if change.VotingPower == 0 { // This change request is to remove the validator @@ -44,14 +37,7 @@ func NewPropExecutor(changesFn func() []validators.Validator) proposal.Executor return nil } - return proposal.NewExecutor(callback) -} - -// assertGovDAOCaller verifies the caller is the GovDAO executor -func assertGovDAOCaller() { - if std.PrevRealm().PkgPath() != daoPkgPath { - panic(errNotGovDAO) - } + return bridge.GovDAO().NewGovDAOExecutor(callback) } // IsValidator returns a flag indicating if the given bech32 address diff --git a/examples/gno.land/r/sys/validators/validators.gno b/examples/gno.land/r/sys/validators/v2/validators.gno similarity index 100% rename from examples/gno.land/r/sys/validators/validators.gno rename to examples/gno.land/r/sys/validators/v2/validators.gno diff --git a/examples/gno.land/r/sys/validators/validators_test.gno b/examples/gno.land/r/sys/validators/v2/validators_test.gno similarity index 100% rename from examples/gno.land/r/sys/validators/validators_test.gno rename to examples/gno.land/r/sys/validators/v2/validators_test.gno diff --git a/gno.land/cmd/gnoland/genesis.go b/gno.land/cmd/gnoland/genesis.go deleted file mode 100644 index 37c0f8f2926..00000000000 --- a/gno.land/cmd/gnoland/genesis.go +++ /dev/null @@ -1,46 +0,0 @@ -package main - -import ( - "flag" - - "github.com/gnolang/gno/tm2/pkg/commands" -) - -func newGenesisCmd(io commands.IO) *commands.Command { - cmd := commands.NewCommand( - commands.Metadata{ - Name: "genesis", - ShortUsage: "genesis [flags] [...]", - ShortHelp: "gno genesis manipulation suite", - LongHelp: "Gno genesis.json manipulation suite, for managing genesis parameters", - }, - commands.NewEmptyConfig(), - commands.HelpExec, - ) - - cmd.AddSubCommands( - newGenerateCmd(io), - newValidatorCmd(io), - newVerifyCmd(io), - newBalancesCmd(io), - newTxsCmd(io), - ) - - return cmd -} - -// commonCfg is the common -// configuration for genesis commands -// that require a genesis.json -type commonCfg struct { - genesisPath string -} - -func (c *commonCfg) RegisterFlags(fs *flag.FlagSet) { - fs.StringVar( - &c.genesisPath, - "genesis-path", - "./genesis.json", - "the path to the genesis.json", - ) -} diff --git a/gno.land/cmd/gnoland/root.go b/gno.land/cmd/gnoland/root.go index 8df716b1fed..c6143ab9cd3 100644 --- a/gno.land/cmd/gnoland/root.go +++ b/gno.land/cmd/gnoland/root.go @@ -5,12 +5,8 @@ import ( "os" "github.com/gnolang/gno/tm2/pkg/commands" - "github.com/peterbourgon/ff/v3" - "github.com/peterbourgon/ff/v3/fftoml" ) -const flagConfigFlag = "flag-config-path" - func main() { cmd := newRootCmd(commands.NewDefaultIO()) @@ -21,11 +17,7 @@ func newRootCmd(io commands.IO) *commands.Command { cmd := commands.NewCommand( commands.Metadata{ ShortUsage: " [flags] [...]", - ShortHelp: "starts the gnoland blockchain node", - Options: []ff.Option{ - ff.WithConfigFileFlag(flagConfigFlag), - ff.WithConfigFileParser(fftoml.Parser), - }, + ShortHelp: "manages the gnoland blockchain node", }, commands.NewEmptyConfig(), commands.HelpExec, @@ -33,7 +25,6 @@ func newRootCmd(io commands.IO) *commands.Command { cmd.AddSubCommands( newStartCmd(io), - newGenesisCmd(io), newSecretsCmd(io), newConfigCmd(io), ) diff --git a/gno.land/cmd/gnoland/start.go b/gno.land/cmd/gnoland/start.go index 21f0cb4b1a6..77d7e20b8ef 100644 --- a/gno.land/cmd/gnoland/start.go +++ b/gno.land/cmd/gnoland/start.go @@ -14,6 +14,7 @@ import ( "time" "github.com/gnolang/gno/gno.land/pkg/gnoland" + "github.com/gnolang/gno/gno.land/pkg/gnoland/ugnot" "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" @@ -25,6 +26,7 @@ import ( "github.com/gnolang/gno/tm2/pkg/crypto" "github.com/gnolang/gno/tm2/pkg/events" osm "github.com/gnolang/gno/tm2/pkg/os" + "github.com/gnolang/gno/tm2/pkg/std" "github.com/gnolang/gno/tm2/pkg/telemetry" "go.uber.org/zap" "go.uber.org/zap/zapcore" @@ -42,6 +44,12 @@ var startGraphic = strings.ReplaceAll(` /___/ `, "'", "`") +var ( + // Keep in sync with contribs/gnogenesis/internal/txs/txs_add_packages.go + genesisDeployAddress = crypto.MustAddressFromString("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") // test1 + genesisDeployFee = std.NewFee(50000, std.MustParseCoin(ugnot.ValueString(1000000))) +) + type startCfg struct { gnoRootDir string // TODO: remove as part of https://github.com/gnolang/gno/issues/1952 skipFailingGenesisTxs bool // TODO: remove as part of https://github.com/gnolang/gno/issues/1952 @@ -51,8 +59,6 @@ type startCfg struct { genesisFile string chainID string dataDir string - genesisMaxVMCycles int64 - config string lazyInit bool logLevel string @@ -137,20 +143,6 @@ func (c *startCfg) RegisterFlags(fs *flag.FlagSet) { "replacement for '%%REMOTE%%' in genesis", ) - fs.Int64Var( - &c.genesisMaxVMCycles, - "genesis-max-vm-cycles", - 100_000_000, - "set maximum allowed vm cycles per operation. Zero means no limit.", - ) - - fs.StringVar( - &c.config, - flagConfigFlag, - "", - "the flag config file (optional)", - ) - fs.StringVar( &c.logLevel, "log-level", diff --git a/gno.land/cmd/gnoland/testdata/append.txtar b/gno.land/cmd/gnoland/testdata/append.txtar index 46b66f9524b..3450b3e9b32 100644 --- a/gno.land/cmd/gnoland/testdata/append.txtar +++ b/gno.land/cmd/gnoland/testdata/append.txtar @@ -3,69 +3,69 @@ loadpkg gno.land/p/demo/ufmt # start a new node gnoland start -gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/append -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1 +gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/append -gas-fee 1000000ugnot -gas-wanted 4000000 -broadcast -chainid=tendermint_test test1 stdout OK! # Call Append 1 -gnokey maketx call -pkgpath gno.land/r/append -func Append -gas-fee 1000000ugnot -gas-wanted 2000000 -args '1' -broadcast -chainid=tendermint_test test1 +gnokey maketx call -pkgpath gno.land/r/append -func Append -gas-fee 1000000ugnot -gas-wanted 4000000 -args '1' -broadcast -chainid=tendermint_test test1 stdout OK! -gnokey maketx call -pkgpath gno.land/r/append -func AppendNil -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1 +gnokey maketx call -pkgpath gno.land/r/append -func AppendNil -gas-fee 1000000ugnot -gas-wanted 4000000 -broadcast -chainid=tendermint_test test1 stdout OK! # Call Append 2 -gnokey maketx call -pkgpath gno.land/r/append -func Append -gas-fee 1000000ugnot -gas-wanted 2000000 -args '2' -broadcast -chainid=tendermint_test test1 +gnokey maketx call -pkgpath gno.land/r/append -func Append -gas-fee 1000000ugnot -gas-wanted 4000000 -args '2' -broadcast -chainid=tendermint_test test1 stdout OK! # Call Append 3 -gnokey maketx call -pkgpath gno.land/r/append -func Append -gas-fee 1000000ugnot -gas-wanted 2000000 -args '3' -broadcast -chainid=tendermint_test test1 +gnokey maketx call -pkgpath gno.land/r/append -func Append -gas-fee 1000000ugnot -gas-wanted 4000000 -args '3' -broadcast -chainid=tendermint_test test1 stdout OK! # Call render -gnokey maketx call -pkgpath gno.land/r/append -func Render -gas-fee 1000000ugnot -gas-wanted 2000000 -args '' -broadcast -chainid=tendermint_test test1 +gnokey maketx call -pkgpath gno.land/r/append -func Render -gas-fee 1000000ugnot -gas-wanted 4000000 -args '' -broadcast -chainid=tendermint_test test1 stdout '("1-2-3-" string)' stdout OK! # Call Pop -gnokey maketx call -pkgpath gno.land/r/append -func Pop -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1 +gnokey maketx call -pkgpath gno.land/r/append -func Pop -gas-fee 1000000ugnot -gas-wanted 4000000 -broadcast -chainid=tendermint_test test1 stdout OK! # Call render -gnokey maketx call -pkgpath gno.land/r/append -func Render -gas-fee 1000000ugnot -gas-wanted 2000000 -args '' -broadcast -chainid=tendermint_test test1 +gnokey maketx call -pkgpath gno.land/r/append -func Render -gas-fee 1000000ugnot -gas-wanted 4000000 -args '' -broadcast -chainid=tendermint_test test1 stdout '("2-3-" string)' stdout OK! # Call Append 42 -gnokey maketx call -pkgpath gno.land/r/append -func Append -gas-fee 1000000ugnot -gas-wanted 2000000 -args '42' -broadcast -chainid=tendermint_test test1 +gnokey maketx call -pkgpath gno.land/r/append -func Append -gas-fee 1000000ugnot -gas-wanted 4000000 -args '42' -broadcast -chainid=tendermint_test test1 stdout OK! # Call render -gnokey maketx call -pkgpath gno.land/r/append -func Render -gas-fee 1000000ugnot -gas-wanted 2000000 -args '' -broadcast -chainid=tendermint_test test1 +gnokey maketx call -pkgpath gno.land/r/append -func Render -gas-fee 1000000ugnot -gas-wanted 4000000 -args '' -broadcast -chainid=tendermint_test test1 stdout '("2-3-42-" string)' stdout OK! -gnokey maketx call -pkgpath gno.land/r/append -func CopyAppend -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1 +gnokey maketx call -pkgpath gno.land/r/append -func CopyAppend -gas-fee 1000000ugnot -gas-wanted 4000000 -broadcast -chainid=tendermint_test test1 stdout OK! -gnokey maketx call -pkgpath gno.land/r/append -func PopB -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1 +gnokey maketx call -pkgpath gno.land/r/append -func PopB -gas-fee 1000000ugnot -gas-wanted 4000000 -broadcast -chainid=tendermint_test test1 stdout OK! # Call render -gnokey maketx call -pkgpath gno.land/r/append -func Render -gas-fee 1000000ugnot -gas-wanted 2000000 -args '' -broadcast -chainid=tendermint_test test1 +gnokey maketx call -pkgpath gno.land/r/append -func Render -gas-fee 1000000ugnot -gas-wanted 4000000 -args '' -broadcast -chainid=tendermint_test test1 stdout '("2-3-42-" string)' stdout OK! -gnokey maketx call -pkgpath gno.land/r/append -func AppendMoreAndC -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1 +gnokey maketx call -pkgpath gno.land/r/append -func AppendMoreAndC -gas-fee 1000000ugnot -gas-wanted 4000000 -broadcast -chainid=tendermint_test test1 stdout OK! -gnokey maketx call -pkgpath gno.land/r/append -func ReassignC -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1 +gnokey maketx call -pkgpath gno.land/r/append -func ReassignC -gas-fee 1000000ugnot -gas-wanted 4000000 -broadcast -chainid=tendermint_test test1 stdout OK! -gnokey maketx call -pkgpath gno.land/r/append -func Render -gas-fee 1000000ugnot -gas-wanted 2000000 -args '' -broadcast -chainid=tendermint_test test1 +gnokey maketx call -pkgpath gno.land/r/append -func Render -gas-fee 1000000ugnot -gas-wanted 4000000 -args '' -broadcast -chainid=tendermint_test test1 stdout '("2-3-42-70-100-" string)' stdout OK! -gnokey maketx call -pkgpath gno.land/r/append -func Render -gas-fee 1000000ugnot -gas-wanted 2000000 -args 'd' -broadcast -chainid=tendermint_test test1 +gnokey maketx call -pkgpath gno.land/r/append -func Render -gas-fee 1000000ugnot -gas-wanted 4000000 -args 'd' -broadcast -chainid=tendermint_test test1 stdout '("1-" string)' stdout OK! diff --git a/gno.land/cmd/gnoland/testdata/assertorigincall.txtar b/gno.land/cmd/gnoland/testdata/assertorigincall.txtar index e3cd1be744a..1315f23cc95 100644 --- a/gno.land/cmd/gnoland/testdata/assertorigincall.txtar +++ b/gno.land/cmd/gnoland/testdata/assertorigincall.txtar @@ -33,85 +33,85 @@ gnoland start # Test cases ## 1. MsgCall -> myrlm.A: PANIC -! gnokey maketx call -pkgpath gno.land/r/myrlm -func A -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 +! gnokey maketx call -pkgpath gno.land/r/myrlm -func A -gas-fee 100000ugnot -gas-wanted 4000000 -broadcast -chainid tendermint_test test1 stderr 'invalid non-origin call' ## 2. MsgCall -> myrlm.B: PASS -gnokey maketx call -pkgpath gno.land/r/myrlm -func B -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 +gnokey maketx call -pkgpath gno.land/r/myrlm -func B -gas-fee 100000ugnot -gas-wanted 4000000 -broadcast -chainid tendermint_test test1 stdout 'OK!' ## 3. MsgCall -> myrlm.C: PASS -gnokey maketx call -pkgpath gno.land/r/myrlm -func C -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 +gnokey maketx call -pkgpath gno.land/r/myrlm -func C -gas-fee 100000ugnot -gas-wanted 4000000 -broadcast -chainid tendermint_test test1 stdout 'OK!' ## 4. MsgCall -> r/foo.A -> myrlm.A: PANIC -! gnokey maketx call -pkgpath gno.land/r/foo -func A -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 +! gnokey maketx call -pkgpath gno.land/r/foo -func A -gas-fee 100000ugnot -gas-wanted 4000000 -broadcast -chainid tendermint_test test1 stderr 'invalid non-origin call' ## 5. MsgCall -> r/foo.B -> myrlm.B: PASS -gnokey maketx call -pkgpath gno.land/r/foo -func B -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 +gnokey maketx call -pkgpath gno.land/r/foo -func B -gas-fee 100000ugnot -gas-wanted 4000000 -broadcast -chainid tendermint_test test1 stdout 'OK!' ## 6. MsgCall -> r/foo.C -> myrlm.C: PANIC -! gnokey maketx call -pkgpath gno.land/r/foo -func C -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 +! gnokey maketx call -pkgpath gno.land/r/foo -func C -gas-fee 100000ugnot -gas-wanted 4000000 -broadcast -chainid tendermint_test test1 stderr 'invalid non-origin call' ## remove due to update to maketx call can only call realm (case 7,8,9) ## 7. MsgCall -> p/demo/bar.A -> myrlm.A: PANIC -## ! gnokey maketx call -pkgpath gno.land/p/demo/bar -func A -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 +## ! gnokey maketx call -pkgpath gno.land/p/demo/bar -func A -gas-fee 100000ugnot -gas-wanted 4000000 -broadcast -chainid tendermint_test test1 ## stderr 'invalid non-origin call' ## 8. MsgCall -> p/demo/bar.B -> myrlm.B: PASS -## gnokey maketx call -pkgpath gno.land/p/demo/bar -func B -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 +## gnokey maketx call -pkgpath gno.land/p/demo/bar -func B -gas-fee 100000ugnot -gas-wanted 4000000 -broadcast -chainid tendermint_test test1 ## stdout 'OK!' ## 9. MsgCall -> p/demo/bar.C -> myrlm.C: PANIC -## ! gnokey maketx call -pkgpath gno.land/p/demo/bar -func C -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 +## ! gnokey maketx call -pkgpath gno.land/p/demo/bar -func C -gas-fee 100000ugnot -gas-wanted 4000000 -broadcast -chainid tendermint_test test1 ## stderr 'invalid non-origin call' ## 10. MsgRun -> run.main -> myrlm.A: PANIC -! gnokey maketx run -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 $WORK/run/myrlmA.gno +! gnokey maketx run -gas-fee 100000ugnot -gas-wanted 4000000 -broadcast -chainid tendermint_test test1 $WORK/run/myrlmA.gno stderr 'invalid non-origin call' ## 11. MsgRun -> run.main -> myrlm.B: PASS -gnokey maketx run -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 $WORK/run/myrlmB.gno +gnokey maketx run -gas-fee 100000ugnot -gas-wanted 4000000 -broadcast -chainid tendermint_test test1 $WORK/run/myrlmB.gno stdout 'OK!' ## 12. MsgRun -> run.main -> myrlm.C: PANIC -! gnokey maketx run -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 $WORK/run/myrlmC.gno +! gnokey maketx run -gas-fee 100000ugnot -gas-wanted 4000000 -broadcast -chainid tendermint_test test1 $WORK/run/myrlmC.gno stderr 'invalid non-origin call' ## 13. MsgRun -> run.main -> foo.A: PANIC -! gnokey maketx run -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 $WORK/run/fooA.gno +! gnokey maketx run -gas-fee 100000ugnot -gas-wanted 4000000 -broadcast -chainid tendermint_test test1 $WORK/run/fooA.gno stderr 'invalid non-origin call' ## 14. MsgRun -> run.main -> foo.B: PASS -gnokey maketx run -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 $WORK/run/fooB.gno +gnokey maketx run -gas-fee 100000ugnot -gas-wanted 4000000 -broadcast -chainid tendermint_test test1 $WORK/run/fooB.gno stdout 'OK!' ## 15. MsgRun -> run.main -> foo.C: PANIC -! gnokey maketx run -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 $WORK/run/fooC.gno +! gnokey maketx run -gas-fee 100000ugnot -gas-wanted 4000000 -broadcast -chainid tendermint_test test1 $WORK/run/fooC.gno stderr 'invalid non-origin call' ## 16. MsgRun -> run.main -> bar.A: PANIC -! gnokey maketx run -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 $WORK/run/barA.gno +! gnokey maketx run -gas-fee 100000ugnot -gas-wanted 4000000 -broadcast -chainid tendermint_test test1 $WORK/run/barA.gno stderr 'invalid non-origin call' ## 17. MsgRun -> run.main -> bar.B: PASS -gnokey maketx run -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 $WORK/run/barB.gno +gnokey maketx run -gas-fee 100000ugnot -gas-wanted 4000000 -broadcast -chainid tendermint_test test1 $WORK/run/barB.gno stdout 'OK!' ## 18. MsgRun -> run.main -> bar.C: PANIC -! gnokey maketx run -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 $WORK/run/barC.gno +! gnokey maketx run -gas-fee 100000ugnot -gas-wanted 4000000 -broadcast -chainid tendermint_test test1 $WORK/run/barC.gno stderr 'invalid non-origin call' ## remove testcase 19 due to maketx call forced to call a realm ## 19. MsgCall -> std.AssertOriginCall: pass -## gnokey maketx call -pkgpath std -func AssertOriginCall -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 +## gnokey maketx call -pkgpath std -func AssertOriginCall -gas-fee 100000ugnot -gas-wanted 4000000 -broadcast -chainid tendermint_test test1 ## stdout 'OK!' ## 20. MsgRun -> std.AssertOriginCall: PANIC -! gnokey maketx run -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 $WORK/run/baz.gno +! gnokey maketx run -gas-fee 100000ugnot -gas-wanted 4000000 -broadcast -chainid tendermint_test test1 $WORK/run/baz.gno stderr 'invalid non-origin call' diff --git a/gno.land/cmd/gnoland/testdata/grc20_registry.txtar b/gno.land/cmd/gnoland/testdata/grc20_registry.txtar index 20e78f7ba6e..a5f7ad5eee3 100644 --- a/gno.land/cmd/gnoland/testdata/grc20_registry.txtar +++ b/gno.land/cmd/gnoland/testdata/grc20_registry.txtar @@ -6,15 +6,15 @@ loadpkg gno.land/r/registry $WORK/registry gnoland start # we call Transfer with foo20, before it's registered -gnokey maketx call -pkgpath gno.land/r/registry -func TransferByName -args 'foo20' -args 'g123456789' -args '42' -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1 +gnokey maketx call -pkgpath gno.land/r/registry -func TransferByName -args 'foo20' -args 'g123456789' -args '42' -gas-fee 1000000ugnot -gas-wanted 4000000 -broadcast -chainid=tendermint_test test1 stdout 'not found' # add foo20, and foo20wrapper -gnokey maketx addpkg -pkgdir $WORK/foo20 -pkgpath gno.land/r/foo20 -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1 -gnokey maketx addpkg -pkgdir $WORK/foo20wrapper -pkgpath gno.land/r/foo20wrapper -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1 +gnokey maketx addpkg -pkgdir $WORK/foo20 -pkgpath gno.land/r/foo20 -gas-fee 1000000ugnot -gas-wanted 4000000 -broadcast -chainid=tendermint_test test1 +gnokey maketx addpkg -pkgdir $WORK/foo20wrapper -pkgpath gno.land/r/foo20wrapper -gas-fee 1000000ugnot -gas-wanted 4000000 -broadcast -chainid=tendermint_test test1 # we call Transfer with foo20, after it's registered -gnokey maketx call -pkgpath gno.land/r/registry -func TransferByName -args 'foo20' -args 'g123456789' -args '42' -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1 +gnokey maketx call -pkgpath gno.land/r/registry -func TransferByName -args 'foo20' -args 'g123456789' -args '42' -gas-fee 1000000ugnot -gas-wanted 4000000 -broadcast -chainid=tendermint_test test1 stdout 'same address, success!' -- registry/registry.gno -- @@ -49,7 +49,7 @@ import "gno.land/r/registry" import "gno.land/r/foo20" func init() { - registry.Register("foo20", foo20.Transfer) + registry.Register("foo20", foo20.Transfer) } -- foo20/foo20.gno -- diff --git a/gno.land/cmd/gnoland/testdata/issue_1167.txtar b/gno.land/cmd/gnoland/testdata/issue_1167.txtar index c43f7a45bd5..73febb0235a 100644 --- a/gno.land/cmd/gnoland/testdata/issue_1167.txtar +++ b/gno.land/cmd/gnoland/testdata/issue_1167.txtar @@ -4,30 +4,30 @@ loadpkg gno.land/p/demo/avl gnoland start # add contract -gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/demo/xx -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1 +gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/demo/xx -gas-fee 1000000ugnot -gas-wanted 4000000 -broadcast -chainid=tendermint_test test1 stdout OK! # execute New -gnokey maketx call -pkgpath gno.land/r/demo/xx -func New -args X -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1 +gnokey maketx call -pkgpath gno.land/r/demo/xx -func New -args X -gas-fee 1000000ugnot -gas-wanted 4000000 -broadcast -chainid=tendermint_test test1 stdout OK! # execute Delta for the first time -gnokey maketx call -pkgpath gno.land/r/demo/xx -func Delta -args X -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1 +gnokey maketx call -pkgpath gno.land/r/demo/xx -func Delta -args X -gas-fee 1000000ugnot -gas-wanted 4000000 -broadcast -chainid=tendermint_test test1 stdout OK! stdout '"1,1,1;" string' # execute Delta for the second time -gnokey maketx call -pkgpath gno.land/r/demo/xx -func Delta -args X -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1 +gnokey maketx call -pkgpath gno.land/r/demo/xx -func Delta -args X -gas-fee 1000000ugnot -gas-wanted 4000000 -broadcast -chainid=tendermint_test test1 stdout OK! stdout '1,1,1;2,2,2;" string' # execute Delta for the third time -gnokey maketx call -pkgpath gno.land/r/demo/xx -func Delta -args X -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1 +gnokey maketx call -pkgpath gno.land/r/demo/xx -func Delta -args X -gas-fee 1000000ugnot -gas-wanted 4000000 -broadcast -chainid=tendermint_test test1 stdout OK! stdout '1,1,1;2,2,2;3,3,3;" string' # execute Render -gnokey maketx call -pkgpath gno.land/r/demo/xx -func Render -args X -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1 +gnokey maketx call -pkgpath gno.land/r/demo/xx -func Render -args X -gas-fee 1000000ugnot -gas-wanted 4000000 -broadcast -chainid=tendermint_test test1 stdout OK! stdout '1,1,1;2,2,2;3,3,3;" string' diff --git a/gno.land/cmd/gnoland/testdata/params.txtar b/gno.land/cmd/gnoland/testdata/params.txtar new file mode 100644 index 00000000000..30363aa6369 --- /dev/null +++ b/gno.land/cmd/gnoland/testdata/params.txtar @@ -0,0 +1,65 @@ +# test for https://github.com/gnolang/gno/pull/2920 + +gnoland start + +# query before adding the package +gnokey query params/vm/gno.land/r/sys/setter.foo.string +stdout 'data: $' +gnokey query params/vm/gno.land/r/sys/setter.bar.bool +stdout 'data: $' +gnokey query params/vm/gno.land/r/sys/setter.baz.int64 +stdout 'data: $' + +gnokey maketx addpkg -pkgdir $WORK/setter -pkgpath gno.land/r/sys/setter -gas-fee 1000000ugnot -gas-wanted 100000000 -broadcast -chainid=tendermint_test test1 + +# query after adding the package, but before setting values +gnokey query params/vm/gno.land/r/sys/setter.foo.string +stdout 'data: $' +gnokey query params/vm/gno.land/r/sys/setter.bar.bool +stdout 'data: $' +gnokey query params/vm/gno.land/r/sys/setter.baz.int64 +stdout 'data: $' + + +# set foo (string) +gnokey maketx call -pkgpath gno.land/r/sys/setter -func SetFoo -args foo1 -gas-fee 1000000ugnot -gas-wanted 10000000 -broadcast -chainid=tendermint_test test1 +gnokey query params/vm/gno.land/r/sys/setter.foo.string +stdout 'data: "foo1"' + +# override foo +gnokey maketx call -pkgpath gno.land/r/sys/setter -func SetFoo -args foo2 -gas-fee 1000000ugnot -gas-wanted 10000000 -broadcast -chainid=tendermint_test test1 +gnokey query params/vm/gno.land/r/sys/setter.foo.string +stdout 'data: "foo2"' + + +# set bar (bool) +gnokey maketx call -pkgpath gno.land/r/sys/setter -func SetBar -args true -gas-fee 1000000ugnot -gas-wanted 10000000 -broadcast -chainid=tendermint_test test1 +gnokey query params/vm/gno.land/r/sys/setter.bar.bool +stdout 'data: true' + +# override bar +gnokey maketx call -pkgpath gno.land/r/sys/setter -func SetBar -args false -gas-fee 1000000ugnot -gas-wanted 10000000 -broadcast -chainid=tendermint_test test1 +gnokey query params/vm/gno.land/r/sys/setter.bar.bool +stdout 'data: false' + + +# set baz (bool) +gnokey maketx call -pkgpath gno.land/r/sys/setter -func SetBaz -args 1337 -gas-fee 1000000ugnot -gas-wanted 10000000 -broadcast -chainid=tendermint_test test1 +gnokey query params/vm/gno.land/r/sys/setter.baz.int64 +stdout 'data: "1337"' + +# override baz +gnokey maketx call -pkgpath gno.land/r/sys/setter -func SetBaz -args 31337 -gas-fee 1000000ugnot -gas-wanted 10000000 -broadcast -chainid=tendermint_test test1 +gnokey query params/vm/gno.land/r/sys/setter.baz.int64 +stdout 'data: "31337"' + +-- setter/setter.gno -- +package setter + +import ( + "std" +) + +func SetFoo(newFoo string) { std.SetParamString("foo.string", newFoo) } +func SetBar(newBar bool) { std.SetParamBool("bar.bool", newBar) } +func SetBaz(newBaz int64) { std.SetParamInt64("baz.int64", newBaz) } diff --git a/gno.land/cmd/gnoland/testdata/prevrealm.txtar b/gno.land/cmd/gnoland/testdata/prevrealm.txtar index 72a207fae22..7a0d994a686 100644 --- a/gno.land/cmd/gnoland/testdata/prevrealm.txtar +++ b/gno.land/cmd/gnoland/testdata/prevrealm.txtar @@ -34,60 +34,60 @@ env RFOO_ADDR=g1evezrh92xaucffmtgsaa3rvmz5s8kedffsg469 # Test cases ## 1. MsgCall -> myrlm.A: user address -gnokey maketx call -pkgpath gno.land/r/myrlm -func A -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 +gnokey maketx call -pkgpath gno.land/r/myrlm -func A -gas-fee 100000ugnot -gas-wanted 4000000 -broadcast -chainid tendermint_test test1 stdout ${USER_ADDR_test1} ## 2. MsgCall -> myrealm.B -> myrlm.A: user address -gnokey maketx call -pkgpath gno.land/r/myrlm -func B -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 +gnokey maketx call -pkgpath gno.land/r/myrlm -func B -gas-fee 100000ugnot -gas-wanted 4000000 -broadcast -chainid tendermint_test test1 stdout ${USER_ADDR_test1} ## 3. MsgCall -> r/foo.A -> myrlm.A: r/foo -gnokey maketx call -pkgpath gno.land/r/foo -func A -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 +gnokey maketx call -pkgpath gno.land/r/foo -func A -gas-fee 100000ugnot -gas-wanted 4000000 -broadcast -chainid tendermint_test test1 stdout ${RFOO_ADDR} ## 4. MsgCall -> r/foo.B -> myrlm.B -> r/foo.A: r/foo -gnokey maketx call -pkgpath gno.land/r/foo -func B -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 +gnokey maketx call -pkgpath gno.land/r/foo -func B -gas-fee 100000ugnot -gas-wanted 4000000 -broadcast -chainid tendermint_test test1 stdout ${RFOO_ADDR} ## remove due to update to maketx call can only call realm (case 5, 6, 13) ## 5. MsgCall -> p/demo/bar.A -> myrlm.A: user address -## gnokey maketx call -pkgpath gno.land/p/demo/bar -func A -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 +## gnokey maketx call -pkgpath gno.land/p/demo/bar -func A -gas-fee 100000ugnot -gas-wanted 4000000 -broadcast -chainid tendermint_test test1 ## stdout ${USER_ADDR_test1} ## 6. MsgCall -> p/demo/bar.B -> myrlm.B -> r/foo.A: user address -## gnokey maketx call -pkgpath gno.land/p/demo/bar -func B -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 +## gnokey maketx call -pkgpath gno.land/p/demo/bar -func B -gas-fee 100000ugnot -gas-wanted 4000000 -broadcast -chainid tendermint_test test1 ## stdout ${USER_ADDR_test1} ## 7. MsgRun -> myrlm.A: user address -gnokey maketx run -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 $WORK/run/myrlmA.gno +gnokey maketx run -gas-fee 100000ugnot -gas-wanted 4000000 -broadcast -chainid tendermint_test test1 $WORK/run/myrlmA.gno stdout ${USER_ADDR_test1} ## 8. MsgRun -> myrealm.B -> myrlm.A: user address -gnokey maketx run -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 $WORK/run/myrlmB.gno +gnokey maketx run -gas-fee 100000ugnot -gas-wanted 4000000 -broadcast -chainid tendermint_test test1 $WORK/run/myrlmB.gno stdout ${USER_ADDR_test1} ## 9. MsgRun -> r/foo.A -> myrlm.A: r/foo -gnokey maketx run -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 $WORK/run/fooA.gno +gnokey maketx run -gas-fee 100000ugnot -gas-wanted 4000000 -broadcast -chainid tendermint_test test1 $WORK/run/fooA.gno stdout ${RFOO_ADDR} ## 10. MsgRun -> r/foo.B -> myrlm.B -> r/foo.A: r/foo -gnokey maketx run -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 $WORK/run/fooB.gno +gnokey maketx run -gas-fee 100000ugnot -gas-wanted 4000000 -broadcast -chainid tendermint_test test1 $WORK/run/fooB.gno stdout ${RFOO_ADDR} ## 11. MsgRun -> p/demo/bar.A -> myrlm.A: user address -gnokey maketx run -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 $WORK/run/barA.gno +gnokey maketx run -gas-fee 100000ugnot -gas-wanted 4000000 -broadcast -chainid tendermint_test test1 $WORK/run/barA.gno stdout ${USER_ADDR_test1} ## 12. MsgRun -> p/demo/bar.B -> myrlm.B -> r/foo.A: user address -gnokey maketx run -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 $WORK/run/barB.gno +gnokey maketx run -gas-fee 100000ugnot -gas-wanted 4000000 -broadcast -chainid tendermint_test test1 $WORK/run/barB.gno stdout ${USER_ADDR_test1} ## 13. MsgCall -> std.PrevRealm(): user address -## gnokey maketx call -pkgpath std -func PrevRealm -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 +## gnokey maketx call -pkgpath std -func PrevRealm -gas-fee 100000ugnot -gas-wanted 4000000 -broadcast -chainid tendermint_test test1 ## stdout ${USER_ADDR_test1} ## 14. MsgRun -> std.PrevRealm(): user address -gnokey maketx run -gas-fee 100000ugnot -gas-wanted 2000000 -broadcast -chainid tendermint_test test1 $WORK/run/baz.gno +gnokey maketx run -gas-fee 100000ugnot -gas-wanted 4000000 -broadcast -chainid tendermint_test test1 $WORK/run/baz.gno stdout ${USER_ADDR_test1} -- r/myrlm/myrlm.gno -- diff --git a/gno.land/cmd/gnoland/testdata/restart_missing_type.txtar b/gno.land/cmd/gnoland/testdata/restart_missing_type.txtar index 7eb91096437..c492f1c6646 100644 --- a/gno.land/cmd/gnoland/testdata/restart_missing_type.txtar +++ b/gno.land/cmd/gnoland/testdata/restart_missing_type.txtar @@ -162,7 +162,7 @@ gnoland restart } ], "fee": { - "gas_wanted": "16000000", + "gas_wanted": "20000000", "gas_fee": "1000000ugnot" }, "signatures": [], @@ -193,10 +193,9 @@ gnoland restart } ], "fee": { - "gas_wanted": "15000000", + "gas_wanted": "16000000", "gas_fee": "1000000ugnot" }, "signatures": [], "memo": "" } - diff --git a/gno.land/cmd/gnoland/types.go b/gno.land/cmd/gnoland/types.go deleted file mode 100644 index a48bfaf7b31..00000000000 --- a/gno.land/cmd/gnoland/types.go +++ /dev/null @@ -1,37 +0,0 @@ -package main - -import ( - "github.com/gnolang/gno/tm2/pkg/std" -) - -// txStore is a wrapper for TM2 transactions -type txStore []std.Tx - -// leftMerge merges the two tx stores, with -// preference to the left -func (i *txStore) leftMerge(b txStore) error { - // Build out the tx hash map - txHashMap := make(map[string]struct{}, len(*i)) - - for _, tx := range *i { - txHash, err := getTxHash(tx) - if err != nil { - return err - } - - txHashMap[txHash] = struct{}{} - } - - for _, tx := range b { - txHash, err := getTxHash(tx) - if err != nil { - return err - } - - if _, exists := txHashMap[txHash]; !exists { - *i = append(*i, tx) - } - } - - return nil -} diff --git a/gno.land/cmd/gnoweb/main.go b/gno.land/cmd/gnoweb/main.go index 547134548ff..5cec7257ebe 100644 --- a/gno.land/cmd/gnoweb/main.go +++ b/gno.land/cmd/gnoweb/main.go @@ -37,6 +37,7 @@ func runMain(args []string) error { fs.StringVar(&cfg.HelpRemote, "help-remote", cfg.HelpRemote, "help page's remote addr") fs.BoolVar(&cfg.WithAnalytics, "with-analytics", cfg.WithAnalytics, "enable privacy-first analytics") fs.StringVar(&bindAddress, "bind", "127.0.0.1:8888", "server listening address") + fs.BoolVar(&cfg.WithHTML, "with-html", cfg.WithHTML, "Enable HTML parsing in markdown rendering") if err := fs.Parse(args); err != nil { return err diff --git a/gno.land/genesis/genesis_txs.jsonl b/gno.land/genesis/genesis_txs.jsonl index daf9fbdc5d4..43453dcd2fc 100644 --- a/gno.land/genesis/genesis_txs.jsonl +++ b/gno.land/genesis/genesis_txs.jsonl @@ -1,17 +1,17 @@ -{"msg":[{"@type":"/vm.m_call","caller":"g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq","send":"","pkg_path":"gno.land/r/demo/users","func":"Invite","args":["g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj:10\ng1589c8cekvmjfmy0qrd4f3z52r7fn7rgk02667s:1\ng13sm84nuqed3fuank8huh7x9mupgw22uft3lcl8:1\ng1m6732pkrngu9vrt0g7056lvr9kcqc4mv83xl5q:1\ng1wg88rhzlwxjd2z4j5de5v5xq30dcf6rjq3dhsj:1\ng18pmaskasz7mxj6rmgrl3al58xu45a7w0l5nmc0:1\ng19wwhkmqlns70604ksp6rkuuu42qhtvyh05lffz:1\ng187982000zsc493znqt828s90cmp6hcp2erhu6m:1\ng1ndpsnrspdnauckytvkfv8s823t3gmpqmtky8pl:1\ng16ja66d65emkr0zxd2tu7xjvm7utthyhpej0037:1\ng1ds24jj9kqjcskd0gzu24r9e4n62ggye230zuv5:1\ng1trkzq75ntamsnw9xnrav2v7gy2lt5g6p29yhdr:1\ng1rrf8s5mrmu00sx04fzfsvc399fklpeg2x0a7mz:1\ng19p5ntfvpt4lwq4jqsmnxsnelhf3tff9scy3w8w:1\ng1tue8l73d6rq4vhqdsp2sr3zhuzpure3k2rnwpz:1\ng14hhsss4ngx5kq77je5g0tl4vftg8qp45ceadk3:1\ng1768hvkh7anhd40ch4h7jdh6j3mpcs7hrat4gl0:1\ng15fa8kyjhu88t9dr8zzua8fwdvkngv5n8yqsm0n:1\ng1xhccdjcscuhgmt3quww6qdy3j3czqt3urc2eac:1\ng1z629z04f85k4t5gnkk5egpxw9tqxeec435esap:1\ng1pfldkplz9puq0v82lu9vqcve9nwrxuq9qe5ttv:1\ng152pn0g5qfgxr7yx8zlwjq48hytkafd8x7egsfv:1\ng1cf2ye686ke38vjyqakreprljum4xu6rwf5jskq:1\ng1c5shztyaj4gjrc5zlwmh9xhex5w7l4asffs2w6:1\ng1lhpx2ktk0ha3qw42raxq4m24a4c4xqxyrgv54q:1\ng1026p54q0j902059sm2zsv37krf0ghcl7gmhyv7:1\ng1n4yvwnv77frq2ccuw27dmtjkd7u4p4jg0pgm7k:1\ng13m7f2e6r3lh3ykxupacdt9sem2tlvmaamwjhll:1\ng19uxluuecjlsqvwmwu8sp6pxaaqfhk972q975xd:1\ng1j80fpcsumfkxypvydvtwtz3j4sdwr8c2u0lr64:1\ng1tjdpptuk9eysq6z38nscqyycr998xjyx3w8jvw:1\ng19t3n89slfemgd3mwuat4lajwcp0yxrkadgeg7a:1\ng1yqndt8xx92l9h494jfruz2w79swzjes3n4wqjc:1\ng13278z0a5ufeg80ffqxpda9dlp599t7ekregcy6:1\ng1ht236wjd83x96uqwh9rh3fq6pylyn78mtwq9v6:1\ng1fj9jccm3zjnqspq7lp2g7lj4czyfq0s35600g9:1\ng1wwppuzdns5u6c6jqpkzua24zh6ppsus6399cea:1\ng1k8pjnguyu36pkc8hy0ufzgpzfmj2jl78la7ek3:1\ng1e8umkzumtxgs8399lw0us4rclea3xl5gxy9spp:1\ng14qekdkj2nmmwea4ufg9n002a3pud23y8k7ugs5:1\ng19w2488ntfgpduzqq3sk4j5x387zynwknqdvjqf:1\ng1495y3z7zrej4rendysnw5kaeu4g3d7x7w0734g:1\ng1hygx8ga9qakhkczyrzs9drm8j8tu4qds9y5e3r:1\ng1f977l6wxdh3qu60kzl75vx2wmzswu68l03r8su:1\ng1644qje5rx6jsdqfkzmgnfcegx4dxkjh6rwqd69:1\ng1mzjajymvmtksdwh3wkrndwj6zls2awl9q83dh6:1\ng14da4n9hcynyzz83q607uu8keuh9hwlv42ra6fa:10\ng14vhcdsyf83ngsrrqc92kmw8q9xakqjm0v8448t:5\n"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AmG6kzznyo1uNqWPAYU6wDpsmzQKDaEOrVRaZ08vOyX0"},"signature":"S8iMMzlOMK8dmox78R9Z8+pSsS8YaTCXrIcaHDpiOgkOy7gqoQJ0oftM0zf8zAz4xpezK8Lzg8Q0fCdXJxV76w=="}],"memo":""} -{"msg":[{"@type":"/vm.m_call","caller":"g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq","send":"","pkg_path":"gno.land/r/demo/users","func":"Invite","args":["g1thlf3yct7n7ex70k0p62user0kn6mj6d3s0cg3\ng1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5\n"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AmG6kzznyo1uNqWPAYU6wDpsmzQKDaEOrVRaZ08vOyX0"},"signature":"njczE6xYdp01+CaUU/8/v0YC/NuZD06+qLind+ZZEEMNaRe/4Ln+4z7dG6HYlaWUMsyI1KCoB6NIehoE0PZ44Q=="}],"memo":""} -{"msg":[{"@type":"/vm.m_call","caller":"g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq","send":"","pkg_path":"gno.land/r/demo/users","func":"Invite","args":["g1589c8cekvmjfmy0qrd4f3z52r7fn7rgk02667s\ng13sm84nuqed3fuank8huh7x9mupgw22uft3lcl8\ng1m6732pkrngu9vrt0g7056lvr9kcqc4mv83xl5q\ng1wg88rhzlwxjd2z4j5de5v5xq30dcf6rjq3dhsj\ng18pmaskasz7mxj6rmgrl3al58xu45a7w0l5nmc0\ng19wwhkmqlns70604ksp6rkuuu42qhtvyh05lffz\ng187982000zsc493znqt828s90cmp6hcp2erhu6m\ng1ndpsnrspdnauckytvkfv8s823t3gmpqmtky8pl\ng16ja66d65emkr0zxd2tu7xjvm7utthyhpej0037\ng1ds24jj9kqjcskd0gzu24r9e4n62ggye230zuv5\ng1trkzq75ntamsnw9xnrav2v7gy2lt5g6p29yhdr\ng1rrf8s5mrmu00sx04fzfsvc399fklpeg2x0a7mz\ng19p5ntfvpt4lwq4jqsmnxsnelhf3tff9scy3w8w\ng1tue8l73d6rq4vhqdsp2sr3zhuzpure3k2rnwpz\ng14hhsss4ngx5kq77je5g0tl4vftg8qp45ceadk3\ng1768hvkh7anhd40ch4h7jdh6j3mpcs7hrat4gl0\ng15fa8kyjhu88t9dr8zzua8fwdvkngv5n8yqsm0n\ng1xhccdjcscuhgmt3quww6qdy3j3czqt3urc2eac\ng1z629z04f85k4t5gnkk5egpxw9tqxeec435esap\ng1pfldkplz9puq0v82lu9vqcve9nwrxuq9qe5ttv\ng152pn0g5qfgxr7yx8zlwjq48hytkafd8x7egsfv\ng1cf2ye686ke38vjyqakreprljum4xu6rwf5jskq\ng1c5shztyaj4gjrc5zlwmh9xhex5w7l4asffs2w6\ng1lhpx2ktk0ha3qw42raxq4m24a4c4xqxyrgv54q\ng1026p54q0j902059sm2zsv37krf0ghcl7gmhyv7\ng1n4yvwnv77frq2ccuw27dmtjkd7u4p4jg0pgm7k\ng13m7f2e6r3lh3ykxupacdt9sem2tlvmaamwjhll\ng19uxluuecjlsqvwmwu8sp6pxaaqfhk972q975xd\ng1j80fpcsumfkxypvydvtwtz3j4sdwr8c2u0lr64\ng1tjdpptuk9eysq6z38nscqyycr998xjyx3w8jvw\ng19t3n89slfemgd3mwuat4lajwcp0yxrkadgeg7a\ng1yqndt8xx92l9h494jfruz2w79swzjes3n4wqjc\ng13278z0a5ufeg80ffqxpda9dlp599t7ekregcy6\ng1ht236wjd83x96uqwh9rh3fq6pylyn78mtwq9v6\ng1fj9jccm3zjnqspq7lp2g7lj4czyfq0s35600g9\ng1wwppuzdns5u6c6jqpkzua24zh6ppsus6399cea\ng1k8pjnguyu36pkc8hy0ufzgpzfmj2jl78la7ek3\ng1e8umkzumtxgs8399lw0us4rclea3xl5gxy9spp\ng14qekdkj2nmmwea4ufg9n002a3pud23y8k7ugs5\ng19w2488ntfgpduzqq3sk4j5x387zynwknqdvjqf\ng1495y3z7zrej4rendysnw5kaeu4g3d7x7w0734g\ng1hygx8ga9qakhkczyrzs9drm8j8tu4qds9y5e3r\ng1f977l6wxdh3qu60kzl75vx2wmzswu68l03r8su\ng1644qje5rx6jsdqfkzmgnfcegx4dxkjh6rwqd69\ng1mzjajymvmtksdwh3wkrndwj6zls2awl9q83dh6\ng1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq\ng14da4n9hcynyzz83q607uu8keuh9hwlv42ra6fa\ng14vhcdsyf83ngsrrqc92kmw8q9xakqjm0v8448t\n"]}],"fee":{"gas_wanted":"4000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AmG6kzznyo1uNqWPAYU6wDpsmzQKDaEOrVRaZ08vOyX0"},"signature":"7AmlhZhsVkxCUl0bbpvpPMnIKihwtG7A5IFR6Tg4xStWLgaUr05XmWRKlO2xjstTtwbVKQT5mFL4h5wyX4SQzw=="}],"memo":""} -{"msg":[{"@type":"/vm.m_call","caller":"g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj","send":"200000000ugnot","pkg_path":"gno.land/r/demo/users","func":"Register","args":["","administrator","g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AmG6kzznyo1uNqWPAYU6wDpsmzQKDaEOrVRaZ08vOyX0"},"signature":"AqCqe0cS55Ym7/BvPDoCDyPP5q8284gecVQ2PMOlq/4lJpO9Q18SOWKI15dMEBY1pT0AYyhCeTirlsM1I3Y4Cg=="}],"memo":""} -{"msg":[{"@type":"/vm.m_call","caller":"g1qpymzwx4l4cy6cerdyajp9ksvjsf20rk5y9rtt","send":"200000000ugnot","pkg_path":"gno.land/r/demo/users","func":"Register","args":["","zo_oma","Love is the encryption key\u003c3"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"A6yg5/iiktruezVw5vZJwLlGwyrvw8RlqOToTRMWXkE2"},"signature":"GGp+bVL2eEvKecPqgcULSABYOSnSMnJzfIsR8ZIRER1GGX/fOiCReX4WKMrGLVROJVfbLQkDRwvhS4TLHlSoSQ=="}],"memo":""} -{"msg":[{"@type":"/vm.m_call","caller":"g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq","send":"200000000ugnot","pkg_path":"gno.land/r/demo/users","func":"Register","args":["","manfred","https://github.com/moul"]}],"fee":{"gas_wanted":"2000000","gas_fee":"200000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AnK+a6mcFDjY6b/v6p7r8QFW1M1PgIoQxBgrwOoyY7v3"},"signature":"9CWeNbKx+hEL+RdHplAVAFntcrAVx5mK9tMqoywuHVoreH844n3yOxddQrGfBk6T2tMBmNWakERRqWZfS+bYAQ=="}],"memo":""} -{"msg":[{"@type":"/vm.m_call","caller":"g1fj9jccm3zjnqspq7lp2g7lj4czyfq0s35600g9","send":"200000000ugnot","pkg_path":"gno.land/r/demo/users","func":"Register","args":["","piupiu","@piux2"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"Ar68lqbU2YC63fbMcYUtJhYO3/66APM/EqF7m0nUjGyz"},"signature":"pTUpP0d/XlfVe3TH1hlaoLhKadzIKG1gtQ/Ueuat72p+659RWRea58Z0mk6GgPE/EeTbhMEY45zufevBdGJVoQ=="}],"memo":""} -{"msg":[{"@type":"/vm.m_call","caller":"g1ds24jj9kqjcskd0gzu24r9e4n62ggye230zuv5","send":"","pkg_path":"gno.land/r/demo/users","func":"Register","args":["g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq","anarcher","https://twitter.com/anarcher"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AjpLbKdQeH+yB/1OCB148l5GlRRrXma71hdA8EES3H7f"},"signature":"pf5xm8oWIQIOEwSGw4icPmynLXb1P1HxKfjeh8UStU1mlIBPKa7yppeIMPpAflC0o2zjFR7Axe7CimAebm3BHg=="}],"memo":""} -{"msg":[{"@type":"/vm.m_call","caller":"g15gdm49ktawvkrl88jadqpucng37yxutucuwaef","send":"200000000ugnot","pkg_path":"gno.land/r/demo/users","func":"Register","args":["","ideamour","\u003c3"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AhClx4AsDuX3DNCPxhDwWnrfd4MIZmxJE4vt47ClVvT2"},"signature":"IQe64af878k6HjLDqIJeg27GXAVF6xS+96cDe2jMlxNV6+8sOcuUctp0GiWVnYfN4tpthC6d4WhBo+VlpHqkbg=="}],"memo":""} -{"msg":[{"@type":"/vm.m_call","caller":"g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj","send":"","pkg_path":"gno.land/r/demo/boards","func":"CreateBoard","args":["testboard"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"A+FhNtsXHjLfSJk1lB8FbiL4mGPjc50Kt81J7EKDnJ2y"},"signature":"vzlSxEFh5jOkaSdv3rsV91v/OJKEF2qSuoCpri1u5tRWq62T7xr3KHRCF5qFnn4aQX/yE8g8f/Y//WPOCUGhJw=="}],"memo":""} -{"msg":[{"@type":"/vm.m_call","caller":"g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj","send":"","pkg_path":"gno.land/r/demo/boards","func":"CreateThread","args":["1","Hello World","This is a demo of Gno smart contract programming. This document was\nconstructed by Gno onto a smart contract hosted on the data Realm \nname [\"gno.land/r/demo/boards\"](https://gno.land/r/demo/boards/)\n([github](https://github.com/gnolang/gno/tree/master/examples/gno.land/r/demo/boards)).\n\n## Starting the `gnoland` node node/validator.\n\nNOTE: Where you see `--remote %%REMOTE%%` here, that flag can be replaced\nwith `--remote localhost:26657` for local testnets.\n\n### build gnoland.\n\n```bash\ngit clone git@github.com:gnolang/gno.git\ncd ./gno\nmake \n```\n\n### add test account.\n\n```bash\n./build/gnokey add test1 --recover\n```\n\nUse this mnemonic:\n\u003e source bonus chronic canvas draft south burst lottery vacant surface solve popular case indicate oppose farm nothing bullet exhibit title speed wink action roast\n\n### start gnoland validator node.\n\n```bash\n./build/gnoland\n```\n\n(This can be reset with `make reset`).\n\n### start gnoland web server (optional).\n\n```bash\ngo run ./gnoland/website\n```\n\n## Signing and broadcasting transactions.\n\n### publish the \"gno.land/p/demo/avl\" package.\n\n```bash\n./build/gnokey maketx addpkg test1 --pkgpath \"gno.land/p/demo/avl\" --pkgdir \"examples/gno.land/p/demo/avl\" --deposit 100ugnot --gas-fee 1ugnot --gas-wanted 2000000 \u003e addpkg.avl.unsigned.txt\n./build/gnokey query \"auth/accounts/g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5\"\n./build/gnokey sign test1 --txpath addpkg.avl.unsigned.txt --chainid \"%%CHAINID%%\" --number 0 --sequence 0 \u003e addpkg.avl.signed.txt\n./build/gnokey broadcast addpkg.avl.signed.txt --remote %%REMOTE%%\n```\n\n### publish the \"gno.land/r/demo/boards\" realm package.\n\n```bash\n./build/gnokey maketx addpkg test1 --pkgpath \"gno.land/r/demo/boards\" --pkgdir \"examples/gno.land/r/demo/boards\" --deposit 100ugnot --gas-fee 1ugnot --gas-wanted 300000000 \u003e addpkg.boards.unsigned.txt\n./build/gnokey sign test1 --txpath addpkg.boards.unsigned.txt --chainid \"%%CHAINID%%\" --number 0 --sequence 1 \u003e addpkg.boards.signed.txt\n./build/gnokey broadcast addpkg.boards.signed.txt --remote %%REMOTE%%\n```\n\n### create a board with a smart contract call.\n\n```bash\n./build/gnokey maketx call test1 --pkgpath \"gno.land/r/demo/boards\" --func CreateBoard --args \"testboard\" --gas-fee 1ugnot --gas-wanted 2000000 \u003e createboard.unsigned.txt\n./build/gnokey sign test1 --txpath createboard.unsigned.txt --chainid \"%%CHAINID%%\" --number 0 --sequence 2 \u003e createboard.signed.txt\n./build/gnokey broadcast createboard.signed.txt --remote %%REMOTE%%\n```\nNext, query for the permanent board ID by querying (you need this to create a new post):\n\n```bash\n./build/gnokey query \"vm/qeval\" --data \"gno.land/r/demo/boards.GetBoardIDFromName(\\\"testboard\\\")\"\n```\n\n### create a post of a board with a smart contract call.\n\n```bash\n./build/gnokey maketx call test1 --pkgpath \"gno.land/r/demo/boards\" --func CreatePost --args 1 --args \"Hello World\" --args#file \"./examples/gno.land/r/demo/boards/README.md\" --gas-fee 1ugnot --gas-wanted 2000000 \u003e createpost.unsigned.txt\n./build/gnokey sign test1 --txpath createpost.unsigned.txt --chainid \"%%CHAINID%%\" --number 0 --sequence 3 \u003e createpost.signed.txt\n./build/gnokey broadcast createpost.signed.txt --remote %%REMOTE%%\n```\n\n### create a comment to a post.\n\n```bash\n./build/gnokey maketx call test1 --pkgpath \"gno.land/r/demo/boards\" --func CreateReply --args 1 --args 1 --args \"A comment\" --gas-fee 1ugnot --gas-wanted 2000000 \u003e createcomment.unsigned.txt\n./build/gnokey sign test1 --txpath createcomment.unsigned.txt --chainid \"%%CHAINID%%\" --number 0 --sequence 4 \u003e createcomment.signed.txt\n./build/gnokey broadcast createcomment.signed.txt --remote %%REMOTE%%\n```\n\n```bash\n./build/gnokey query \"vm/qrender\" --data \"gno.land/r/demo/boards:testboard/1\"\n```\n\n### render page with optional path expression.\n\nThe contents of `https://gno.land/r/demo/boards:` and `https://gno.land/r/demo/boards:testboard` are rendered by calling\nthe `Render(path string)` function like so:\n\n```bash\n./build/gnokey query \"vm/qrender\" --data \"gno.land/r/demo/boards:testboard\"\n```\n"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"A+FhNtsXHjLfSJk1lB8FbiL4mGPjc50Kt81J7EKDnJ2y"},"signature":"V43B1waFxhzheW9TfmCpjLdrC4dC1yjUGES5y3J6QsNar6hRpNz4G1thzWmWK7xXhg8u1PCIpxLxGczKQYhuPw=="}],"memo":""} -{"msg":[{"@type":"/vm.m_call","caller":"g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj","send":"","pkg_path":"gno.land/r/demo/boards","func":"CreateThread","args":["1","NFT example","NFT's are all the rage these days, for various reasons.\n\nI read over EIP-721 which appears to be the de-facto NFT standard on Ethereum. Then, made a sample implementation of EIP-721 (let's here called GRC-721). The implementation isn't complete, but it demonstrates the main functionality.\n\n - [EIP-721](https://eips.ethereum.org/EIPS/eip-721)\n - [gno.land/r/demo/nft/nft.gno](https://gno.land/r/demo/nft/nft.gno)\n - [zrealm_nft3.gno test](https://github.com/gnolang/gno/blob/master/examples/gno.land/r/demo/nft/z_3_filetest.gno)\n\nIn short, this demonstrates how to implement Ethereum contract interfaces in gno.land; by using only standard Go language features.\n\nPlease leave a comment ([guide](https://gno.land/r/demo/boards:testboard/1)).\n"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"A+FhNtsXHjLfSJk1lB8FbiL4mGPjc50Kt81J7EKDnJ2y"},"signature":"ZXfrTiHxPFQL8uSm+Tv7WXIHPMca9okhm94RAlC6YgNbB1VHQYYpoP4w+cnL3YskVzGrOZxensXa9CAZ+cNNeg=="}],"memo":""} -{"msg":[{"@type":"/vm.m_call","caller":"g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj","send":"","pkg_path":"gno.land/r/demo/boards","func":"CreateThread","args":["1","Simple echo example with coins","This is a simple test realm contract that demonstrates how to use the banker.\n\nSee [gno.land/r/demo/banktest/banktest.gno](/r/demo/banktest/banktest.gno) to see the original contract code.\n\nThis article will go through each line to explain how it works.\n\n```go\npackage banktest\n```\n\nThis package is locally named \"banktest\" (could be anything).\n\n```go\nimport (\n\t\"std\"\n)\n```\n\nThe \"std\" package is defined by the gno code in stdlibs/std/. \u003c/br\u003e\nSelf explanatory; and you'll see more usage from std later.\n\n```go\ntype activity struct {\n\tcaller std.Address\n\tsent std.Coins\n\treturned std.Coins\n\ttime std.Time\n}\n\nfunc (act *activity) String() string {\n\treturn act.caller.String() + \" \" +\n\t\tact.sent.String() + \" sent, \" +\n\t\tact.returned.String() + \" returned, at \" +\n\t\tstd.FormatTimestamp(act.time, \"2006-01-02 3:04pm MST\")\n}\n\nvar latest [10]*activity\n```\n\nThis is just maintaining a list of recent activity to this contract.\nNotice that the \"latest\" variable is defined \"globally\" within\nthe context of the realm with path \"gno.land/r/demo/banktest\".\n\nThis means that calls to functions defined within this package\nare encapsulated within this \"data realm\", where the data is \nmutated based on transactions that can potentially cross many\nrealm and non-realm packge boundaries (in the call stack).\n\n```go\n// Deposit will take the coins (to the realm's pkgaddr) or return them to user.\nfunc Deposit(returnDenom string, returnAmount int64) string {\n\tstd.AssertOriginCall()\n\tcaller := std.GetOrigCaller()\n\tsend := std.Coins{{returnDenom, returnAmount}}\n```\n\nThis is the beginning of the definition of the contract function named\n\"Deposit\". `std.AssertOriginCall() asserts that this function was called by a\ngno transactional Message. The caller is the user who signed off on this\ntransactional message. Send is the amount of deposit sent along with this\nmessage.\n\n```go\n\t// record activity\n\tact := \u0026activity{\n\t\tcaller: caller,\n\t\tsent: std.GetOrigSend(),\n\t\treturned: send,\n\t\ttime: std.GetTimestamp(),\n\t}\n\tfor i := len(latest) - 2; i \u003e= 0; i-- {\n\t\tlatest[i+1] = latest[i] // shift by +1.\n\t}\n\tlatest[0] = act\n```\n\nUpdating the \"latest\" array for viewing at gno.land/r/demo/banktest: (w/ trailing colon).\n\n```go\n\t// return if any.\n\tif returnAmount \u003e 0 {\n```\n\nIf the user requested the return of coins...\n\n```go\n\t\tbanker := std.GetBanker(std.BankerTypeOrigSend)\n```\n\nuse a std.Banker instance to return any deposited coins to the original sender.\n\n```go\n\t\tpkgaddr := std.GetOrigPkgAddr()\n\t\t// TODO: use std.Coins constructors, this isn't generally safe.\n\t\tbanker.SendCoins(pkgaddr, caller, send)\n\t\treturn \"returned!\"\n```\n\nNotice that each realm package has an associated Cosmos address.\n\n\nFinally, the results are rendered via an ABCI query call when you visit [/r/demo/banktest:](/r/demo/banktest:).\n\n```go\nfunc Render(path string) string {\n\t// get realm coins.\n\tbanker := std.GetBanker(std.BankerTypeReadonly)\n\tcoins := banker.GetCoins(std.GetOrigPkgAddr())\n\n\t// render\n\tres := \"\"\n\tres += \"## recent activity\\n\"\n\tres += \"\\n\"\n\tfor _, act := range latest {\n\t\tif act == nil {\n\t\t\tbreak\n\t\t}\n\t\tres += \" * \" + act.String() + \"\\n\"\n\t}\n\tres += \"\\n\"\n\tres += \"## total deposits\\n\"\n\tres += coins.String()\n\treturn res\n}\n```\n\nYou can call this contract yourself, by vistiing [/r/demo/banktest](/r/demo/banktest) and the [quickstart guide](/r/demo/boards:testboard/4).\n"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"A+FhNtsXHjLfSJk1lB8FbiL4mGPjc50Kt81J7EKDnJ2y"},"signature":"iZX/llZlNTdZMLv1goCTgK2bWqzT8enlTq56wMTCpVxJGA0BTvuEM5Nnt9vrnlG6Taqj2GuTrmEnJBkDFTmt9g=="}],"memo":""} -{"msg":[{"@type":"/vm.m_call","caller":"g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj","send":"","pkg_path":"gno.land/r/demo/boards","func":"CreateThread","args":["1","TASK: Describe in your words","Describe in an essay (250+ words), on your favorite medium, why you are interested in gno.land and gnolang.\n\nReply here with a URL link to your written piece as a comment, for rewards.\n"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AmG6kzznyo1uNqWPAYU6wDpsmzQKDaEOrVRaZ08vOyX0"},"signature":"4HBNtrta8HdeHj4JTN56PBTRK8GOe31NMRRXDiyYtjozuyRdWfOGEsGjGgHWcoBUJq6DepBgD4FetdqfhZ6TNQ=="}],"memo":""} -{"msg":[{"@type":"/vm.m_call","caller":"g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq","send":"","pkg_path":"gno.land/r/demo/boards","func":"CreateThread","args":["1","Getting Started","This is a demo of Gno smart contract programming. This document was\nconstructed by Gno onto a smart contract hosted on the data Realm\nname [\"gno.land/r/demo/boards\"](https://gno.land/r/demo/boards/)\n([github](https://github.com/gnolang/gno/tree/master/examples/gno.land/r/demo/boards)).\n\n\n\n## Build `gnokey`, create your account, and interact with Gno.\n\nNOTE: Where you see `--remote %%REMOTE%%` here, that flag can be replaced\nwith `--remote localhost:26657` for local testnets.\n\n### Build `gnokey`.\n\n```bash\ngit clone git@github.com:gnolang/gno.git\ncd ./gno\nmake\n```\n\n### Generate a seed/mnemonic code.\n\n```bash\n./build/gnokey generate\n```\n\nNOTE: You can generate 24 words with any good bip39 generator.\n\n### Create a new account using your mnemonic.\n\n```bash\n./build/gnokey add KEYNAME --recover\n```\n\nNOTE: `KEYNAME` is your key identifier, and should be changed.\n\n### Verify that you can see your account locally.\n\n```bash\n./build/gnokey list\n```\n\n## Interact with the blockchain:\n\n### Get your current balance, account number, and sequence number.\n\n```bash\n./build/gnokey query auth/accounts/ACCOUNT_ADDR --remote %%REMOTE%%\n```\n\nNOTE: you can retrieve your `ACCOUNT_ADDR` with `./build/gnokey list`.\n\n### Acquire testnet tokens using the official faucet.\n\nGo to https://gno.land/faucet\n\n### Create a board with a smart contract call.\n\nNOTE: `BOARDNAME` will be the slug of the board, and should be changed.\n\n```bash\n./build/gnokey maketx call KEYNAME --pkgpath \"gno.land/r/demo/boards\" --func \"CreateBoard\" --args \"BOARDNAME\" --gas-fee \"1000000ugnot\" --gas-wanted \"2000000\" --broadcast=true --chainid %%CHAINID%% --remote %%REMOTE%%\n```\n\nInteractive documentation: https://gno.land/r/demo/boards?help\u0026__func=CreateBoard\n\nNext, query for the permanent board ID by querying (you need this to create a new post):\n\n```bash\n./build/gnokey query \"vm/qeval\" --data \"gno.land/r/demo/boards.GetBoardIDFromName(\\\"BOARDNAME\\\")\" --remote %%REMOTE%%\n```\n\n### Create a post of a board with a smart contract call.\n\nNOTE: If a board was created successfully, your SEQUENCE_NUMBER would have increased.\n\n```bash\n./build/gnokey maketx call KEYNAME --pkgpath \"gno.land/r/demo/boards\" --func \"CreateThread\" --args BOARD_ID --args \"Hello gno.land\" --args\\#file \"./examples/gno.land/r/demo/boards/example_post.md\" --gas-fee 1000000ugnot --gas-wanted 2000000 --broadcast=true --chainid %%CHAINID%% --remote %%REMOTE%%\n```\n\nInteractive documentation: https://gno.land/r/demo/boards?help\u0026__func=CreateThread\n\n### Create a comment to a post.\n\n```bash\n./build/gnokey maketx call KEYNAME --pkgpath \"gno.land/r/demo/boards\" --func \"CreateReply\" --args \"BOARD_ID\" --args \"1\" --args \"1\" --args \"Nice to meet you too.\" --gas-fee 1000000ugnot --gas-wanted 2000000 --broadcast=true --chainid %%CHAINID%% --remote %%REMOTE%%\n```\n\nInteractive documentation: https://gno.land/r/demo/boards?help\u0026__func=CreateReply\n\n```bash\n./build/gnokey query \"vm/qrender\" --data \"gno.land/r/demo/boards:BOARDNAME/1\" --remote %%REMOTE%%\n```\n\n### Render page with optional path expression.\n\nThe contents of `https://gno.land/r/demo/boards:` and `https://gno.land/r/demo/boards:gnolang` are rendered by calling\nthe `Render(path string)` function like so:\n\n```bash\n./build/gnokey query \"vm/qrender\" --data \"gno.land/r/demo/boards:gnolang\"\n```\n\n## Starting a local `gnoland` node:\n\n### Add test account.\n\n```bash\n./build/gnokey add test1 --recover\n```\n\nUse this mneonic:\n\u003e source bonus chronic canvas draft south burst lottery vacant surface solve popular case indicate oppose farm nothing bullet exhibit title speed wink action roast\n\n### Start `gnoland` node.\n\n```bash\n./build/gnoland\n```\n\nNOTE: This can be reset with `make reset`\n\n### Publish the \"gno.land/p/demo/avl\" package.\n\n```bash\n./build/gnokey maketx addpkg test1 --pkgpath \"gno.land/p/demo/avl\" --pkgdir \"examples/gno.land/p/demo/avl\" --deposit 100000000ugnot --gas-fee 1000000ugnot --gas-wanted 2000000 --broadcast=true --chainid %%CHAINID%% --remote localhost:26657\n```\n\n### Publish the \"gno.land/r/demo/boards\" realm package.\n\n```bash\n./build/gnokey maketx addpkg test1 --pkgpath \"gno.land/r/demo/boards\" --pkgdir \"examples/gno.land/r/demo/boards\" --deposit 100000000ugnot --gas-fee 1000000ugnot --gas-wanted 300000000 --broadcast=true --chainid %%CHAINID%% --remote localhost:26657\n```\n"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AnK+a6mcFDjY6b/v6p7r8QFW1M1PgIoQxBgrwOoyY7v3"},"signature":"sHjOGXZEi9wt2FSXFHmkDDoVQyepvFHKRDDU0zgedHYnCYPx5/YndyihsDD5Y2Z7/RgNYBh4JlJwDMGFNStzBQ=="}],"memo":""} -{"msg":[{"@type":"/vm.m_call","caller":"g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq","send":"","pkg_path":"gno.land/r/gnoland/blog","func":"ModAddPost","args":["post1","First post","Lorem Ipsum","2022-05-20T13:17:22Z","","tag1,tag2"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AnK+a6mcFDjY6b/v6p7r8QFW1M1PgIoQxBgrwOoyY7v3"},"signature":"sHjOGXZEi9wt2FSXFHmkDDoVQyepvFHKRDDU0zgedHYnCYPx5/YndyihsDD5Y2Z7/RgNYBh4JlJwDMGFNStzBQ=="}],"memo":""} -{"msg":[{"@type":"/vm.m_call","caller":"g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq","send":"","pkg_path":"gno.land/r/gnoland/blog","func":"ModAddPost","args":["post2","Second post","Lorem Ipsum","2022-05-20T13:17:23Z","","tag1,tag3"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AnK+a6mcFDjY6b/v6p7r8QFW1M1PgIoQxBgrwOoyY7v3"},"signature":"sHjOGXZEi9wt2FSXFHmkDDoVQyepvFHKRDDU0zgedHYnCYPx5/YndyihsDD5Y2Z7/RgNYBh4JlJwDMGFNStzBQ=="}],"memo":""} +{"tx": {"msg":[{"@type":"/vm.m_call","caller":"g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq","send":"","pkg_path":"gno.land/r/demo/users","func":"Invite","args":["g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj:10\ng1589c8cekvmjfmy0qrd4f3z52r7fn7rgk02667s:1\ng13sm84nuqed3fuank8huh7x9mupgw22uft3lcl8:1\ng1m6732pkrngu9vrt0g7056lvr9kcqc4mv83xl5q:1\ng1wg88rhzlwxjd2z4j5de5v5xq30dcf6rjq3dhsj:1\ng18pmaskasz7mxj6rmgrl3al58xu45a7w0l5nmc0:1\ng19wwhkmqlns70604ksp6rkuuu42qhtvyh05lffz:1\ng187982000zsc493znqt828s90cmp6hcp2erhu6m:1\ng1ndpsnrspdnauckytvkfv8s823t3gmpqmtky8pl:1\ng16ja66d65emkr0zxd2tu7xjvm7utthyhpej0037:1\ng1ds24jj9kqjcskd0gzu24r9e4n62ggye230zuv5:1\ng1trkzq75ntamsnw9xnrav2v7gy2lt5g6p29yhdr:1\ng1rrf8s5mrmu00sx04fzfsvc399fklpeg2x0a7mz:1\ng19p5ntfvpt4lwq4jqsmnxsnelhf3tff9scy3w8w:1\ng1tue8l73d6rq4vhqdsp2sr3zhuzpure3k2rnwpz:1\ng14hhsss4ngx5kq77je5g0tl4vftg8qp45ceadk3:1\ng1768hvkh7anhd40ch4h7jdh6j3mpcs7hrat4gl0:1\ng15fa8kyjhu88t9dr8zzua8fwdvkngv5n8yqsm0n:1\ng1xhccdjcscuhgmt3quww6qdy3j3czqt3urc2eac:1\ng1z629z04f85k4t5gnkk5egpxw9tqxeec435esap:1\ng1pfldkplz9puq0v82lu9vqcve9nwrxuq9qe5ttv:1\ng152pn0g5qfgxr7yx8zlwjq48hytkafd8x7egsfv:1\ng1cf2ye686ke38vjyqakreprljum4xu6rwf5jskq:1\ng1c5shztyaj4gjrc5zlwmh9xhex5w7l4asffs2w6:1\ng1lhpx2ktk0ha3qw42raxq4m24a4c4xqxyrgv54q:1\ng1026p54q0j902059sm2zsv37krf0ghcl7gmhyv7:1\ng1n4yvwnv77frq2ccuw27dmtjkd7u4p4jg0pgm7k:1\ng13m7f2e6r3lh3ykxupacdt9sem2tlvmaamwjhll:1\ng19uxluuecjlsqvwmwu8sp6pxaaqfhk972q975xd:1\ng1j80fpcsumfkxypvydvtwtz3j4sdwr8c2u0lr64:1\ng1tjdpptuk9eysq6z38nscqyycr998xjyx3w8jvw:1\ng19t3n89slfemgd3mwuat4lajwcp0yxrkadgeg7a:1\ng1yqndt8xx92l9h494jfruz2w79swzjes3n4wqjc:1\ng13278z0a5ufeg80ffqxpda9dlp599t7ekregcy6:1\ng1ht236wjd83x96uqwh9rh3fq6pylyn78mtwq9v6:1\ng1fj9jccm3zjnqspq7lp2g7lj4czyfq0s35600g9:1\ng1wwppuzdns5u6c6jqpkzua24zh6ppsus6399cea:1\ng1k8pjnguyu36pkc8hy0ufzgpzfmj2jl78la7ek3:1\ng1e8umkzumtxgs8399lw0us4rclea3xl5gxy9spp:1\ng14qekdkj2nmmwea4ufg9n002a3pud23y8k7ugs5:1\ng19w2488ntfgpduzqq3sk4j5x387zynwknqdvjqf:1\ng1495y3z7zrej4rendysnw5kaeu4g3d7x7w0734g:1\ng1hygx8ga9qakhkczyrzs9drm8j8tu4qds9y5e3r:1\ng1f977l6wxdh3qu60kzl75vx2wmzswu68l03r8su:1\ng1644qje5rx6jsdqfkzmgnfcegx4dxkjh6rwqd69:1\ng1mzjajymvmtksdwh3wkrndwj6zls2awl9q83dh6:1\ng14da4n9hcynyzz83q607uu8keuh9hwlv42ra6fa:10\ng14vhcdsyf83ngsrrqc92kmw8q9xakqjm0v8448t:5\n"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AmG6kzznyo1uNqWPAYU6wDpsmzQKDaEOrVRaZ08vOyX0"},"signature":"S8iMMzlOMK8dmox78R9Z8+pSsS8YaTCXrIcaHDpiOgkOy7gqoQJ0oftM0zf8zAz4xpezK8Lzg8Q0fCdXJxV76w=="}],"memo":""}} +{"tx": {"msg":[{"@type":"/vm.m_call","caller":"g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq","send":"","pkg_path":"gno.land/r/demo/users","func":"Invite","args":["g1thlf3yct7n7ex70k0p62user0kn6mj6d3s0cg3\ng1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5\n"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AmG6kzznyo1uNqWPAYU6wDpsmzQKDaEOrVRaZ08vOyX0"},"signature":"njczE6xYdp01+CaUU/8/v0YC/NuZD06+qLind+ZZEEMNaRe/4Ln+4z7dG6HYlaWUMsyI1KCoB6NIehoE0PZ44Q=="}],"memo":""}} +{"tx": {"msg":[{"@type":"/vm.m_call","caller":"g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq","send":"","pkg_path":"gno.land/r/demo/users","func":"Invite","args":["g1589c8cekvmjfmy0qrd4f3z52r7fn7rgk02667s\ng13sm84nuqed3fuank8huh7x9mupgw22uft3lcl8\ng1m6732pkrngu9vrt0g7056lvr9kcqc4mv83xl5q\ng1wg88rhzlwxjd2z4j5de5v5xq30dcf6rjq3dhsj\ng18pmaskasz7mxj6rmgrl3al58xu45a7w0l5nmc0\ng19wwhkmqlns70604ksp6rkuuu42qhtvyh05lffz\ng187982000zsc493znqt828s90cmp6hcp2erhu6m\ng1ndpsnrspdnauckytvkfv8s823t3gmpqmtky8pl\ng16ja66d65emkr0zxd2tu7xjvm7utthyhpej0037\ng1ds24jj9kqjcskd0gzu24r9e4n62ggye230zuv5\ng1trkzq75ntamsnw9xnrav2v7gy2lt5g6p29yhdr\ng1rrf8s5mrmu00sx04fzfsvc399fklpeg2x0a7mz\ng19p5ntfvpt4lwq4jqsmnxsnelhf3tff9scy3w8w\ng1tue8l73d6rq4vhqdsp2sr3zhuzpure3k2rnwpz\ng14hhsss4ngx5kq77je5g0tl4vftg8qp45ceadk3\ng1768hvkh7anhd40ch4h7jdh6j3mpcs7hrat4gl0\ng15fa8kyjhu88t9dr8zzua8fwdvkngv5n8yqsm0n\ng1xhccdjcscuhgmt3quww6qdy3j3czqt3urc2eac\ng1z629z04f85k4t5gnkk5egpxw9tqxeec435esap\ng1pfldkplz9puq0v82lu9vqcve9nwrxuq9qe5ttv\ng152pn0g5qfgxr7yx8zlwjq48hytkafd8x7egsfv\ng1cf2ye686ke38vjyqakreprljum4xu6rwf5jskq\ng1c5shztyaj4gjrc5zlwmh9xhex5w7l4asffs2w6\ng1lhpx2ktk0ha3qw42raxq4m24a4c4xqxyrgv54q\ng1026p54q0j902059sm2zsv37krf0ghcl7gmhyv7\ng1n4yvwnv77frq2ccuw27dmtjkd7u4p4jg0pgm7k\ng13m7f2e6r3lh3ykxupacdt9sem2tlvmaamwjhll\ng19uxluuecjlsqvwmwu8sp6pxaaqfhk972q975xd\ng1j80fpcsumfkxypvydvtwtz3j4sdwr8c2u0lr64\ng1tjdpptuk9eysq6z38nscqyycr998xjyx3w8jvw\ng19t3n89slfemgd3mwuat4lajwcp0yxrkadgeg7a\ng1yqndt8xx92l9h494jfruz2w79swzjes3n4wqjc\ng13278z0a5ufeg80ffqxpda9dlp599t7ekregcy6\ng1ht236wjd83x96uqwh9rh3fq6pylyn78mtwq9v6\ng1fj9jccm3zjnqspq7lp2g7lj4czyfq0s35600g9\ng1wwppuzdns5u6c6jqpkzua24zh6ppsus6399cea\ng1k8pjnguyu36pkc8hy0ufzgpzfmj2jl78la7ek3\ng1e8umkzumtxgs8399lw0us4rclea3xl5gxy9spp\ng14qekdkj2nmmwea4ufg9n002a3pud23y8k7ugs5\ng19w2488ntfgpduzqq3sk4j5x387zynwknqdvjqf\ng1495y3z7zrej4rendysnw5kaeu4g3d7x7w0734g\ng1hygx8ga9qakhkczyrzs9drm8j8tu4qds9y5e3r\ng1f977l6wxdh3qu60kzl75vx2wmzswu68l03r8su\ng1644qje5rx6jsdqfkzmgnfcegx4dxkjh6rwqd69\ng1mzjajymvmtksdwh3wkrndwj6zls2awl9q83dh6\ng1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq\ng14da4n9hcynyzz83q607uu8keuh9hwlv42ra6fa\ng14vhcdsyf83ngsrrqc92kmw8q9xakqjm0v8448t\n"]}],"fee":{"gas_wanted":"4000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AmG6kzznyo1uNqWPAYU6wDpsmzQKDaEOrVRaZ08vOyX0"},"signature":"7AmlhZhsVkxCUl0bbpvpPMnIKihwtG7A5IFR6Tg4xStWLgaUr05XmWRKlO2xjstTtwbVKQT5mFL4h5wyX4SQzw=="}],"memo":""}} +{"tx": {"msg":[{"@type":"/vm.m_call","caller":"g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj","send":"200000000ugnot","pkg_path":"gno.land/r/demo/users","func":"Register","args":["","administrator","g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AmG6kzznyo1uNqWPAYU6wDpsmzQKDaEOrVRaZ08vOyX0"},"signature":"AqCqe0cS55Ym7/BvPDoCDyPP5q8284gecVQ2PMOlq/4lJpO9Q18SOWKI15dMEBY1pT0AYyhCeTirlsM1I3Y4Cg=="}],"memo":""}} +{"tx": {"msg":[{"@type":"/vm.m_call","caller":"g1qpymzwx4l4cy6cerdyajp9ksvjsf20rk5y9rtt","send":"200000000ugnot","pkg_path":"gno.land/r/demo/users","func":"Register","args":["","zo_oma","Love is the encryption key\u003c3"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"A6yg5/iiktruezVw5vZJwLlGwyrvw8RlqOToTRMWXkE2"},"signature":"GGp+bVL2eEvKecPqgcULSABYOSnSMnJzfIsR8ZIRER1GGX/fOiCReX4WKMrGLVROJVfbLQkDRwvhS4TLHlSoSQ=="}],"memo":""}} +{"tx": {"msg":[{"@type":"/vm.m_call","caller":"g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq","send":"200000000ugnot","pkg_path":"gno.land/r/demo/users","func":"Register","args":["","manfred","https://github.com/moul"]}],"fee":{"gas_wanted":"2000000","gas_fee":"200000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AnK+a6mcFDjY6b/v6p7r8QFW1M1PgIoQxBgrwOoyY7v3"},"signature":"9CWeNbKx+hEL+RdHplAVAFntcrAVx5mK9tMqoywuHVoreH844n3yOxddQrGfBk6T2tMBmNWakERRqWZfS+bYAQ=="}],"memo":""}} +{"tx": {"msg":[{"@type":"/vm.m_call","caller":"g1fj9jccm3zjnqspq7lp2g7lj4czyfq0s35600g9","send":"200000000ugnot","pkg_path":"gno.land/r/demo/users","func":"Register","args":["","piupiu","@piux2"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"Ar68lqbU2YC63fbMcYUtJhYO3/66APM/EqF7m0nUjGyz"},"signature":"pTUpP0d/XlfVe3TH1hlaoLhKadzIKG1gtQ/Ueuat72p+659RWRea58Z0mk6GgPE/EeTbhMEY45zufevBdGJVoQ=="}],"memo":""}} +{"tx": {"msg":[{"@type":"/vm.m_call","caller":"g1ds24jj9kqjcskd0gzu24r9e4n62ggye230zuv5","send":"","pkg_path":"gno.land/r/demo/users","func":"Register","args":["g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq","anarcher","https://twitter.com/anarcher"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AjpLbKdQeH+yB/1OCB148l5GlRRrXma71hdA8EES3H7f"},"signature":"pf5xm8oWIQIOEwSGw4icPmynLXb1P1HxKfjeh8UStU1mlIBPKa7yppeIMPpAflC0o2zjFR7Axe7CimAebm3BHg=="}],"memo":""}} +{"tx": {"msg":[{"@type":"/vm.m_call","caller":"g15gdm49ktawvkrl88jadqpucng37yxutucuwaef","send":"200000000ugnot","pkg_path":"gno.land/r/demo/users","func":"Register","args":["","ideamour","\u003c3"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AhClx4AsDuX3DNCPxhDwWnrfd4MIZmxJE4vt47ClVvT2"},"signature":"IQe64af878k6HjLDqIJeg27GXAVF6xS+96cDe2jMlxNV6+8sOcuUctp0GiWVnYfN4tpthC6d4WhBo+VlpHqkbg=="}],"memo":""}} +{"tx": {"msg":[{"@type":"/vm.m_call","caller":"g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj","send":"","pkg_path":"gno.land/r/demo/boards","func":"CreateBoard","args":["testboard"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"A+FhNtsXHjLfSJk1lB8FbiL4mGPjc50Kt81J7EKDnJ2y"},"signature":"vzlSxEFh5jOkaSdv3rsV91v/OJKEF2qSuoCpri1u5tRWq62T7xr3KHRCF5qFnn4aQX/yE8g8f/Y//WPOCUGhJw=="}],"memo":""}} +{"tx": {"msg":[{"@type":"/vm.m_call","caller":"g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj","send":"","pkg_path":"gno.land/r/demo/boards","func":"CreateThread","args":["1","Hello World","This is a demo of Gno smart contract programming. This document was\nconstructed by Gno onto a smart contract hosted on the data Realm \nname [\"gno.land/r/demo/boards\"](https://gno.land/r/demo/boards/)\n([github](https://github.com/gnolang/gno/tree/master/examples/gno.land/r/demo/boards)).\n\n## Starting the `gnoland` node node/validator.\n\nNOTE: Where you see `--remote %%REMOTE%%` here, that flag can be replaced\nwith `--remote localhost:26657` for local testnets.\n\n### build gnoland.\n\n```bash\ngit clone git@github.com:gnolang/gno.git\ncd ./gno\nmake \n```\n\n### add test account.\n\n```bash\n./build/gnokey add test1 --recover\n```\n\nUse this mnemonic:\n\u003e source bonus chronic canvas draft south burst lottery vacant surface solve popular case indicate oppose farm nothing bullet exhibit title speed wink action roast\n\n### start gnoland validator node.\n\n```bash\n./build/gnoland\n```\n\n(This can be reset with `make reset`).\n\n### start gnoland web server (optional).\n\n```bash\ngo run ./gnoland/website\n```\n\n## Signing and broadcasting transactions.\n\n### publish the \"gno.land/p/demo/avl\" package.\n\n```bash\n./build/gnokey maketx addpkg test1 --pkgpath \"gno.land/p/demo/avl\" --pkgdir \"examples/gno.land/p/demo/avl\" --deposit 100ugnot --gas-fee 1ugnot --gas-wanted 2000000 \u003e addpkg.avl.unsigned.txt\n./build/gnokey query \"auth/accounts/g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5\"\n./build/gnokey sign test1 --txpath addpkg.avl.unsigned.txt --chainid \"%%CHAINID%%\" --number 0 --sequence 0 \u003e addpkg.avl.signed.txt\n./build/gnokey broadcast addpkg.avl.signed.txt --remote %%REMOTE%%\n```\n\n### publish the \"gno.land/r/demo/boards\" realm package.\n\n```bash\n./build/gnokey maketx addpkg test1 --pkgpath \"gno.land/r/demo/boards\" --pkgdir \"examples/gno.land/r/demo/boards\" --deposit 100ugnot --gas-fee 1ugnot --gas-wanted 300000000 \u003e addpkg.boards.unsigned.txt\n./build/gnokey sign test1 --txpath addpkg.boards.unsigned.txt --chainid \"%%CHAINID%%\" --number 0 --sequence 1 \u003e addpkg.boards.signed.txt\n./build/gnokey broadcast addpkg.boards.signed.txt --remote %%REMOTE%%\n```\n\n### create a board with a smart contract call.\n\n```bash\n./build/gnokey maketx call test1 --pkgpath \"gno.land/r/demo/boards\" --func CreateBoard --args \"testboard\" --gas-fee 1ugnot --gas-wanted 2000000 \u003e createboard.unsigned.txt\n./build/gnokey sign test1 --txpath createboard.unsigned.txt --chainid \"%%CHAINID%%\" --number 0 --sequence 2 \u003e createboard.signed.txt\n./build/gnokey broadcast createboard.signed.txt --remote %%REMOTE%%\n```\nNext, query for the permanent board ID by querying (you need this to create a new post):\n\n```bash\n./build/gnokey query \"vm/qeval\" --data \"gno.land/r/demo/boards.GetBoardIDFromName(\\\"testboard\\\")\"\n```\n\n### create a post of a board with a smart contract call.\n\n```bash\n./build/gnokey maketx call test1 --pkgpath \"gno.land/r/demo/boards\" --func CreatePost --args 1 --args \"Hello World\" --args#file \"./examples/gno.land/r/demo/boards/README.md\" --gas-fee 1ugnot --gas-wanted 2000000 \u003e createpost.unsigned.txt\n./build/gnokey sign test1 --txpath createpost.unsigned.txt --chainid \"%%CHAINID%%\" --number 0 --sequence 3 \u003e createpost.signed.txt\n./build/gnokey broadcast createpost.signed.txt --remote %%REMOTE%%\n```\n\n### create a comment to a post.\n\n```bash\n./build/gnokey maketx call test1 --pkgpath \"gno.land/r/demo/boards\" --func CreateReply --args 1 --args 1 --args \"A comment\" --gas-fee 1ugnot --gas-wanted 2000000 \u003e createcomment.unsigned.txt\n./build/gnokey sign test1 --txpath createcomment.unsigned.txt --chainid \"%%CHAINID%%\" --number 0 --sequence 4 \u003e createcomment.signed.txt\n./build/gnokey broadcast createcomment.signed.txt --remote %%REMOTE%%\n```\n\n```bash\n./build/gnokey query \"vm/qrender\" --data \"gno.land/r/demo/boards:testboard/1\"\n```\n\n### render page with optional path expression.\n\nThe contents of `https://gno.land/r/demo/boards:` and `https://gno.land/r/demo/boards:testboard` are rendered by calling\nthe `Render(path string)` function like so:\n\n```bash\n./build/gnokey query \"vm/qrender\" --data \"gno.land/r/demo/boards:testboard\"\n```\n"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"A+FhNtsXHjLfSJk1lB8FbiL4mGPjc50Kt81J7EKDnJ2y"},"signature":"V43B1waFxhzheW9TfmCpjLdrC4dC1yjUGES5y3J6QsNar6hRpNz4G1thzWmWK7xXhg8u1PCIpxLxGczKQYhuPw=="}],"memo":""}} +{"tx": {"msg":[{"@type":"/vm.m_call","caller":"g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj","send":"","pkg_path":"gno.land/r/demo/boards","func":"CreateThread","args":["1","NFT example","NFT's are all the rage these days, for various reasons.\n\nI read over EIP-721 which appears to be the de-facto NFT standard on Ethereum. Then, made a sample implementation of EIP-721 (let's here called GRC-721). The implementation isn't complete, but it demonstrates the main functionality.\n\n - [EIP-721](https://eips.ethereum.org/EIPS/eip-721)\n - [gno.land/r/demo/nft/nft.gno](https://gno.land/r/demo/nft/nft.gno)\n - [zrealm_nft3.gno test](https://github.com/gnolang/gno/blob/master/examples/gno.land/r/demo/nft/z_3_filetest.gno)\n\nIn short, this demonstrates how to implement Ethereum contract interfaces in gno.land; by using only standard Go language features.\n\nPlease leave a comment ([guide](https://gno.land/r/demo/boards:testboard/1)).\n"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"A+FhNtsXHjLfSJk1lB8FbiL4mGPjc50Kt81J7EKDnJ2y"},"signature":"ZXfrTiHxPFQL8uSm+Tv7WXIHPMca9okhm94RAlC6YgNbB1VHQYYpoP4w+cnL3YskVzGrOZxensXa9CAZ+cNNeg=="}],"memo":""}} +{"tx": {"msg":[{"@type":"/vm.m_call","caller":"g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj","send":"","pkg_path":"gno.land/r/demo/boards","func":"CreateThread","args":["1","Simple echo example with coins","This is a simple test realm contract that demonstrates how to use the banker.\n\nSee [gno.land/r/demo/banktest/banktest.gno](/r/demo/banktest/banktest.gno) to see the original contract code.\n\nThis article will go through each line to explain how it works.\n\n```go\npackage banktest\n```\n\nThis package is locally named \"banktest\" (could be anything).\n\n```go\nimport (\n\t\"std\"\n)\n```\n\nThe \"std\" package is defined by the gno code in stdlibs/std/. \u003c/br\u003e\nSelf explanatory; and you'll see more usage from std later.\n\n```go\ntype activity struct {\n\tcaller std.Address\n\tsent std.Coins\n\treturned std.Coins\n\ttime std.Time\n}\n\nfunc (act *activity) String() string {\n\treturn act.caller.String() + \" \" +\n\t\tact.sent.String() + \" sent, \" +\n\t\tact.returned.String() + \" returned, at \" +\n\t\tstd.FormatTimestamp(act.time, \"2006-01-02 3:04pm MST\")\n}\n\nvar latest [10]*activity\n```\n\nThis is just maintaining a list of recent activity to this contract.\nNotice that the \"latest\" variable is defined \"globally\" within\nthe context of the realm with path \"gno.land/r/demo/banktest\".\n\nThis means that calls to functions defined within this package\nare encapsulated within this \"data realm\", where the data is \nmutated based on transactions that can potentially cross many\nrealm and non-realm packge boundaries (in the call stack).\n\n```go\n// Deposit will take the coins (to the realm's pkgaddr) or return them to user.\nfunc Deposit(returnDenom string, returnAmount int64) string {\n\tstd.AssertOriginCall()\n\tcaller := std.GetOrigCaller()\n\tsend := std.Coins{{returnDenom, returnAmount}}\n```\n\nThis is the beginning of the definition of the contract function named\n\"Deposit\". `std.AssertOriginCall() asserts that this function was called by a\ngno transactional Message. The caller is the user who signed off on this\ntransactional message. Send is the amount of deposit sent along with this\nmessage.\n\n```go\n\t// record activity\n\tact := \u0026activity{\n\t\tcaller: caller,\n\t\tsent: std.GetOrigSend(),\n\t\treturned: send,\n\t\ttime: std.GetTimestamp(),\n\t}\n\tfor i := len(latest) - 2; i \u003e= 0; i-- {\n\t\tlatest[i+1] = latest[i] // shift by +1.\n\t}\n\tlatest[0] = act\n```\n\nUpdating the \"latest\" array for viewing at gno.land/r/demo/banktest: (w/ trailing colon).\n\n```go\n\t// return if any.\n\tif returnAmount \u003e 0 {\n```\n\nIf the user requested the return of coins...\n\n```go\n\t\tbanker := std.GetBanker(std.BankerTypeOrigSend)\n```\n\nuse a std.Banker instance to return any deposited coins to the original sender.\n\n```go\n\t\tpkgaddr := std.GetOrigPkgAddr()\n\t\t// TODO: use std.Coins constructors, this isn't generally safe.\n\t\tbanker.SendCoins(pkgaddr, caller, send)\n\t\treturn \"returned!\"\n```\n\nNotice that each realm package has an associated Cosmos address.\n\n\nFinally, the results are rendered via an ABCI query call when you visit [/r/demo/banktest:](/r/demo/banktest:).\n\n```go\nfunc Render(path string) string {\n\t// get realm coins.\n\tbanker := std.GetBanker(std.BankerTypeReadonly)\n\tcoins := banker.GetCoins(std.GetOrigPkgAddr())\n\n\t// render\n\tres := \"\"\n\tres += \"## recent activity\\n\"\n\tres += \"\\n\"\n\tfor _, act := range latest {\n\t\tif act == nil {\n\t\t\tbreak\n\t\t}\n\t\tres += \" * \" + act.String() + \"\\n\"\n\t}\n\tres += \"\\n\"\n\tres += \"## total deposits\\n\"\n\tres += coins.String()\n\treturn res\n}\n```\n\nYou can call this contract yourself, by vistiing [/r/demo/banktest](/r/demo/banktest) and the [quickstart guide](/r/demo/boards:testboard/4).\n"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"A+FhNtsXHjLfSJk1lB8FbiL4mGPjc50Kt81J7EKDnJ2y"},"signature":"iZX/llZlNTdZMLv1goCTgK2bWqzT8enlTq56wMTCpVxJGA0BTvuEM5Nnt9vrnlG6Taqj2GuTrmEnJBkDFTmt9g=="}],"memo":""}} +{"tx": {"msg":[{"@type":"/vm.m_call","caller":"g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj","send":"","pkg_path":"gno.land/r/demo/boards","func":"CreateThread","args":["1","TASK: Describe in your words","Describe in an essay (250+ words), on your favorite medium, why you are interested in gno.land and gnolang.\n\nReply here with a URL link to your written piece as a comment, for rewards.\n"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AmG6kzznyo1uNqWPAYU6wDpsmzQKDaEOrVRaZ08vOyX0"},"signature":"4HBNtrta8HdeHj4JTN56PBTRK8GOe31NMRRXDiyYtjozuyRdWfOGEsGjGgHWcoBUJq6DepBgD4FetdqfhZ6TNQ=="}],"memo":""}} +{"tx": {"msg":[{"@type":"/vm.m_call","caller":"g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq","send":"","pkg_path":"gno.land/r/demo/boards","func":"CreateThread","args":["1","Getting Started","This is a demo of Gno smart contract programming. This document was\nconstructed by Gno onto a smart contract hosted on the data Realm\nname [\"gno.land/r/demo/boards\"](https://gno.land/r/demo/boards/)\n([github](https://github.com/gnolang/gno/tree/master/examples/gno.land/r/demo/boards)).\n\n\n\n## Build `gnokey`, create your account, and interact with Gno.\n\nNOTE: Where you see `--remote %%REMOTE%%` here, that flag can be replaced\nwith `--remote localhost:26657` for local testnets.\n\n### Build `gnokey`.\n\n```bash\ngit clone git@github.com:gnolang/gno.git\ncd ./gno\nmake\n```\n\n### Generate a seed/mnemonic code.\n\n```bash\n./build/gnokey generate\n```\n\nNOTE: You can generate 24 words with any good bip39 generator.\n\n### Create a new account using your mnemonic.\n\n```bash\n./build/gnokey add KEYNAME --recover\n```\n\nNOTE: `KEYNAME` is your key identifier, and should be changed.\n\n### Verify that you can see your account locally.\n\n```bash\n./build/gnokey list\n```\n\n## Interact with the blockchain:\n\n### Get your current balance, account number, and sequence number.\n\n```bash\n./build/gnokey query auth/accounts/ACCOUNT_ADDR --remote %%REMOTE%%\n```\n\nNOTE: you can retrieve your `ACCOUNT_ADDR` with `./build/gnokey list`.\n\n### Acquire testnet tokens using the official faucet.\n\nGo to https://gno.land/faucet\n\n### Create a board with a smart contract call.\n\nNOTE: `BOARDNAME` will be the slug of the board, and should be changed.\n\n```bash\n./build/gnokey maketx call KEYNAME --pkgpath \"gno.land/r/demo/boards\" --func \"CreateBoard\" --args \"BOARDNAME\" --gas-fee \"1000000ugnot\" --gas-wanted \"2000000\" --broadcast=true --chainid %%CHAINID%% --remote %%REMOTE%%\n```\n\nInteractive documentation: https://gno.land/r/demo/boards?help\u0026__func=CreateBoard\n\nNext, query for the permanent board ID by querying (you need this to create a new post):\n\n```bash\n./build/gnokey query \"vm/qeval\" --data \"gno.land/r/demo/boards.GetBoardIDFromName(\\\"BOARDNAME\\\")\" --remote %%REMOTE%%\n```\n\n### Create a post of a board with a smart contract call.\n\nNOTE: If a board was created successfully, your SEQUENCE_NUMBER would have increased.\n\n```bash\n./build/gnokey maketx call KEYNAME --pkgpath \"gno.land/r/demo/boards\" --func \"CreateThread\" --args BOARD_ID --args \"Hello gno.land\" --args\\#file \"./examples/gno.land/r/demo/boards/example_post.md\" --gas-fee 1000000ugnot --gas-wanted 2000000 --broadcast=true --chainid %%CHAINID%% --remote %%REMOTE%%\n```\n\nInteractive documentation: https://gno.land/r/demo/boards?help\u0026__func=CreateThread\n\n### Create a comment to a post.\n\n```bash\n./build/gnokey maketx call KEYNAME --pkgpath \"gno.land/r/demo/boards\" --func \"CreateReply\" --args \"BOARD_ID\" --args \"1\" --args \"1\" --args \"Nice to meet you too.\" --gas-fee 1000000ugnot --gas-wanted 2000000 --broadcast=true --chainid %%CHAINID%% --remote %%REMOTE%%\n```\n\nInteractive documentation: https://gno.land/r/demo/boards?help\u0026__func=CreateReply\n\n```bash\n./build/gnokey query \"vm/qrender\" --data \"gno.land/r/demo/boards:BOARDNAME/1\" --remote %%REMOTE%%\n```\n\n### Render page with optional path expression.\n\nThe contents of `https://gno.land/r/demo/boards:` and `https://gno.land/r/demo/boards:gnolang` are rendered by calling\nthe `Render(path string)` function like so:\n\n```bash\n./build/gnokey query \"vm/qrender\" --data \"gno.land/r/demo/boards:gnolang\"\n```\n\n## Starting a local `gnoland` node:\n\n### Add test account.\n\n```bash\n./build/gnokey add test1 --recover\n```\n\nUse this mneonic:\n\u003e source bonus chronic canvas draft south burst lottery vacant surface solve popular case indicate oppose farm nothing bullet exhibit title speed wink action roast\n\n### Start `gnoland` node.\n\n```bash\n./build/gnoland\n```\n\nNOTE: This can be reset with `make reset`\n\n### Publish the \"gno.land/p/demo/avl\" package.\n\n```bash\n./build/gnokey maketx addpkg test1 --pkgpath \"gno.land/p/demo/avl\" --pkgdir \"examples/gno.land/p/demo/avl\" --deposit 100000000ugnot --gas-fee 1000000ugnot --gas-wanted 2000000 --broadcast=true --chainid %%CHAINID%% --remote localhost:26657\n```\n\n### Publish the \"gno.land/r/demo/boards\" realm package.\n\n```bash\n./build/gnokey maketx addpkg test1 --pkgpath \"gno.land/r/demo/boards\" --pkgdir \"examples/gno.land/r/demo/boards\" --deposit 100000000ugnot --gas-fee 1000000ugnot --gas-wanted 300000000 --broadcast=true --chainid %%CHAINID%% --remote localhost:26657\n```\n"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AnK+a6mcFDjY6b/v6p7r8QFW1M1PgIoQxBgrwOoyY7v3"},"signature":"sHjOGXZEi9wt2FSXFHmkDDoVQyepvFHKRDDU0zgedHYnCYPx5/YndyihsDD5Y2Z7/RgNYBh4JlJwDMGFNStzBQ=="}],"memo":""}} +{"tx": {"msg":[{"@type":"/vm.m_call","caller":"g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq","send":"","pkg_path":"gno.land/r/gnoland/blog","func":"ModAddPost","args":["post1","First post","Lorem Ipsum","2022-05-20T13:17:22Z","","tag1,tag2"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AnK+a6mcFDjY6b/v6p7r8QFW1M1PgIoQxBgrwOoyY7v3"},"signature":"sHjOGXZEi9wt2FSXFHmkDDoVQyepvFHKRDDU0zgedHYnCYPx5/YndyihsDD5Y2Z7/RgNYBh4JlJwDMGFNStzBQ=="}],"memo":""}} +{"tx": {"msg":[{"@type":"/vm.m_call","caller":"g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq","send":"","pkg_path":"gno.land/r/gnoland/blog","func":"ModAddPost","args":["post2","Second post","Lorem Ipsum","2022-05-20T13:17:23Z","","tag1,tag3"]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AnK+a6mcFDjY6b/v6p7r8QFW1M1PgIoQxBgrwOoyY7v3"},"signature":"sHjOGXZEi9wt2FSXFHmkDDoVQyepvFHKRDDU0zgedHYnCYPx5/YndyihsDD5Y2Z7/RgNYBh4JlJwDMGFNStzBQ=="}],"memo":""}} diff --git a/gno.land/pkg/gnoclient/client_test.go b/gno.land/pkg/gnoclient/client_test.go index b7eb21837a7..1f8563d34fe 100644 --- a/gno.land/pkg/gnoclient/client_test.go +++ b/gno.land/pkg/gnoclient/client_test.go @@ -8,6 +8,7 @@ import ( "github.com/gnolang/gno/gno.land/pkg/gnoland/ugnot" "github.com/gnolang/gno/gno.land/pkg/sdk/vm" + "github.com/gnolang/gno/gnovm" abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" ctypes "github.com/gnolang/gno/tm2/pkg/bft/rpc/core/types" "github.com/gnolang/gno/tm2/pkg/bft/types" @@ -17,7 +18,7 @@ import ( "github.com/gnolang/gno/tm2/pkg/std" ) -var testGasFee = ugnot.ValueString(10000) +var testGasFee = ugnot.ValueString(10_000) func TestRender(t *testing.T) { t.Parallel() @@ -652,8 +653,8 @@ func main() { msg := vm.MsgRun{ Caller: caller.GetAddress(), - Package: &std.MemPackage{ - Files: []*std.MemFile{ + Package: &gnovm.MemPackage{ + Files: []*gnovm.MemFile{ { Name: "main.gno", Body: fileBody, @@ -729,8 +730,8 @@ func main() { msg1 := vm.MsgRun{ Caller: caller.GetAddress(), - Package: &std.MemPackage{ - Files: []*std.MemFile{ + Package: &gnovm.MemPackage{ + Files: []*gnovm.MemFile{ { Name: "main1.gno", Body: fileBody, @@ -742,8 +743,8 @@ func main() { msg2 := vm.MsgRun{ Caller: caller.GetAddress(), - Package: &std.MemPackage{ - Files: []*std.MemFile{ + Package: &gnovm.MemPackage{ + Files: []*gnovm.MemFile{ { Name: "main2.gno", Body: fileBody, @@ -794,10 +795,10 @@ func TestRunErrors(t *testing.T) { msgs: []vm.MsgRun{ { Caller: mockAddress, - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: "", Path: "", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "file1.gno", Body: "", @@ -841,10 +842,10 @@ func TestRunErrors(t *testing.T) { msgs: []vm.MsgRun{ { Caller: mockAddress, - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: "", Path: "", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "file1.gno", Body: "", @@ -872,10 +873,10 @@ func TestRunErrors(t *testing.T) { msgs: []vm.MsgRun{ { Caller: mockAddress, - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: "", Path: "", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "file1.gno", Body: "", @@ -903,10 +904,10 @@ func TestRunErrors(t *testing.T) { msgs: []vm.MsgRun{ { Caller: mockAddress, - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: "", Path: "", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "file1.gno", Body: "", @@ -943,7 +944,7 @@ func TestRunErrors(t *testing.T) { msgs: []vm.MsgRun{ { Caller: mockAddress, - Package: &std.MemPackage{Name: "", Path: " "}, + Package: &gnovm.MemPackage{Name: "", Path: " "}, Send: nil, }, }, @@ -993,10 +994,10 @@ func TestAddPackageErrors(t *testing.T) { msgs: []vm.MsgAddPackage{ { Creator: mockAddress, - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: "", Path: "", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "file1.gno", Body: "", @@ -1040,10 +1041,10 @@ func TestAddPackageErrors(t *testing.T) { msgs: []vm.MsgAddPackage{ { Creator: mockAddress, - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: "", Path: "", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "file1.gno", Body: "", @@ -1071,10 +1072,10 @@ func TestAddPackageErrors(t *testing.T) { msgs: []vm.MsgAddPackage{ { Creator: mockAddress, - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: "", Path: "", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "file1.gno", Body: "", @@ -1102,10 +1103,10 @@ func TestAddPackageErrors(t *testing.T) { msgs: []vm.MsgAddPackage{ { Creator: mockAddress, - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: "", Path: "", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "file1.gno", Body: "", @@ -1142,7 +1143,7 @@ func TestAddPackageErrors(t *testing.T) { msgs: []vm.MsgAddPackage{ { Creator: mockAddress, - Package: &std.MemPackage{Name: "", Path: ""}, + Package: &gnovm.MemPackage{Name: "", Path: ""}, Deposit: nil, }, }, diff --git a/gno.land/pkg/gnoclient/integration_test.go b/gno.land/pkg/gnoclient/integration_test.go index ea068e0680b..0a06eb4756a 100644 --- a/gno.land/pkg/gnoclient/integration_test.go +++ b/gno.land/pkg/gnoclient/integration_test.go @@ -5,17 +5,17 @@ import ( "github.com/gnolang/gno/gnovm/pkg/gnolang" - "github.com/gnolang/gno/tm2/pkg/sdk/bank" - "github.com/gnolang/gno/tm2/pkg/std" - "github.com/gnolang/gno/gno.land/pkg/gnoland/ugnot" "github.com/gnolang/gno/gno.land/pkg/integration" "github.com/gnolang/gno/gno.land/pkg/sdk/vm" + "github.com/gnolang/gno/gnovm" "github.com/gnolang/gno/gnovm/pkg/gnoenv" rpcclient "github.com/gnolang/gno/tm2/pkg/bft/rpc/client" "github.com/gnolang/gno/tm2/pkg/crypto" "github.com/gnolang/gno/tm2/pkg/crypto/keys" "github.com/gnolang/gno/tm2/pkg/log" + "github.com/gnolang/gno/tm2/pkg/sdk/bank" + "github.com/gnolang/gno/tm2/pkg/std" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -316,9 +316,9 @@ func main() { // Make Msg configs msg := vm.MsgRun{ Caller: caller.GetAddress(), - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: "main", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "main.gno", Body: fileBody, @@ -359,7 +359,7 @@ func TestRunMultiple_Integration(t *testing.T) { // Make Tx config baseCfg := BaseTxCfg{ GasFee: ugnot.ValueString(10000), - GasWanted: 8000000, + GasWanted: 13000000, AccountNumber: 0, SequenceNumber: 0, Memo: "", @@ -393,9 +393,9 @@ func main() { // Make Msg configs msg1 := vm.MsgRun{ Caller: caller.GetAddress(), - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: "main", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "main.gno", Body: fileBody1, @@ -406,9 +406,9 @@ func main() { } msg2 := vm.MsgRun{ Caller: caller.GetAddress(), - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: "main", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "main.gno", Body: fileBody2, @@ -474,10 +474,10 @@ func Echo(str string) string { // Make Msg config msg := vm.MsgAddPackage{ Creator: caller.GetAddress(), - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: "echo", Path: deploymentPath, - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: fileName, Body: body, @@ -556,7 +556,7 @@ func Echo(str string) string { body2 := `package hello func Hello(str string) string { - return "Hello " + str + "!" + return "Hello " + str + "!" }` caller, err := client.Signer.Info() @@ -564,10 +564,10 @@ func Hello(str string) string { msg1 := vm.MsgAddPackage{ Creator: caller.GetAddress(), - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: "echo", Path: deploymentPath1, - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "echo.gno", Body: body1, @@ -579,10 +579,10 @@ func Hello(str string) string { msg2 := vm.MsgAddPackage{ Creator: caller.GetAddress(), - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: "hello", Path: deploymentPath2, - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "gno.mod", Body: "module gno.land/p/demo/integration/test/hello", diff --git a/gno.land/pkg/gnoland/app.go b/gno.land/pkg/gnoland/app.go index 2380658c6e9..ff1b5a88fea 100644 --- a/gno.land/pkg/gnoland/app.go +++ b/gno.land/pkg/gnoland/app.go @@ -12,6 +12,7 @@ import ( "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" + bft "github.com/gnolang/gno/tm2/pkg/bft/types" "github.com/gnolang/gno/tm2/pkg/crypto" dbm "github.com/gnolang/gno/tm2/pkg/db" "github.com/gnolang/gno/tm2/pkg/events" @@ -19,6 +20,7 @@ import ( "github.com/gnolang/gno/tm2/pkg/sdk" "github.com/gnolang/gno/tm2/pkg/sdk/auth" "github.com/gnolang/gno/tm2/pkg/sdk/bank" + "github.com/gnolang/gno/tm2/pkg/sdk/params" "github.com/gnolang/gno/tm2/pkg/std" "github.com/gnolang/gno/tm2/pkg/store" "github.com/gnolang/gno/tm2/pkg/store/dbadapter" @@ -34,7 +36,6 @@ type AppOptions struct { DB dbm.DB // required Logger *slog.Logger // required EventSwitch events.EventSwitch // required - MaxCycles int64 // hard limit for cycles in GnoVM InitChainerConfig // options related to InitChainer } @@ -88,12 +89,13 @@ func NewAppWithOptions(cfg *AppOptions) (abci.Application, error) { // Construct keepers. acctKpr := auth.NewAccountKeeper(mainKey, ProtoGnoAccount) bankKpr := bank.NewBankKeeper(acctKpr) - vmk := vm.NewVMKeeper(baseKey, mainKey, acctKpr, bankKpr, cfg.MaxCycles) + paramsKpr := params.NewParamsKeeper(mainKey, "vm") + vmk := vm.NewVMKeeper(baseKey, mainKey, acctKpr, bankKpr, paramsKpr) // Set InitChainer icc := cfg.InitChainerConfig icc.baseApp = baseApp - icc.acctKpr, icc.bankKpr, icc.vmKpr = acctKpr, bankKpr, vmk + icc.acctKpr, icc.bankKpr, icc.vmKpr, icc.paramsKpr = acctKpr, bankKpr, vmk, paramsKpr baseApp.SetInitChainer(icc.InitChainer) // Set AnteHandler @@ -148,6 +150,7 @@ func NewAppWithOptions(cfg *AppOptions) (abci.Application, error) { // Set a handler Route. baseApp.Router().AddRoute("auth", auth.NewHandler(acctKpr)) baseApp.Router().AddRoute("bank", bank.NewHandler(bankKpr)) + baseApp.Router().AddRoute("params", params.NewHandler(paramsKpr)) baseApp.Router().AddRoute("vm", vm.NewHandler(vmk)) // Load latest version. @@ -225,10 +228,11 @@ type InitChainerConfig struct { // These fields are passed directly by NewAppWithOptions, and should not be // configurable by end-users. - baseApp *sdk.BaseApp - vmKpr vm.VMKeeperI - acctKpr auth.AccountKeeperI - bankKpr bank.BankKeeperI + baseApp *sdk.BaseApp + vmKpr vm.VMKeeperI + acctKpr auth.AccountKeeperI + bankKpr bank.BankKeeperI + paramsKpr params.ParamsKeeperI } // InitChainer is the function that can be used as a [sdk.InitChainer]. @@ -298,9 +302,31 @@ func (cfg InitChainerConfig) loadAppState(ctx sdk.Context, appState any) ([]abci } txResponses := make([]abci.ResponseDeliverTx, 0, len(state.Txs)) + // Run genesis txs for _, tx := range state.Txs { - res := cfg.baseApp.Deliver(tx) + var ( + stdTx = tx.Tx + metadata = tx.Metadata + + ctxFn sdk.ContextFn + ) + + // Check if there is metadata associated with the tx + if metadata != nil { + // Create a custom context modifier + ctxFn = func(ctx sdk.Context) sdk.Context { + // Create a copy of the header, in + // which only the timestamp information is modified + header := ctx.BlockHeader().(*bft.Header).Copy() + header.Time = time.Unix(metadata.Timestamp, 0) + + // Save the modified header + return ctx.WithBlockHeader(header) + } + } + + res := cfg.baseApp.Deliver(stdTx, ctxFn) if res.IsErr() { ctx.Logger().Error( "Unable to deliver genesis tx", @@ -316,7 +342,7 @@ func (cfg InitChainerConfig) loadAppState(ctx sdk.Context, appState any) ([]abci GasUsed: res.GasUsed, }) - cfg.GenesisTxResultHandler(ctx, tx, res) + cfg.GenesisTxResultHandler(ctx, stdTx, res) } return txResponses, nil } diff --git a/gno.land/pkg/gnoland/app_test.go b/gno.land/pkg/gnoland/app_test.go index 193ff0b0b14..5e4dcb2b449 100644 --- a/gno.land/pkg/gnoland/app_test.go +++ b/gno.land/pkg/gnoland/app_test.go @@ -9,7 +9,8 @@ import ( "time" "github.com/gnolang/gno/gno.land/pkg/sdk/vm" - gnostd "github.com/gnolang/gno/gnovm/stdlibs/std" + "github.com/gnolang/gno/gnovm" + gnostdlibs "github.com/gnolang/gno/gnovm/stdlibs/std" "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" @@ -51,16 +52,18 @@ func TestNewAppWithOptions(t *testing.T) { Amount: []std.Coin{{Amount: 1e15, Denom: "ugnot"}}, }, }, - Txs: []std.Tx{ + Txs: []TxWithMetadata{ { - Msgs: []std.Msg{vm.NewMsgAddPackage(addr, "gno.land/r/demo", []*std.MemFile{ - { - Name: "demo.gno", - Body: "package demo; func Hello() string { return `hello`; }", - }, - })}, - Fee: std.Fee{GasWanted: 1e6, GasFee: std.Coin{Amount: 1e6, Denom: "ugnot"}}, - Signatures: []std.Signature{{}}, // one empty signature + Tx: std.Tx{ + Msgs: []std.Msg{vm.NewMsgAddPackage(addr, "gno.land/r/demo", []*gnovm.MemFile{ + { + Name: "demo.gno", + Body: "package demo; func Hello() string { return `hello`; }", + }, + })}, + Fee: std.Fee{GasWanted: 1e6, GasFee: std.Coin{Amount: 1e6, Denom: "ugnot"}}, + Signatures: []std.Signature{{}}, // one empty signature + }, }, }, }, @@ -205,7 +208,7 @@ func generateValidatorUpdates(t *testing.T, count int) []abci.ValidatorUpdate { for i := 0; i < count; i++ { // Generate a random private key - key := getDummyKey(t) + key := getDummyKey(t).PubKey() validator := abci.ValidatorUpdate{ Address: key.Address(), @@ -219,6 +222,189 @@ func generateValidatorUpdates(t *testing.T, count int) []abci.ValidatorUpdate { return validators } +func createAndSignTx( + t *testing.T, + msgs []std.Msg, + chainID string, + key crypto.PrivKey, +) std.Tx { + t.Helper() + + tx := std.Tx{ + Msgs: msgs, + Fee: std.Fee{ + GasFee: std.NewCoin("ugnot", 2000000), + GasWanted: 10000000, + }, + } + + signBytes, err := tx.GetSignBytes(chainID, 0, 0) + require.NoError(t, err) + + // Sign the tx + signedTx, err := key.Sign(signBytes) + require.NoError(t, err) + + tx.Signatures = []std.Signature{ + { + PubKey: key.PubKey(), + Signature: signedTx, + }, + } + + return tx +} + +func TestInitChainer_MetadataTxs(t *testing.T) { + var ( + currentTimestamp = time.Now() + laterTimestamp = currentTimestamp.Add(10 * 24 * time.Hour) // 10 days + + getMetadataState = func(tx std.Tx, balances []Balance) GnoGenesisState { + return GnoGenesisState{ + // Set the package deployment as the genesis tx + Txs: []TxWithMetadata{ + { + Tx: tx, + Metadata: &GnoTxMetadata{ + Timestamp: laterTimestamp.Unix(), + }, + }, + }, + // Make sure the deployer account has a balance + Balances: balances, + } + } + + getNonMetadataState = func(tx std.Tx, balances []Balance) GnoGenesisState { + return GnoGenesisState{ + Txs: []TxWithMetadata{ + { + Tx: tx, + }, + }, + Balances: balances, + } + } + ) + + testTable := []struct { + name string + genesisTime time.Time + expectedTime time.Time + stateFn func(std.Tx, []Balance) GnoGenesisState + }{ + { + "non-metadata transaction", + currentTimestamp, + currentTimestamp, + getNonMetadataState, + }, + { + "metadata transaction", + currentTimestamp, + laterTimestamp, + getMetadataState, + }, + } + + for _, testCase := range testTable { + t.Run(testCase.name, func(t *testing.T) { + var ( + db = memdb.NewMemDB() + + key = getDummyKey(t) // user account, and genesis deployer + chainID = "test" + + path = "gno.land/r/demo/metadatatx" + body = `package metadatatx + + import "time" + + // Time is initialized on deployment (genesis) + var t time.Time = time.Now() + + // GetT returns the time that was saved from genesis + func GetT() int64 { return t.Unix() } +` + ) + + // Create a fresh app instance + app, err := NewAppWithOptions(TestAppOptions(db)) + require.NoError(t, err) + + // Prepare the deploy transaction + msg := vm.MsgAddPackage{ + Creator: key.PubKey().Address(), + Package: &gnovm.MemPackage{ + Name: "metadatatx", + Path: path, + Files: []*gnovm.MemFile{ + { + Name: "file.gno", + Body: body, + }, + }, + }, + Deposit: nil, + } + + // Create the initial genesis tx + tx := createAndSignTx(t, []std.Msg{msg}, chainID, key) + + // Run the top-level init chain process + app.InitChain(abci.RequestInitChain{ + ChainID: chainID, + Time: testCase.genesisTime, + ConsensusParams: &abci.ConsensusParams{ + Block: defaultBlockParams(), + Validator: &abci.ValidatorParams{ + PubKeyTypeURLs: []string{}, + }, + }, + // Set the package deployment as the genesis tx, + // and make sure the deployer account has a balance + AppState: testCase.stateFn(tx, []Balance{ + { + // Make sure the deployer account has a balance + Address: key.PubKey().Address(), + Amount: std.NewCoins(std.NewCoin("ugnot", 20_000_000)), + }, + }), + }) + + // Prepare the call transaction + callMsg := vm.MsgCall{ + Caller: key.PubKey().Address(), + PkgPath: path, + Func: "GetT", + } + + tx = createAndSignTx(t, []std.Msg{callMsg}, chainID, key) + + // Marshal the transaction to Amino binary + marshalledTx, err := amino.Marshal(tx) + require.NoError(t, err) + + // Execute the call to the "GetT" method + // on the deployed Realm + resp := app.DeliverTx(abci.RequestDeliverTx{ + Tx: marshalledTx, + }) + + require.True(t, resp.IsOK()) + + // Make sure the initialized Realm state is + // the injected context timestamp from the tx metadata + assert.Contains( + t, + string(resp.Data), + fmt.Sprintf("(%d int64)", testCase.expectedTime.Unix()), + ) + }) + } +} + func TestEndBlocker(t *testing.T) { t.Parallel() @@ -308,7 +494,7 @@ func TestEndBlocker(t *testing.T) { c := newCollector[validatorUpdate](mockEventSwitch, noFilter) // Fire a GnoVM event - mockEventSwitch.FireEvent(gnostd.GnoEvent{}) + mockEventSwitch.FireEvent(gnostdlibs.GnoEvent{}) // Create the EndBlocker eb := EndBlocker(c, mockVMKeeper, &mockEndBlockerApp{}) @@ -351,7 +537,7 @@ func TestEndBlocker(t *testing.T) { c := newCollector[validatorUpdate](mockEventSwitch, noFilter) // Fire a GnoVM event - mockEventSwitch.FireEvent(gnostd.GnoEvent{}) + mockEventSwitch.FireEvent(gnostdlibs.GnoEvent{}) // Create the EndBlocker eb := EndBlocker(c, mockVMKeeper, &mockEndBlockerApp{}) @@ -390,7 +576,7 @@ func TestEndBlocker(t *testing.T) { // Construct the GnoVM events vmEvents := make([]abci.Event, 0, len(changes)) for index := range changes { - event := gnostd.GnoEvent{ + event := gnostdlibs.GnoEvent{ Type: validatorAddedEvent, PkgPath: valRealm, } @@ -399,7 +585,7 @@ func TestEndBlocker(t *testing.T) { if index%2 == 0 { changes[index].Power = 0 - event = gnostd.GnoEvent{ + event = gnostdlibs.GnoEvent{ Type: validatorRemovedEvent, PkgPath: valRealm, } diff --git a/gno.land/pkg/gnoland/balance_test.go b/gno.land/pkg/gnoland/balance_test.go index 99a348e9f2f..489384196ad 100644 --- a/gno.land/pkg/gnoland/balance_test.go +++ b/gno.land/pkg/gnoland/balance_test.go @@ -120,7 +120,7 @@ func TestBalances_GetBalancesFromEntries(t *testing.T) { for index, key := range dummyKeys { entries[index] = fmt.Sprintf( "%s=%s", - key.Address().String(), + key.PubKey().Address().String(), ugnot.ValueString(amount.AmountOf(ugnot.Denom)), ) } @@ -131,7 +131,7 @@ func TestBalances_GetBalancesFromEntries(t *testing.T) { // Validate the balance map assert.Len(t, balanceMap, len(dummyKeys)) for _, key := range dummyKeys { - assert.Equal(t, amount, balanceMap[key.Address()].Amount) + assert.Equal(t, amount, balanceMap[key.PubKey().Address()].Amount) } }) @@ -162,7 +162,7 @@ func TestBalances_GetBalancesFromEntries(t *testing.T) { t.Run("malformed balance, invalid amount", func(t *testing.T) { t.Parallel() - dummyKey := getDummyKey(t) + dummyKey := getDummyKey(t).PubKey() balances := []string{ fmt.Sprintf( @@ -194,7 +194,7 @@ func TestBalances_GetBalancesFromSheet(t *testing.T) { for index, key := range dummyKeys { balances[index] = fmt.Sprintf( "%s=%s", - key.Address().String(), + key.PubKey().Address().String(), ugnot.ValueString(amount.AmountOf(ugnot.Denom)), ) } @@ -206,14 +206,14 @@ func TestBalances_GetBalancesFromSheet(t *testing.T) { // Validate the balance map assert.Len(t, balanceMap, len(dummyKeys)) for _, key := range dummyKeys { - assert.Equal(t, amount, balanceMap[key.Address()].Amount) + assert.Equal(t, amount, balanceMap[key.PubKey().Address()].Amount) } }) t.Run("malformed balance, invalid amount", func(t *testing.T) { t.Parallel() - dummyKey := getDummyKey(t) + dummyKey := getDummyKey(t).PubKey() balances := []string{ fmt.Sprintf( @@ -236,9 +236,8 @@ func TestBalances_GetBalancesFromSheet(t *testing.T) { // XXX: this function should probably be exposed somewhere as it's duplicate of // cmd/genesis/... -// getDummyKey generates a random public key, -// and returns the key info -func getDummyKey(t *testing.T) crypto.PubKey { +// getDummyKey generates a random private key +func getDummyKey(t *testing.T) crypto.PrivKey { t.Helper() mnemonic, err := client.GenerateMnemonic(256) @@ -246,14 +245,14 @@ func getDummyKey(t *testing.T) crypto.PubKey { seed := bip39.NewSeed(mnemonic, "") - return generateKeyFromSeed(seed, 0).PubKey() + return generateKeyFromSeed(seed, 0) } // getDummyKeys generates random keys for testing -func getDummyKeys(t *testing.T, count int) []crypto.PubKey { +func getDummyKeys(t *testing.T, count int) []crypto.PrivKey { t.Helper() - dummyKeys := make([]crypto.PubKey, count) + dummyKeys := make([]crypto.PrivKey, count) for i := 0; i < count; i++ { dummyKeys[i] = getDummyKey(t) diff --git a/gno.land/pkg/gnoland/genesis.go b/gno.land/pkg/gnoland/genesis.go index f5f0aa56758..613fba51c37 100644 --- a/gno.land/pkg/gnoland/genesis.go +++ b/gno.land/pkg/gnoland/genesis.go @@ -60,8 +60,9 @@ func LoadGenesisBalancesFile(path string) ([]Balance, error) { // LoadGenesisTxsFile loads genesis transactions from the provided file path. // XXX: Improve the way we generate and load this file -func LoadGenesisTxsFile(path string, chainID string, genesisRemote string) ([]std.Tx, error) { - txs := []std.Tx{} +func LoadGenesisTxsFile(path string, chainID string, genesisRemote string) ([]TxWithMetadata, error) { + txs := make([]TxWithMetadata, 0) + txsBz := osm.MustReadFile(path) txsLines := strings.Split(string(txsBz), "\n") for _, txLine := range txsLines { @@ -73,7 +74,7 @@ func LoadGenesisTxsFile(path string, chainID string, genesisRemote string) ([]st txLine = strings.ReplaceAll(txLine, "%%CHAINID%%", chainID) txLine = strings.ReplaceAll(txLine, "%%REMOTE%%", genesisRemote) - var tx std.Tx + var tx TxWithMetadata if err := amino.UnmarshalJSON([]byte(txLine), &tx); err != nil { return nil, fmt.Errorf("unable to Unmarshall txs file: %w", err) } @@ -86,7 +87,7 @@ func LoadGenesisTxsFile(path string, chainID string, genesisRemote string) ([]st // LoadPackagesFromDir loads gno packages from a directory. // It creates and returns a list of transactions based on these packages. -func LoadPackagesFromDir(dir string, creator bft.Address, fee std.Fee) ([]std.Tx, error) { +func LoadPackagesFromDir(dir string, creator bft.Address, fee std.Fee) ([]TxWithMetadata, error) { // list all packages from target path pkgs, err := gnomod.ListPkgs(dir) if err != nil { @@ -101,14 +102,16 @@ func LoadPackagesFromDir(dir string, creator bft.Address, fee std.Fee) ([]std.Tx // Filter out draft packages. nonDraftPkgs := sortedPkgs.GetNonDraftPkgs() - txs := []std.Tx{} + txs := make([]TxWithMetadata, 0, len(nonDraftPkgs)) for _, pkg := range nonDraftPkgs { tx, err := LoadPackage(pkg, creator, fee, nil) if err != nil { return nil, fmt.Errorf("unable to load package %q: %w", pkg.Dir, err) } - txs = append(txs, tx) + txs = append(txs, TxWithMetadata{ + Tx: tx, + }) } return txs, nil diff --git a/gno.land/pkg/gnoland/node_inmemory.go b/gno.land/pkg/gnoland/node_inmemory.go index d168c955607..9dccbbfac8d 100644 --- a/gno.land/pkg/gnoland/node_inmemory.go +++ b/gno.land/pkg/gnoland/node_inmemory.go @@ -16,15 +16,13 @@ import ( "github.com/gnolang/gno/tm2/pkg/db/memdb" "github.com/gnolang/gno/tm2/pkg/events" "github.com/gnolang/gno/tm2/pkg/p2p" - "github.com/gnolang/gno/tm2/pkg/std" ) type InMemoryNodeConfig struct { - PrivValidator bft.PrivValidator // identity of the validator - Genesis *bft.GenesisDoc - TMConfig *tmcfg.Config - GenesisMaxVMCycles int64 - DB *memdb.MemDB // will be initialized if nil + PrivValidator bft.PrivValidator // identity of the validator + Genesis *bft.GenesisDoc + TMConfig *tmcfg.Config + DB *memdb.MemDB // will be initialized if nil // If StdlibDir not set, then it's filepath.Join(TMConfig.RootDir, "gnovm", "stdlibs") InitChainerConfig @@ -45,7 +43,7 @@ func NewDefaultGenesisConfig(chainid string) *bft.GenesisDoc { }, AppState: &GnoGenesisState{ Balances: []Balance{}, - Txs: []std.Tx{}, + Txs: []TxWithMetadata{}, }, } } @@ -106,7 +104,6 @@ func NewInMemoryNode(logger *slog.Logger, cfg *InMemoryNodeConfig) (*node.Node, // Initialize the application with the provided options gnoApp, err := NewAppWithOptions(&AppOptions{ Logger: logger, - MaxCycles: cfg.GenesisMaxVMCycles, DB: cfg.DB, EventSwitch: evsw, InitChainerConfig: cfg.InitChainerConfig, diff --git a/gno.land/pkg/gnoland/package.go b/gno.land/pkg/gnoland/package.go index fd1afbde136..e4b2449c972 100644 --- a/gno.land/pkg/gnoland/package.go +++ b/gno.land/pkg/gnoland/package.go @@ -11,4 +11,6 @@ var Package = amino.RegisterPackage(amino.NewPackage( ).WithDependencies().WithTypes( &GnoAccount{}, "Account", GnoGenesisState{}, "GenesisState", + TxWithMetadata{}, "TxWithMetadata", + GnoTxMetadata{}, "GnoTxMetadata", )) diff --git a/gno.land/pkg/gnoland/types.go b/gno.land/pkg/gnoland/types.go index 016f3279dbd..6bc4417d8e0 100644 --- a/gno.land/pkg/gnoland/types.go +++ b/gno.land/pkg/gnoland/types.go @@ -1,8 +1,13 @@ package gnoland import ( + "bufio" + "context" "errors" + "fmt" + "os" + "github.com/gnolang/gno/tm2/pkg/amino" "github.com/gnolang/gno/tm2/pkg/std" ) @@ -20,6 +25,61 @@ func ProtoGnoAccount() std.Account { } type GnoGenesisState struct { - Balances []Balance `json:"balances"` - Txs []std.Tx `json:"txs"` + Balances []Balance `json:"balances"` + Txs []TxWithMetadata `json:"txs"` +} + +type TxWithMetadata struct { + Tx std.Tx `json:"tx"` + Metadata *GnoTxMetadata `json:"metadata,omitempty"` +} + +type GnoTxMetadata struct { + Timestamp int64 `json:"timestamp"` +} + +// ReadGenesisTxs reads the genesis txs from the given file path +func ReadGenesisTxs(ctx context.Context, path string) ([]TxWithMetadata, error) { + // Open the txs file + file, loadErr := os.Open(path) + if loadErr != nil { + return nil, fmt.Errorf("unable to open tx file %s: %w", path, loadErr) + } + defer file.Close() + + var ( + txs []TxWithMetadata + + scanner = bufio.NewScanner(file) + ) + + scanner.Buffer(make([]byte, 1_000_000), 2_000_000) + + for scanner.Scan() { + select { + case <-ctx.Done(): + return nil, ctx.Err() + default: + // Parse the amino JSON + var tx TxWithMetadata + if err := amino.UnmarshalJSON(scanner.Bytes(), &tx); err != nil { + return nil, fmt.Errorf( + "unable to unmarshal amino JSON, %w", + err, + ) + } + + txs = append(txs, tx) + } + } + + // Check for scanning errors + if err := scanner.Err(); err != nil { + return nil, fmt.Errorf( + "error encountered while reading file, %w", + err, + ) + } + + return txs, nil } diff --git a/gno.land/pkg/gnoland/types_test.go b/gno.land/pkg/gnoland/types_test.go new file mode 100644 index 00000000000..b4625d6d7d6 --- /dev/null +++ b/gno.land/pkg/gnoland/types_test.go @@ -0,0 +1,131 @@ +package gnoland + +import ( + "context" + "fmt" + "os" + "path/filepath" + "testing" + "time" + + "github.com/gnolang/gno/gno.land/pkg/gnoland/ugnot" + "github.com/gnolang/gno/tm2/pkg/amino" + "github.com/gnolang/gno/tm2/pkg/crypto" + "github.com/gnolang/gno/tm2/pkg/sdk/bank" + "github.com/gnolang/gno/tm2/pkg/std" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// generateTxs generates dummy transactions +func generateTxs(t *testing.T, count int) []TxWithMetadata { + t.Helper() + + txs := make([]TxWithMetadata, count) + + for i := 0; i < count; i++ { + txs[i] = TxWithMetadata{ + Tx: std.Tx{ + Msgs: []std.Msg{ + bank.MsgSend{ + FromAddress: crypto.Address{byte(i)}, + ToAddress: crypto.Address{byte(i)}, + Amount: std.NewCoins(std.NewCoin(ugnot.Denom, 1)), + }, + }, + Fee: std.Fee{ + GasWanted: 10, + GasFee: std.NewCoin(ugnot.Denom, 1000000), + }, + Memo: fmt.Sprintf("tx %d", i), + }, + } + } + + return txs +} + +func TestReadGenesisTxs(t *testing.T) { + t.Parallel() + + createFile := func(path, data string) { + file, err := os.Create(path) + require.NoError(t, err) + + _, err = file.WriteString(data) + require.NoError(t, err) + } + + t.Run("invalid path", func(t *testing.T) { + t.Parallel() + + path := "" // invalid + + ctx, cancelFn := context.WithTimeout(context.Background(), 5*time.Second) + defer cancelFn() + + txs, err := ReadGenesisTxs(ctx, path) + assert.Nil(t, txs) + + assert.Error(t, err) + }) + + t.Run("invalid tx format", func(t *testing.T) { + t.Parallel() + + var ( + dir = t.TempDir() + path = filepath.Join(dir, "txs.jsonl") + ) + + // Create the file + createFile( + path, + "random data", + ) + + ctx, cancelFn := context.WithTimeout(context.Background(), 5*time.Second) + defer cancelFn() + + txs, err := ReadGenesisTxs(ctx, path) + assert.Nil(t, txs) + + assert.Error(t, err) + }) + + t.Run("valid txs", func(t *testing.T) { + t.Parallel() + + var ( + dir = t.TempDir() + path = filepath.Join(dir, "txs.jsonl") + txs = generateTxs(t, 1000) + ) + + // Create the file + file, err := os.Create(path) + require.NoError(t, err) + + // Write the transactions + for _, tx := range txs { + encodedTx, err := amino.MarshalJSON(tx) + require.NoError(t, err) + + _, err = file.WriteString(fmt.Sprintf("%s\n", encodedTx)) + require.NoError(t, err) + } + + ctx, cancelFn := context.WithTimeout(context.Background(), 5*time.Second) + defer cancelFn() + + // Load the transactions + readTxs, err := ReadGenesisTxs(ctx, path) + require.NoError(t, err) + + require.Len(t, readTxs, len(txs)) + + for index, readTx := range readTxs { + assert.Equal(t, txs[index], readTx) + } + }) +} diff --git a/gno.land/pkg/gnoland/vals.go b/gno.land/pkg/gnoland/validators.go similarity index 94% rename from gno.land/pkg/gnoland/vals.go rename to gno.land/pkg/gnoland/validators.go index 1843dff3984..339ebd9dcad 100644 --- a/gno.land/pkg/gnoland/vals.go +++ b/gno.land/pkg/gnoland/validators.go @@ -9,7 +9,7 @@ import ( ) const ( - valRealm = "gno.land/r/sys/validators" + valRealm = "gno.land/r/sys/validators/v2" // XXX: make it configurable from GovDAO valChangesFn = "GetChanges" validatorAddedEvent = "ValidatorAdded" diff --git a/gno.land/pkg/gnoweb/gnoweb.go b/gno.land/pkg/gnoweb/gnoweb.go index 5377ae6a420..ed6271f5afe 100644 --- a/gno.land/pkg/gnoweb/gnoweb.go +++ b/gno.land/pkg/gnoweb/gnoweb.go @@ -13,14 +13,15 @@ import ( "net/url" "os" "path/filepath" + "regexp" "runtime" "strings" "time" + "github.com/gnolang/gno/gnovm" "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/std" "github.com/gorilla/mux" "github.com/gotuna/gotuna" @@ -45,6 +46,7 @@ type Config struct { HelpChainID string HelpRemote string WithAnalytics bool + WithHTML bool } func NewDefaultConfig() Config { @@ -56,6 +58,7 @@ func NewDefaultConfig() Config { HelpChainID: "dev", HelpRemote: "127.0.0.1:26657", WithAnalytics: false, + WithHTML: false, } } @@ -109,6 +112,34 @@ func MakeApp(logger *slog.Logger, cfg Config) gotuna.App { return app } +var ( + inlineCodePattern = regexp.MustCompile("`[^`]*`") + htmlTagPattern = regexp.MustCompile(`<\/?\w+[^>]*?>`) +) + +func sanitizeContent(cfg *Config, content string) string { + if cfg.WithHTML { + return content + } + + placeholders := map[string]string{} + contentWithPlaceholders := inlineCodePattern.ReplaceAllStringFunc(content, func(match string) string { + placeholder := fmt.Sprintf("__GNOMDCODE_%d__", len(placeholders)) + placeholders[placeholder] = match + return placeholder + }) + + sanitizedContent := htmlTagPattern.ReplaceAllString(contentWithPlaceholders, "") + + if len(placeholders) > 0 { + for placeholder, code := range placeholders { + sanitizedContent = strings.ReplaceAll(sanitizedContent, placeholder, code) + } + } + + return sanitizedContent +} + // handlerRealmAlias is used to render official pages from realms. // url is intended to be shorter. // UX is intended to be more minimalistic. @@ -151,7 +182,7 @@ func handlerRealmAlias(logger *slog.Logger, app gotuna.App, cfg *Config, rlmpath tmpl.Set("RealmPath", rlmpath) tmpl.Set("Query", querystr) tmpl.Set("PathLinks", pathLinks) - tmpl.Set("Contents", string(res.Data)) + tmpl.Set("Contents", sanitizeContent(cfg, string(res.Data))) tmpl.Set("Config", cfg) tmpl.Set("IsAlias", true) tmpl.Render(w, r, "realm_render.html", "funcs.html") @@ -339,7 +370,7 @@ func handleRealmRender(logger *slog.Logger, app gotuna.App, cfg *Config, w http. tmpl.Set("RealmPath", rlmpath) tmpl.Set("Query", querystr) tmpl.Set("PathLinks", pathLinks) - tmpl.Set("Contents", string(res.Data)) + tmpl.Set("Contents", sanitizeContent(cfg, string(res.Data))) tmpl.Set("Config", cfg) tmpl.Set("HasReadme", hasReadme) tmpl.Render(w, r, "realm_render.html", "funcs.html") @@ -358,7 +389,7 @@ func handlerPackageFile(logger *slog.Logger, app gotuna.App, cfg *Config) http.H return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) pkgpath := "gno.land/p/" + vars["filepath"] - diruri, filename := std.SplitFilepath(pkgpath) + diruri, filename := gnovm.SplitFilepath(pkgpath) if filename == "" && diruri == pkgpath { // redirect to diruri + "/" http.Redirect(w, r, "/p/"+vars["filepath"]+"/", http.StatusFound) @@ -476,7 +507,7 @@ func handleNotFound(logger *slog.Logger, app gotuna.App, cfg *Config, path strin // decode path for non-ascii characters decodedPath, err := url.PathUnescape(path) if err != nil { - logger.Error("failed to decode path", err) + logger.Error("failed to decode path", "error", err) decodedPath = path } w.WriteHeader(http.StatusNotFound) @@ -491,7 +522,7 @@ 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 { - logger.Error("handler", "error:", err) + logger.Error("handler", "error", err) } // XXX: writeError should return an error page template. diff --git a/gno.land/pkg/gnoweb/views/realm_help.html b/gno.land/pkg/gnoweb/views/realm_help.html index b9c8e119e7a..0a93f786c0d 100644 --- a/gno.land/pkg/gnoweb/views/realm_help.html +++ b/gno.land/pkg/gnoweb/views/realm_help.html @@ -17,7 +17,7 @@
    These are the realm's exposed functions ("public smart contracts").

    - My address: (see `gnokey list`)
    + My address: (see `gnokey list`)


    {{ template "func_specs" . }} diff --git a/gno.land/pkg/integration/testdata/loadpkg_example.txtar b/gno.land/pkg/integration/testdata/loadpkg_example.txtar index d0c95331ff5..9dccd72c8a6 100644 --- a/gno.land/pkg/integration/testdata/loadpkg_example.txtar +++ b/gno.land/pkg/integration/testdata/loadpkg_example.txtar @@ -4,11 +4,11 @@ loadpkg gno.land/p/demo/ufmt ## start a new node gnoland start -gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/importtest -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1 +gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/importtest -gas-fee 1000000ugnot -gas-wanted 4000000 -broadcast -chainid=tendermint_test test1 stdout OK! ## execute Render -gnokey maketx call -pkgpath gno.land/r/importtest -func Render -gas-fee 1000000ugnot -gas-wanted 2000000 -args '' -broadcast -chainid=tendermint_test test1 +gnokey maketx call -pkgpath gno.land/r/importtest -func Render -gas-fee 1000000ugnot -gas-wanted 4000000 -args '' -broadcast -chainid=tendermint_test test1 stdout '("92054" string)' stdout OK! @@ -25,4 +25,3 @@ import ( func Render(_ string) string { return ufmt.Sprintf("%d", 92054) } - diff --git a/gno.land/pkg/integration/testing_integration.go b/gno.land/pkg/integration/testing_integration.go index d3f55cfadf7..56b298e4541 100644 --- a/gno.land/pkg/integration/testing_integration.go +++ b/gno.land/pkg/integration/testing_integration.go @@ -134,7 +134,7 @@ func setupGnolandTestScript(t *testing.T, txtarDir string) testscript.Params { // This genesis will be use when node is started. genesis := &gnoland.GnoGenesisState{ Balances: LoadDefaultGenesisBalanceFile(t, gnoRootDir), - Txs: []std.Tx{}, + Txs: []gnoland.TxWithMetadata{}, } // test1 must be created outside of the loop below because it is already included in genesis so @@ -660,13 +660,13 @@ func (pl *pkgsLoader) SetPatch(replace, with string) { pl.patchs[replace] = with } -func (pl *pkgsLoader) LoadPackages(creator bft.Address, fee std.Fee, deposit std.Coins) ([]std.Tx, error) { +func (pl *pkgsLoader) LoadPackages(creator bft.Address, fee std.Fee, deposit std.Coins) ([]gnoland.TxWithMetadata, error) { pkgslist, err := pl.List().Sort() // sorts packages by their dependencies. if err != nil { return nil, fmt.Errorf("unable to sort packages: %w", err) } - txs := make([]std.Tx, len(pkgslist)) + txs := make([]gnoland.TxWithMetadata, len(pkgslist)) for i, pkg := range pkgslist { tx, err := gnoland.LoadPackage(pkg, creator, fee, deposit) if err != nil { @@ -693,7 +693,9 @@ func (pl *pkgsLoader) LoadPackages(creator bft.Address, fee std.Fee, deposit std } } - txs[i] = tx + txs[i] = gnoland.TxWithMetadata{ + Tx: tx, + } } return txs, nil diff --git a/gno.land/pkg/integration/testing_node.go b/gno.land/pkg/integration/testing_node.go index 5e9e2272049..ef7e05d0787 100644 --- a/gno.land/pkg/integration/testing_node.go +++ b/gno.land/pkg/integration/testing_node.go @@ -54,13 +54,13 @@ func TestingInMemoryNode(t TestingTS, logger *slog.Logger, config *gnoland.InMem // TestingNodeConfig constructs an in-memory node configuration // with default packages and genesis transactions already loaded. // It will return the default creator address of the loaded packages. -func TestingNodeConfig(t TestingTS, gnoroot string, additionalTxs ...std.Tx) (*gnoland.InMemoryNodeConfig, bft.Address) { +func TestingNodeConfig(t TestingTS, gnoroot string, additionalTxs ...gnoland.TxWithMetadata) (*gnoland.InMemoryNodeConfig, bft.Address) { cfg := TestingMinimalNodeConfig(t, gnoroot) creator := crypto.MustAddressFromString(DefaultAccount_Address) // test1 balances := LoadDefaultGenesisBalanceFile(t, gnoroot) - txs := []std.Tx{} + txs := make([]gnoland.TxWithMetadata, 0) txs = append(txs, LoadDefaultPackages(t, creator, gnoroot)...) txs = append(txs, additionalTxs...) @@ -121,13 +121,13 @@ func DefaultTestingGenesisConfig(t TestingTS, gnoroot string, self crypto.PubKey Amount: std.MustParseCoins(ugnot.ValueString(10000000000000)), }, }, - Txs: []std.Tx{}, + Txs: []gnoland.TxWithMetadata{}, }, } } // LoadDefaultPackages loads the default packages for testing using a given creator address and gnoroot directory. -func LoadDefaultPackages(t TestingTS, creator bft.Address, gnoroot string) []std.Tx { +func LoadDefaultPackages(t TestingTS, creator bft.Address, gnoroot string) []gnoland.TxWithMetadata { examplesDir := filepath.Join(gnoroot, "examples") defaultFee := std.NewFee(50000, std.MustParseCoin(ugnot.ValueString(1000000))) @@ -148,7 +148,7 @@ func LoadDefaultGenesisBalanceFile(t TestingTS, gnoroot string) []gnoland.Balanc } // LoadDefaultGenesisTXsFile loads the default genesis transactions file for testing. -func LoadDefaultGenesisTXsFile(t TestingTS, chainid string, gnoroot string) []std.Tx { +func LoadDefaultGenesisTXsFile(t TestingTS, chainid string, gnoroot string) []gnoland.TxWithMetadata { txsFile := filepath.Join(gnoroot, "gno.land", "genesis", "genesis_txs.jsonl") // NOTE: We dont care about giving a correct address here, as it's only for display diff --git a/gno.land/pkg/keyscli/root.go b/gno.land/pkg/keyscli/root.go index 19513fc0de6..c910e01b82c 100644 --- a/gno.land/pkg/keyscli/root.go +++ b/gno.land/pkg/keyscli/root.go @@ -30,6 +30,7 @@ func NewRootCmd(io commands.IO, base client.BaseOptions) *commands.Command { cmd.AddSubCommands( client.NewAddCmd(cfg, io), client.NewDeleteCmd(cfg, io), + client.NewRotateCmd(cfg, io), client.NewGenerateCmd(cfg, io), client.NewExportCmd(cfg, io), client.NewImportCmd(cfg, io), diff --git a/gno.land/pkg/keyscli/run.go b/gno.land/pkg/keyscli/run.go index aa0ee298201..b0e05fe5a84 100644 --- a/gno.land/pkg/keyscli/run.go +++ b/gno.land/pkg/keyscli/run.go @@ -8,6 +8,7 @@ import ( "os" "github.com/gnolang/gno/gno.land/pkg/sdk/vm" + "github.com/gnolang/gno/gnovm" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" "github.com/gnolang/gno/tm2/pkg/amino" "github.com/gnolang/gno/tm2/pkg/commands" @@ -73,13 +74,13 @@ func execMakeRun(cfg *MakeRunCfg, args []string, cmdio commands.IO) error { return errors.Wrap(err, "parsing gas fee coin") } - memPkg := &std.MemPackage{} + memPkg := &gnovm.MemPackage{} if sourcePath == "-" { // stdin data, err := io.ReadAll(cmdio.In()) if err != nil { return fmt.Errorf("could not read stdin: %w", err) } - memPkg.Files = []*std.MemFile{ + memPkg.Files = []*gnovm.MemFile{ { Name: "stdin.gno", Body: string(data), @@ -97,7 +98,7 @@ func execMakeRun(cfg *MakeRunCfg, args []string, cmdio commands.IO) error { if err != nil { return fmt.Errorf("could not read %q: %w", sourcePath, err) } - memPkg.Files = []*std.MemFile{ + memPkg.Files = []*gnovm.MemFile{ { Name: info.Name(), Body: string(b), diff --git a/gno.land/pkg/sdk/vm/builtins.go b/gno.land/pkg/sdk/vm/builtins.go index de58cd3e8ae..161e459873d 100644 --- a/gno.land/pkg/sdk/vm/builtins.go +++ b/gno.land/pkg/sdk/vm/builtins.go @@ -42,7 +42,7 @@ func (bnk *SDKBanker) TotalCoin(denom string) int64 { func (bnk *SDKBanker) IssueCoin(b32addr crypto.Bech32Address, denom string, amount int64) { addr := crypto.MustAddressFromString(string(b32addr)) - _, err := bnk.vmk.bank.AddCoins(bnk.ctx, addr, std.Coins{std.Coin{denom, amount}}) + _, err := bnk.vmk.bank.AddCoins(bnk.ctx, addr, std.Coins{std.Coin{Denom: denom, Amount: amount}}) if err != nil { panic(err) } @@ -50,8 +50,31 @@ func (bnk *SDKBanker) IssueCoin(b32addr crypto.Bech32Address, denom string, amou func (bnk *SDKBanker) RemoveCoin(b32addr crypto.Bech32Address, denom string, amount int64) { addr := crypto.MustAddressFromString(string(b32addr)) - _, err := bnk.vmk.bank.SubtractCoins(bnk.ctx, addr, std.Coins{std.Coin{denom, amount}}) + _, err := bnk.vmk.bank.SubtractCoins(bnk.ctx, addr, std.Coins{std.Coin{Denom: denom, Amount: amount}}) if err != nil { panic(err) } } + +// ---------------------------------------- +// SDKParams + +type SDKParams struct { + vmk *VMKeeper + ctx sdk.Context +} + +func NewSDKParams(vmk *VMKeeper, ctx sdk.Context) *SDKParams { + return &SDKParams{ + vmk: vmk, + ctx: ctx, + } +} + +func (prm *SDKParams) SetString(key, value string) { prm.vmk.prmk.SetString(prm.ctx, key, value) } +func (prm *SDKParams) SetBool(key string, value bool) { prm.vmk.prmk.SetBool(prm.ctx, key, value) } +func (prm *SDKParams) SetInt64(key string, value int64) { prm.vmk.prmk.SetInt64(prm.ctx, key, value) } +func (prm *SDKParams) SetUint64(key string, value uint64) { + prm.vmk.prmk.SetUint64(prm.ctx, key, value) +} +func (prm *SDKParams) SetBytes(key string, value []byte) { prm.vmk.prmk.SetBytes(prm.ctx, key, value) } diff --git a/gno.land/pkg/sdk/vm/common_test.go b/gno.land/pkg/sdk/vm/common_test.go index 43a8fe1fbec..8b1b7d909c1 100644 --- a/gno.land/pkg/sdk/vm/common_test.go +++ b/gno.land/pkg/sdk/vm/common_test.go @@ -11,6 +11,7 @@ import ( "github.com/gnolang/gno/tm2/pkg/sdk" authm "github.com/gnolang/gno/tm2/pkg/sdk/auth" bankm "github.com/gnolang/gno/tm2/pkg/sdk/bank" + paramsm "github.com/gnolang/gno/tm2/pkg/sdk/params" "github.com/gnolang/gno/tm2/pkg/std" "github.com/gnolang/gno/tm2/pkg/store" "github.com/gnolang/gno/tm2/pkg/store/dbadapter" @@ -22,6 +23,7 @@ type testEnv struct { vmk *VMKeeper bank bankm.BankKeeper acck authm.AccountKeeper + vmh vmHandler } func setupTestEnv() testEnv { @@ -47,7 +49,8 @@ func _setupTestEnv(cacheStdlibs bool) testEnv { ctx := sdk.NewContext(sdk.RunTxModeDeliver, ms, &bft.Header{ChainID: "test-chain-id"}, log.NewNoopLogger()) acck := authm.NewAccountKeeper(iavlCapKey, std.ProtoBaseAccount) bank := bankm.NewBankKeeper(acck) - vmk := NewVMKeeper(baseCapKey, iavlCapKey, acck, bank, 100_000_000) + prmk := paramsm.NewParamsKeeper(iavlCapKey, "params") + vmk := NewVMKeeper(baseCapKey, iavlCapKey, acck, bank, prmk) mcw := ms.MultiCacheWrap() vmk.Initialize(log.NewNoopLogger(), mcw) @@ -60,6 +63,7 @@ func _setupTestEnv(cacheStdlibs bool) testEnv { } vmk.CommitGnoTransactionStore(stdlibCtx) mcw.MultiWrite() + vmh := NewHandler(vmk) - return testEnv{ctx: ctx, vmk: vmk, bank: bank, acck: acck} + return testEnv{ctx: ctx, vmk: vmk, bank: bank, acck: acck, vmh: vmh} } diff --git a/gno.land/pkg/sdk/vm/gas_test.go b/gno.land/pkg/sdk/vm/gas_test.go index 4171b1cdbc3..ff924610627 100644 --- a/gno.land/pkg/sdk/vm/gas_test.go +++ b/gno.land/pkg/sdk/vm/gas_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/gnolang/gno/gno.land/pkg/gnoland/ugnot" + "github.com/gnolang/gno/gnovm" bft "github.com/gnolang/gno/tm2/pkg/bft/types" "github.com/gnolang/gno/tm2/pkg/crypto" "github.com/gnolang/gno/tm2/pkg/sdk" @@ -74,7 +75,7 @@ func TestAddPkgDeliverTx(t *testing.T) { assert.True(t, res.IsOK()) // NOTE: let's try to keep this bellow 100_000 :) - assert.Equal(t, int64(92825), gasDeliver) + assert.Equal(t, int64(93825), gasDeliver) } // Enough gas for a failed transaction. @@ -142,16 +143,15 @@ func setupAddPkg(success bool) (sdk.Context, sdk.Tx, vmHandler) { ctx := env.ctx // conduct base gas meter tests from a non-genesis block since genesis block use infinite gas meter instead. ctx = ctx.WithBlockHeader(&bft.Header{Height: int64(1)}) - vmHandler := NewHandler(env.vmk) // Create an account with 10M ugnot (10gnot) addr := crypto.AddressFromPreimage([]byte("test1")) acc := env.acck.NewAccountWithAddress(ctx, addr) env.acck.SetAccount(ctx, acc) env.bank.SetCoins(ctx, addr, std.MustParseCoins(ugnot.ValueString(10000000))) // success message - var files []*std.MemFile + var files []*gnovm.MemFile if success { - files = []*std.MemFile{ + files = []*gnovm.MemFile{ { Name: "hello.gno", Body: `package hello @@ -163,7 +163,7 @@ func Echo() string { } } else { // failed message - files = []*std.MemFile{ + files = []*gnovm.MemFile{ { Name: "hello.gno", Body: `package hello @@ -182,5 +182,5 @@ func Echo() UnknowType { fee := std.NewFee(500000, std.MustParseCoin(ugnot.ValueString(1))) tx := std.NewTx(msgs, fee, []std.Signature{}, "") - return ctx, tx, vmHandler + return ctx, tx, env.vmh } diff --git a/gno.land/pkg/sdk/vm/handler_test.go b/gno.land/pkg/sdk/vm/handler_test.go index 38ac8fa61b9..0d238deed1f 100644 --- a/gno.land/pkg/sdk/vm/handler_test.go +++ b/gno.land/pkg/sdk/vm/handler_test.go @@ -1,8 +1,13 @@ package vm import ( + "fmt" "testing" + "github.com/gnolang/gno/gnovm" + abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" + "github.com/gnolang/gno/tm2/pkg/crypto" + "github.com/gnolang/gno/tm2/pkg/std" "github.com/stretchr/testify/assert" ) @@ -48,3 +53,272 @@ func Test_parseQueryEval_panic(t *testing.T) { parseQueryEvalData("gno.land/r/demo/users") }) } + +func TestVmHandlerQuery_Eval(t *testing.T) { + tt := []struct { + input []byte + expectedResult string + expectedResultMatch string + expectedErrorMatch string + expectedPanicMatch string + // XXX: expectedEvents + }{ + // valid queries + {input: []byte(`gno.land/r/hello.Echo("hello")`), expectedResult: `("echo:hello" string)`}, + {input: []byte(`gno.land/r/hello.caller()`), expectedResult: `("" std.Address)`}, // FIXME? + {input: []byte(`gno.land/r/hello.GetHeight()`), expectedResult: `(0 int64)`}, + // {input: []byte(`gno.land/r/hello.time.RFC3339`), expectedResult: `test`}, // not working, but should we care? + {input: []byte(`gno.land/r/hello.PubString`), expectedResult: `("public string" string)`}, + {input: []byte(`gno.land/r/hello.ConstString`), expectedResult: `("const string" string)`}, + {input: []byte(`gno.land/r/hello.pvString`), expectedResult: `("private string" string)`}, + {input: []byte(`gno.land/r/hello.counter`), expectedResult: `(42 int)`}, + {input: []byte(`gno.land/r/hello.GetCounter()`), expectedResult: `(42 int)`}, + {input: []byte(`gno.land/r/hello.Inc()`), expectedResult: `(43 int)`}, + {input: []byte(`gno.land/r/hello.pvEcho("hello")`), expectedResult: `("pvecho:hello" string)`}, + {input: []byte(`gno.land/r/hello.1337`), expectedResult: `(1337 int)`}, + {input: []byte(`gno.land/r/hello.13.37`), expectedResult: `(13.37 float64)`}, + {input: []byte(`gno.land/r/hello.float64(1337)`), expectedResult: `(1337 float64)`}, + {input: []byte(`gno.land/r/hello.myStructInst`), expectedResult: `(struct{(1000 int)} gno.land/r/hello.myStruct)`}, + {input: []byte(`gno.land/r/hello.myStructInst.Foo()`), expectedResult: `("myStruct.Foo" string)`}, + {input: []byte(`gno.land/r/hello.myStruct`), expectedResultMatch: `\(typeval{gno.land/r/hello.myStruct \(0x.*\)} type{}\)`}, + {input: []byte(`gno.land/r/hello.Inc`), expectedResult: `(Inc func()( int))`}, + {input: []byte(`gno.land/r/hello.fn()("hi")`), expectedResult: `("echo:hi" string)`}, + {input: []byte(`gno.land/r/hello.sl`), expectedResultMatch: `(slice[ref(.*)] []int)`}, // XXX: should return the actual value + {input: []byte(`gno.land/r/hello.sl[1]`), expectedResultMatch: `(slice[ref(.*)] []int)`}, // XXX: should return the actual value + {input: []byte(`gno.land/r/hello.println(1234)`), expectedResultMatch: `^$`}, // XXX: compare stdout? + + // panics + {input: []byte(`gno.land/r/hello`), expectedPanicMatch: `expected . syntax in query input data`}, + + // errors + {input: []byte(`gno.land/r/hello.doesnotexist`), expectedErrorMatch: `^/:0:0: name doesnotexist not declared:`}, // multiline error + {input: []byte(`gno.land/r/doesnotexist.Foo`), expectedErrorMatch: `^invalid package path$`}, + {input: []byte(`gno.land/r/hello.Panic()`), expectedErrorMatch: `^foo$`}, + {input: []byte(`gno.land/r/hello.sl[6]`), expectedErrorMatch: `^slice index out of bounds: 6 \(len=5\)$`}, + } + + for _, tc := range tt { + name := string(tc.input) + t.Run(name, func(t *testing.T) { + env := setupTestEnv() + ctx := env.vmk.MakeGnoTransactionStore(env.ctx) + vmHandler := env.vmh + + // Give "addr1" some gnots. + addr := crypto.AddressFromPreimage([]byte("addr1")) + acc := env.acck.NewAccountWithAddress(ctx, addr) + env.acck.SetAccount(ctx, acc) + env.bank.SetCoins(ctx, addr, std.MustParseCoins("10000000ugnot")) + assert.True(t, env.bank.GetCoins(ctx, addr).IsEqual(std.MustParseCoins("10000000ugnot"))) + + // Create test package. + files := []*gnovm.MemFile{ + {Name: "hello.gno", Body: ` +package hello + +import "std" +import "time" + +var _ = time.RFC3339 +func caller() std.Address { return std.GetOrigCaller() } +var GetHeight = std.GetHeight +var sl = []int{1,2,3,4,5} +func fn() func(string) string { return Echo } +type myStruct struct{a int} +var myStructInst = myStruct{a: 1000} +func (ms myStruct) Foo() string { return "myStruct.Foo" } +func Panic() { panic("foo") } +var counter int = 42 +var pvString = "private string" +var PubString = "public string" +const ConstString = "const string" +func Echo(msg string) string { return "echo:"+msg } +func GetCounter() int { return counter } +func Inc() int { counter += 1; return counter } +func pvEcho(msg string) string { return "pvecho:"+msg } +`}, + } + pkgPath := "gno.land/r/hello" + msg1 := NewMsgAddPackage(addr, pkgPath, files) + err := env.vmk.AddPackage(ctx, msg1) + assert.NoError(t, err) + env.vmk.CommitGnoTransactionStore(ctx) + + req := abci.RequestQuery{ + Path: "vm/qeval", + Data: tc.input, + } + + defer func() { + if r := recover(); r != nil { + output := fmt.Sprintf("%v", r) + assert.Regexp(t, tc.expectedPanicMatch, output) + } else { + assert.Equal(t, tc.expectedPanicMatch, "", "should not panic") + } + }() + res := vmHandler.Query(env.ctx, req) + if tc.expectedPanicMatch == "" { + if tc.expectedErrorMatch == "" { + assert.True(t, res.IsOK(), "should not have error") + if tc.expectedResult != "" { + assert.Equal(t, string(res.Data), tc.expectedResult) + } + if tc.expectedResultMatch != "" { + assert.Regexp(t, tc.expectedResultMatch, string(res.Data)) + } + } else { + assert.False(t, res.IsOK(), "should have an error") + errmsg := res.Error.Error() + assert.Regexp(t, tc.expectedErrorMatch, errmsg) + } + } + }) + } +} + +func TestVmHandlerQuery_Funcs(t *testing.T) { + tt := []struct { + input []byte + expectedResult string + expectedErrorMatch string + }{ + // valid queries + {input: []byte(`gno.land/r/hello`), expectedResult: `[{"FuncName":"Panic","Params":null,"Results":null},{"FuncName":"Echo","Params":[{"Name":"msg","Type":"string","Value":""}],"Results":[{"Name":"_","Type":"string","Value":""}]},{"FuncName":"GetCounter","Params":null,"Results":[{"Name":"_","Type":"int","Value":""}]},{"FuncName":"Inc","Params":null,"Results":[{"Name":"_","Type":"int","Value":""}]}]`}, + {input: []byte(`gno.land/r/doesnotexist`), expectedErrorMatch: `invalid package path`}, + {input: []byte(`std`), expectedErrorMatch: `invalid package path`}, + {input: []byte(`strings`), expectedErrorMatch: `invalid package path`}, + } + + for _, tc := range tt { + name := string(tc.input) + t.Run(name, func(t *testing.T) { + env := setupTestEnv() + ctx := env.vmk.MakeGnoTransactionStore(env.ctx) + vmHandler := env.vmh + + // Give "addr1" some gnots. + addr := crypto.AddressFromPreimage([]byte("addr1")) + acc := env.acck.NewAccountWithAddress(ctx, addr) + env.acck.SetAccount(ctx, acc) + env.bank.SetCoins(ctx, addr, std.MustParseCoins("10000000ugnot")) + assert.True(t, env.bank.GetCoins(ctx, addr).IsEqual(std.MustParseCoins("10000000ugnot"))) + + // Create test package. + files := []*gnovm.MemFile{ + {Name: "hello.gno", Body: ` +package hello + +var sl = []int{1,2,3,4,5} +func fn() func(string) string { return Echo } +type myStruct struct{a int} +var myStructInst = myStruct{a: 1000} +func (ms myStruct) Foo() string { return "myStruct.Foo" } +func Panic() { panic("foo") } +var counter int = 42 +var pvString = "private string" +var PubString = "public string" +const ConstString = "const string" +func Echo(msg string) string { return "echo:"+msg } +func GetCounter() int { return counter } +func Inc() int { counter += 1; return counter } +func pvEcho(msg string) string { return "pvecho:"+msg } +`}, + } + pkgPath := "gno.land/r/hello" + msg1 := NewMsgAddPackage(addr, pkgPath, files) + err := env.vmk.AddPackage(ctx, msg1) + assert.NoError(t, err) + + req := abci.RequestQuery{ + Path: "vm/qfuncs", + Data: tc.input, + } + + res := vmHandler.Query(env.ctx, req) + if tc.expectedErrorMatch == "" { + assert.True(t, res.IsOK(), "should not have error") + if tc.expectedResult != "" { + assert.Equal(t, string(res.Data), tc.expectedResult) + } + } else { + assert.False(t, res.IsOK(), "should have an error") + errmsg := res.Error.Error() + assert.Regexp(t, tc.expectedErrorMatch, errmsg) + } + }) + } +} + +func TestVmHandlerQuery_File(t *testing.T) { + tt := []struct { + input []byte + expectedResult string + expectedResultMatch string + expectedErrorMatch string + expectedPanicMatch string + // XXX: expectedEvents + }{ + // valid queries + {input: []byte(`gno.land/r/hello/hello.gno`), expectedResult: "package hello\n\nfunc Hello() string { return \"hello\" }\n"}, + {input: []byte(`gno.land/r/hello/README.md`), expectedResult: "# Hello"}, + {input: []byte(`gno.land/r/hello/doesnotexist.gno`), expectedErrorMatch: `file "gno.land/r/hello/doesnotexist.gno" is not available`}, + {input: []byte(`gno.land/r/hello`), expectedResult: "README.md\nhello.gno"}, + {input: []byte(`gno.land/r/doesnotexist`), expectedErrorMatch: `package "gno.land/r/doesnotexist" is not available`}, + {input: []byte(`gno.land/r/doesnotexist/hello.gno`), expectedErrorMatch: `file "gno.land/r/doesnotexist/hello.gno" is not available`}, + } + + for _, tc := range tt { + name := string(tc.input) + t.Run(name, func(t *testing.T) { + env := setupTestEnv() + ctx := env.vmk.MakeGnoTransactionStore(env.ctx) + vmHandler := env.vmh + + // Give "addr1" some gnots. + addr := crypto.AddressFromPreimage([]byte("addr1")) + acc := env.acck.NewAccountWithAddress(ctx, addr) + env.acck.SetAccount(ctx, acc) + env.bank.SetCoins(ctx, addr, std.MustParseCoins("10000000ugnot")) + assert.True(t, env.bank.GetCoins(ctx, addr).IsEqual(std.MustParseCoins("10000000ugnot"))) + + // Create test package. + files := []*gnovm.MemFile{ + {Name: "README.md", Body: "# Hello"}, + {Name: "hello.gno", Body: "package hello\n\nfunc Hello() string { return \"hello\" }\n"}, + } + pkgPath := "gno.land/r/hello" + msg1 := NewMsgAddPackage(addr, pkgPath, files) + err := env.vmk.AddPackage(ctx, msg1) + assert.NoError(t, err) + + req := abci.RequestQuery{ + Path: "vm/qfile", + Data: tc.input, + } + + defer func() { + if r := recover(); r != nil { + output := fmt.Sprintf("%v", r) + assert.Regexp(t, tc.expectedPanicMatch, output) + } else { + assert.Equal(t, "", tc.expectedPanicMatch, "should not panic") + } + }() + res := vmHandler.Query(env.ctx, req) + if tc.expectedErrorMatch == "" { + assert.True(t, res.IsOK(), "should not have error") + if tc.expectedResult != "" { + assert.Equal(t, string(res.Data), tc.expectedResult) + } + if tc.expectedResultMatch != "" { + assert.Regexp(t, tc.expectedResultMatch, string(res.Data)) + } + } else { + assert.False(t, res.IsOK(), "should have an error") + errmsg := res.Error.Error() + assert.Regexp(t, tc.expectedErrorMatch, errmsg) + } + }) + } +} diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index 365473b3e7a..7f5216a4f03 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -14,6 +14,7 @@ import ( "sync" "time" + "github.com/gnolang/gno/gnovm" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" "github.com/gnolang/gno/gnovm/stdlibs" "github.com/gnolang/gno/tm2/pkg/crypto" @@ -23,6 +24,7 @@ import ( "github.com/gnolang/gno/tm2/pkg/sdk" "github.com/gnolang/gno/tm2/pkg/sdk/auth" "github.com/gnolang/gno/tm2/pkg/sdk/bank" + "github.com/gnolang/gno/tm2/pkg/sdk/params" "github.com/gnolang/gno/tm2/pkg/std" "github.com/gnolang/gno/tm2/pkg/store" "github.com/gnolang/gno/tm2/pkg/store/dbadapter" @@ -59,11 +61,10 @@ type VMKeeper struct { iavlKey store.StoreKey acck auth.AccountKeeper bank bank.BankKeeper + prmk params.ParamsKeeper // cached, the DeliverTx persistent state. gnoStore gno.Store - - maxCycles int64 // max allowed cylces on VM executions } // NewVMKeeper returns a new VMKeeper. @@ -72,15 +73,14 @@ func NewVMKeeper( iavlKey store.StoreKey, acck auth.AccountKeeper, bank bank.BankKeeper, - maxCycles int64, + prmk params.ParamsKeeper, ) *VMKeeper { - // TODO: create an Options struct to avoid too many constructor parameters vmk := &VMKeeper{ - baseKey: baseKey, - iavlKey: iavlKey, - acck: acck, - bank: bank, - maxCycles: maxCycles, + baseKey: baseKey, + iavlKey: iavlKey, + acck: acck, + bank: bank, + prmk: prmk, } return vmk } @@ -226,9 +226,15 @@ func (vm *VMKeeper) getGnoTransactionStore(ctx sdk.Context) gno.TransactionStore // Namespace can be either a user or crypto address. var reNamespace = regexp.MustCompile(`^gno.land/(?:r|p)/([\.~_a-zA-Z0-9]+)`) +const ( + sysUsersPkgParamKey = "vm/gno.land/r/sys/params.string" + sysUsersPkgDefault = "gno.land/r/sys/users" +) + // checkNamespacePermission check if the user as given has correct permssion to on the given pkg path func (vm *VMKeeper) checkNamespacePermission(ctx sdk.Context, creator crypto.Address, pkgPath string) error { - const sysUsersPkg = "gno.land/r/sys/users" + sysUsersPkg := sysUsersPkgDefault + vm.prmk.GetString(ctx, sysUsersPkgParamKey, &sysUsersPkg) store := vm.getGnoTransactionStore(ctx) @@ -262,18 +268,18 @@ func (vm *VMKeeper) checkNamespacePermission(ctx sdk.Context, creator crypto.Add OrigPkgAddr: pkgAddr.Bech32(), // XXX: should we remove the banker ? Banker: NewSDKBanker(vm, ctx), + Params: NewSDKParams(vm, ctx), EventLogger: ctx.EventLogger(), } m := gno.NewMachineWithOptions( gno.MachineOptions{ - PkgPath: "", - Output: os.Stdout, // XXX - Store: store, - Context: msgCtx, - Alloc: store.GetAllocator(), - MaxCycles: vm.maxCycles, - GasMeter: ctx.GasMeter(), + PkgPath: "", + Output: os.Stdout, // XXX + Store: store, + Context: msgCtx, + Alloc: store.GetAllocator(), + GasMeter: ctx.GasMeter(), }) defer m.Release() @@ -363,18 +369,18 @@ func (vm *VMKeeper) AddPackage(ctx sdk.Context, msg MsgAddPackage) (err error) { OrigSendSpent: new(std.Coins), OrigPkgAddr: pkgAddr.Bech32(), Banker: NewSDKBanker(vm, ctx), + Params: NewSDKParams(vm, ctx), EventLogger: ctx.EventLogger(), } // Parse and run the files, construct *PV. m2 := gno.NewMachineWithOptions( gno.MachineOptions{ - PkgPath: "", - Output: os.Stdout, // XXX - Store: gnostore, - Alloc: gnostore.GetAllocator(), - Context: msgCtx, - MaxCycles: vm.maxCycles, - GasMeter: ctx.GasMeter(), + PkgPath: "", + Output: os.Stdout, // XXX + Store: gnostore, + Alloc: gnostore.GetAllocator(), + Context: msgCtx, + GasMeter: ctx.GasMeter(), }) defer m2.Release() defer func() { @@ -464,18 +470,18 @@ func (vm *VMKeeper) Call(ctx sdk.Context, msg MsgCall) (res string, err error) { OrigSendSpent: new(std.Coins), OrigPkgAddr: pkgAddr.Bech32(), Banker: NewSDKBanker(vm, ctx), + Params: NewSDKParams(vm, ctx), EventLogger: ctx.EventLogger(), } // Construct machine and evaluate. m := gno.NewMachineWithOptions( gno.MachineOptions{ - PkgPath: "", - Output: os.Stdout, // XXX - Store: gnostore, - Context: msgCtx, - Alloc: gnostore.GetAllocator(), - MaxCycles: vm.maxCycles, - GasMeter: ctx.GasMeter(), + PkgPath: "", + Output: os.Stdout, // XXX + Store: gnostore, + Context: msgCtx, + Alloc: gnostore.GetAllocator(), + GasMeter: ctx.GasMeter(), }) defer m.Release() m.SetActivePackage(mpv) @@ -563,19 +569,19 @@ func (vm *VMKeeper) Run(ctx sdk.Context, msg MsgRun) (res string, err error) { OrigSendSpent: new(std.Coins), OrigPkgAddr: pkgAddr.Bech32(), Banker: NewSDKBanker(vm, ctx), + Params: NewSDKParams(vm, ctx), EventLogger: ctx.EventLogger(), } // Parse and run the files, construct *PV. buf := new(bytes.Buffer) m := gno.NewMachineWithOptions( gno.MachineOptions{ - PkgPath: "", - Output: buf, - Store: gnostore, - Alloc: gnostore.GetAllocator(), - Context: msgCtx, - MaxCycles: vm.maxCycles, - GasMeter: ctx.GasMeter(), + PkgPath: "", + Output: buf, + Store: gnostore, + Alloc: gnostore.GetAllocator(), + Context: msgCtx, + GasMeter: ctx.GasMeter(), }) // XXX MsgRun does not have pkgPath. How do we find it on chain? defer m.Release() @@ -596,13 +602,12 @@ func (vm *VMKeeper) Run(ctx sdk.Context, msg MsgRun) (res string, err error) { m2 := gno.NewMachineWithOptions( gno.MachineOptions{ - PkgPath: "", - Output: buf, - Store: gnostore, - Alloc: gnostore.GetAllocator(), - Context: msgCtx, - MaxCycles: vm.maxCycles, - GasMeter: ctx.GasMeter(), + PkgPath: "", + Output: buf, + Store: gnostore, + Alloc: gnostore.GetAllocator(), + Context: msgCtx, + GasMeter: ctx.GasMeter(), }) defer m2.Release() m2.SetActivePackage(pv) @@ -724,17 +729,17 @@ func (vm *VMKeeper) QueryEval(ctx sdk.Context, pkgPath string, expr string) (res // OrigSendSpent: nil, OrigPkgAddr: pkgAddr.Bech32(), Banker: NewSDKBanker(vm, ctx), // safe as long as ctx is a fork to be discarded. + Params: NewSDKParams(vm, ctx), EventLogger: ctx.EventLogger(), } m := gno.NewMachineWithOptions( gno.MachineOptions{ - PkgPath: pkgPath, - Output: os.Stdout, // XXX - Store: gnostore, - Context: msgCtx, - Alloc: alloc, - MaxCycles: vm.maxCycles, - GasMeter: ctx.GasMeter(), + PkgPath: pkgPath, + Output: os.Stdout, // XXX + Store: gnostore, + Context: msgCtx, + Alloc: alloc, + GasMeter: ctx.GasMeter(), }) defer m.Release() defer func() { @@ -791,17 +796,17 @@ func (vm *VMKeeper) QueryEvalString(ctx sdk.Context, pkgPath string, expr string // OrigSendSpent: nil, OrigPkgAddr: pkgAddr.Bech32(), Banker: NewSDKBanker(vm, ctx), // safe as long as ctx is a fork to be discarded. + Params: NewSDKParams(vm, ctx), EventLogger: ctx.EventLogger(), } m := gno.NewMachineWithOptions( gno.MachineOptions{ - PkgPath: pkgPath, - Output: os.Stdout, // XXX - Store: gnostore, - Context: msgCtx, - Alloc: alloc, - MaxCycles: vm.maxCycles, - GasMeter: ctx.GasMeter(), + PkgPath: pkgPath, + Output: os.Stdout, // XXX + Store: gnostore, + Context: msgCtx, + Alloc: alloc, + GasMeter: ctx.GasMeter(), }) defer m.Release() defer func() { @@ -828,7 +833,7 @@ func (vm *VMKeeper) QueryEvalString(ctx sdk.Context, pkgPath string, expr string func (vm *VMKeeper) QueryFile(ctx sdk.Context, filepath string) (res string, err error) { store := vm.newGnoTransactionStore(ctx) // throwaway (never committed) - dirpath, filename := std.SplitFilepath(filepath) + dirpath, filename := gnovm.SplitFilepath(filepath) if filename != "" { memFile := store.GetMemFile(dirpath, filename) if memFile == nil { diff --git a/gno.land/pkg/sdk/vm/keeper_test.go b/gno.land/pkg/sdk/vm/keeper_test.go index 9257da2ddaf..9afbb3de551 100644 --- a/gno.land/pkg/sdk/vm/keeper_test.go +++ b/gno.land/pkg/sdk/vm/keeper_test.go @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/gnolang/gno/gno.land/pkg/gnoland/ugnot" + "github.com/gnolang/gno/gnovm" "github.com/gnolang/gno/gnovm/pkg/gnolang" "github.com/gnolang/gno/tm2/pkg/crypto" "github.com/gnolang/gno/tm2/pkg/db/memdb" @@ -35,7 +36,7 @@ func TestVMKeeperAddPackage(t *testing.T) { assert.True(t, env.bank.GetCoins(ctx, addr).IsEqual(std.MustParseCoins(coinsString))) // Create test package. - files := []*std.MemFile{ + files := []*gnovm.MemFile{ { Name: "test.gno", Body: `package test @@ -80,8 +81,8 @@ func TestVMKeeperOrigSend1(t *testing.T) { assert.True(t, env.bank.GetCoins(ctx, addr).IsEqual(std.MustParseCoins(coinsString))) // Create test package. - files := []*std.MemFile{ - {"init.gno", ` + files := []*gnovm.MemFile{ + {Name: "init.gno", Body: ` package test import "std" @@ -125,8 +126,8 @@ func TestVMKeeperOrigSend2(t *testing.T) { assert.True(t, env.bank.GetCoins(ctx, addr).IsEqual(std.MustParseCoins(coinsString))) // Create test package. - files := []*std.MemFile{ - {"init.gno", ` + files := []*gnovm.MemFile{ + {Name: "init.gno", Body: ` package test import "std" @@ -179,8 +180,8 @@ func TestVMKeeperOrigSend3(t *testing.T) { assert.True(t, env.bank.GetCoins(ctx, addr).IsEqual(std.MustParseCoins(coinsString))) // Create test package. - files := []*std.MemFile{ - {"init.gno", ` + files := []*gnovm.MemFile{ + {Name: "init.gno", Body: ` package test import "std" @@ -223,8 +224,8 @@ func TestVMKeeperRealmSend1(t *testing.T) { assert.True(t, env.bank.GetCoins(ctx, addr).IsEqual(std.MustParseCoins(coinsString))) // Create test package. - files := []*std.MemFile{ - {"init.gno", ` + files := []*gnovm.MemFile{ + {Name: "init.gno", Body: ` package test import "std" @@ -267,8 +268,8 @@ func TestVMKeeperRealmSend2(t *testing.T) { assert.True(t, env.bank.GetCoins(ctx, addr).IsEqual(std.MustParseCoins(coinsString))) // Create test package. - files := []*std.MemFile{ - {"init.gno", ` + files := []*gnovm.MemFile{ + {Name: "init.gno", Body: ` package test import "std" @@ -298,6 +299,60 @@ func Echo(msg string) string { assert.Error(t, err) } +// Using x/params from a realm. +func TestVMKeeperParams(t *testing.T) { + env := setupTestEnv() + ctx := env.vmk.MakeGnoTransactionStore(env.ctx) + + // Give "addr1" some gnots. + addr := crypto.AddressFromPreimage([]byte("addr1")) + acc := env.acck.NewAccountWithAddress(ctx, addr) + env.acck.SetAccount(ctx, acc) + env.bank.SetCoins(ctx, addr, std.MustParseCoins(coinsString)) + // env.prmk. + assert.True(t, env.bank.GetCoins(ctx, addr).IsEqual(std.MustParseCoins(coinsString))) + + // Create test package. + files := []*gnovm.MemFile{ + {Name: "init.gno", Body: ` +package test + +import "std" + +func init() { + std.SetParamString("foo.string", "foo1") +} + +func Do() string { + std.SetParamInt64("bar.int64", int64(1337)) + std.SetParamString("foo.string", "foo2") // override init + + return "XXX" // return std.GetConfig("gno.land/r/test.foo"), if we want to expose std.GetConfig, maybe as a std.TestGetConfig +}`}, + } + pkgPath := "gno.land/r/test" + msg1 := NewMsgAddPackage(addr, pkgPath, files) + err := env.vmk.AddPackage(ctx, msg1) + assert.NoError(t, err) + + // Run Echo function. + coins := std.MustParseCoins(ugnot.ValueString(9_000_000)) + msg2 := NewMsgCall(addr, coins, pkgPath, "Do", []string{}) + + res, err := env.vmk.Call(ctx, msg2) + assert.NoError(t, err) + _ = res + expected := fmt.Sprintf("(\"%s\" string)\n\n", "XXX") // XXX: return something more useful + assert.Equal(t, expected, res) + + var foo string + var bar int64 + env.vmk.prmk.GetString(ctx, "gno.land/r/test.foo.string", &foo) + env.vmk.prmk.GetInt64(ctx, "gno.land/r/test.bar.int64", &bar) + assert.Equal(t, "foo2", foo) + assert.Equal(t, int64(1337), bar) +} + // Assign admin as OrigCaller on deploying the package. func TestVMKeeperOrigCallerInit(t *testing.T) { env := setupTestEnv() @@ -311,8 +366,8 @@ func TestVMKeeperOrigCallerInit(t *testing.T) { assert.True(t, env.bank.GetCoins(ctx, addr).IsEqual(std.MustParseCoins(coinsString))) // Create test package. - files := []*std.MemFile{ - {"init.gno", ` + files := []*gnovm.MemFile{ + {Name: "init.gno", Body: ` package test import "std" @@ -320,7 +375,7 @@ import "std" var admin std.Address func init() { - admin = std.GetOrigCaller() + admin = std.GetOrigCaller() } func Echo(msg string) string { @@ -362,8 +417,8 @@ func TestVMKeeperRunSimple(t *testing.T) { acc := env.acck.NewAccountWithAddress(ctx, addr) env.acck.SetAccount(ctx, acc) - files := []*std.MemFile{ - {"script.gno", ` + files := []*gnovm.MemFile{ + {Name: "script.gno", Body: ` package main func main() { @@ -401,8 +456,8 @@ func testVMKeeperRunImportStdlibs(t *testing.T, env testEnv) { acc := env.acck.NewAccountWithAddress(ctx, addr) env.acck.SetAccount(ctx, acc) - files := []*std.MemFile{ - {"script.gno", ` + files := []*gnovm.MemFile{ + {Name: "script.gno", Body: ` package main import "std" @@ -434,7 +489,7 @@ func TestNumberOfArgsError(t *testing.T) { assert.True(t, env.bank.GetCoins(ctx, addr).IsEqual(std.MustParseCoins(coinsString))) // Create test package. - files := []*std.MemFile{ + files := []*gnovm.MemFile{ { Name: "test.gno", Body: `package test @@ -473,8 +528,8 @@ func TestVMKeeperReinitialize(t *testing.T) { assert.True(t, env.bank.GetCoins(ctx, addr).IsEqual(std.MustParseCoins(coinsString))) // Create test package. - files := []*std.MemFile{ - {"init.gno", ` + files := []*gnovm.MemFile{ + {Name: "init.gno", Body: ` package test func Echo(msg string) string { diff --git a/gno.land/pkg/sdk/vm/msg_test.go b/gno.land/pkg/sdk/vm/msg_test.go index eaaaa0f0ab2..684dc21e9f2 100644 --- a/gno.land/pkg/sdk/vm/msg_test.go +++ b/gno.land/pkg/sdk/vm/msg_test.go @@ -3,6 +3,7 @@ package vm import ( "testing" + "github.com/gnolang/gno/gnovm" "github.com/gnolang/gno/tm2/pkg/crypto" "github.com/gnolang/gno/tm2/pkg/std" "github.com/stretchr/testify/assert" @@ -14,7 +15,7 @@ func TestMsgAddPackage_ValidateBasic(t *testing.T) { creator := crypto.AddressFromPreimage([]byte("addr1")) pkgName := "test" pkgPath := "gno.land/r/namespace/test" - files := []*std.MemFile{ + files := []*gnovm.MemFile{ { Name: "test.gno", Body: `package test @@ -40,7 +41,7 @@ func TestMsgAddPackage_ValidateBasic(t *testing.T) { name: "missing creator address", msg: MsgAddPackage{ Creator: crypto.Address{}, - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: pkgName, Path: pkgPath, Files: files, @@ -56,7 +57,7 @@ func TestMsgAddPackage_ValidateBasic(t *testing.T) { name: "missing package path", msg: MsgAddPackage{ Creator: creator, - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: pkgName, Path: "", Files: files, @@ -72,7 +73,7 @@ func TestMsgAddPackage_ValidateBasic(t *testing.T) { name: "invalid deposit coins", msg: MsgAddPackage{ Creator: creator, - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: pkgName, Path: pkgPath, Files: files, @@ -199,7 +200,7 @@ func TestMsgRun_ValidateBasic(t *testing.T) { caller := crypto.AddressFromPreimage([]byte("addr1")) pkgName := "main" pkgPath := "gno.land/r/" + caller.String() + "/run" - pkgFiles := []*std.MemFile{ + pkgFiles := []*gnovm.MemFile{ { Name: "main.gno", Body: `package main @@ -226,7 +227,7 @@ func TestMsgRun_ValidateBasic(t *testing.T) { name: "invalid caller address", msg: MsgRun{ Caller: crypto.Address{}, - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: pkgName, Path: pkgPath, Files: pkgFiles, @@ -242,7 +243,7 @@ func TestMsgRun_ValidateBasic(t *testing.T) { name: "invalid package path", msg: MsgRun{ Caller: caller, - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: pkgName, Path: "gno.land/r/namespace/test", // this is not a valid run path Files: pkgFiles, diff --git a/gno.land/pkg/sdk/vm/msgs.go b/gno.land/pkg/sdk/vm/msgs.go index d650c23f382..d5b82067a98 100644 --- a/gno.land/pkg/sdk/vm/msgs.go +++ b/gno.land/pkg/sdk/vm/msgs.go @@ -4,6 +4,7 @@ import ( "fmt" "strings" + "github.com/gnolang/gno/gnovm" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" "github.com/gnolang/gno/tm2/pkg/amino" "github.com/gnolang/gno/tm2/pkg/crypto" @@ -16,15 +17,15 @@ import ( // MsgAddPackage - create and initialize new package type MsgAddPackage struct { - Creator crypto.Address `json:"creator" yaml:"creator"` - Package *std.MemPackage `json:"package" yaml:"package"` - Deposit std.Coins `json:"deposit" yaml:"deposit"` + Creator crypto.Address `json:"creator" yaml:"creator"` + Package *gnovm.MemPackage `json:"package" yaml:"package"` + Deposit std.Coins `json:"deposit" yaml:"deposit"` } var _ std.Msg = MsgAddPackage{} // NewMsgAddPackage - upload a package with files. -func NewMsgAddPackage(creator crypto.Address, pkgPath string, files []*std.MemFile) MsgAddPackage { +func NewMsgAddPackage(creator crypto.Address, pkgPath string, files []*gnovm.MemFile) MsgAddPackage { var pkgName string for _, file := range files { if strings.HasSuffix(file.Name, ".gno") { @@ -34,7 +35,7 @@ func NewMsgAddPackage(creator crypto.Address, pkgPath string, files []*std.MemFi } return MsgAddPackage{ Creator: creator, - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: pkgName, Path: pkgPath, Files: files, @@ -145,14 +146,14 @@ func (msg MsgCall) GetReceived() std.Coins { // MsgRun - executes arbitrary Gno code. type MsgRun struct { - Caller crypto.Address `json:"caller" yaml:"caller"` - Send std.Coins `json:"send" yaml:"send"` - Package *std.MemPackage `json:"package" yaml:"package"` + Caller crypto.Address `json:"caller" yaml:"caller"` + Send std.Coins `json:"send" yaml:"send"` + Package *gnovm.MemPackage `json:"package" yaml:"package"` } var _ std.Msg = MsgRun{} -func NewMsgRun(caller crypto.Address, send std.Coins, files []*std.MemFile) MsgRun { +func NewMsgRun(caller crypto.Address, send std.Coins, files []*gnovm.MemFile) MsgRun { for _, file := range files { if strings.HasSuffix(file.Name, ".gno") { pkgName := string(gno.PackageNameFromFileBody(file.Name, file.Body)) @@ -164,7 +165,7 @@ func NewMsgRun(caller crypto.Address, send std.Coins, files []*std.MemFile) MsgR return MsgRun{ Caller: caller, Send: send, - Package: &std.MemPackage{ + Package: &gnovm.MemPackage{ Name: "main", Path: "", // auto set by the handler Files: files, diff --git a/gno.land/pkg/sdk/vm/package.go b/gno.land/pkg/sdk/vm/package.go index 30dd116d4e3..0359061ccea 100644 --- a/gno.land/pkg/sdk/vm/package.go +++ b/gno.land/pkg/sdk/vm/package.go @@ -1,6 +1,7 @@ package vm import ( + "github.com/gnolang/gno/gnovm" "github.com/gnolang/gno/tm2/pkg/amino" "github.com/gnolang/gno/tm2/pkg/std" ) @@ -11,6 +12,7 @@ var Package = amino.RegisterPackage(amino.NewPackage( amino.GetCallersDirname(), ).WithDependencies( std.Package, + gnovm.Package, ).WithTypes( MsgCall{}, "m_call", MsgRun{}, "m_run", diff --git a/gno.land/pkg/sdk/vm/vm.proto b/gno.land/pkg/sdk/vm/vm.proto index e02226e1ae4..efaf025e431 100644 --- a/gno.land/pkg/sdk/vm/vm.proto +++ b/gno.land/pkg/sdk/vm/vm.proto @@ -5,6 +5,7 @@ option go_package = "github.com/gnolang/gno/gno.land/pkg/sdk/vm/pb"; // imports import "github.com/gnolang/gno/tm2/pkg/std/std.proto"; +import "github.com/gnolang/gno/gnovm/gnovm.proto"; // messages message m_call { @@ -18,12 +19,12 @@ message m_call { message m_run { string caller = 1; string send = 2; - std.MemPackage package = 3; + gnovm.MemPackage package = 3; } message m_addpkg { string creator = 1; - std.MemPackage package = 2; + gnovm.MemPackage package = 2; string deposit = 3; } @@ -40,5 +41,8 @@ message InvalidExprError { } message TypeCheckError { - repeated string errors = 1 [json_name = "Errors"]; + repeated string errors = 1; +} + +message UnauthorizedUserError { } \ No newline at end of file diff --git a/gnovm/Makefile b/gnovm/Makefile index 5ff3af9c253..d27395d9cd1 100644 --- a/gnovm/Makefile +++ b/gnovm/Makefile @@ -54,7 +54,7 @@ lint: .PHONY: fmt fmt: - go run ./cmd/gno fmt $(GNOFMT_FLAGS) ./stdlibs/... + go run ./cmd/gno fmt $(GNOFMT_FLAGS) ./stdlibs/... ./tests/stdlibs/... $(rundep) mvdan.cc/gofumpt $(GOFMT_FLAGS) . .PHONY: imports diff --git a/gnovm/cmd/gno/lint.go b/gnovm/cmd/gno/lint.go index 6c497c7e2c0..c6008117f13 100644 --- a/gnovm/cmd/gno/lint.go +++ b/gnovm/cmd/gno/lint.go @@ -17,6 +17,7 @@ import ( "github.com/gnolang/gno/gnovm/tests" "github.com/gnolang/gno/tm2/pkg/commands" osm "github.com/gnolang/gno/tm2/pkg/os" + "go.uber.org/multierr" ) type lintCfg struct { @@ -174,12 +175,18 @@ func catchRuntimeError(pkgPath string, stderr io.WriteCloser, action func()) (ha case *gno.PreprocessError: err := verr.Unwrap() fmt.Fprint(stderr, issueFromError(pkgPath, err).String()+"\n") - case scanner.ErrorList: - for _, err := range verr { - fmt.Fprint(stderr, issueFromError(pkgPath, err).String()+"\n") - } case error: - fmt.Fprint(stderr, issueFromError(pkgPath, verr).String()+"\n") + errors := multierr.Errors(verr) + for _, err := range errors { + errList, ok := err.(scanner.ErrorList) + if ok { + for _, errorInList := range errList { + fmt.Fprint(stderr, issueFromError(pkgPath, errorInList).String()+"\n") + } + } else { + fmt.Fprint(stderr, issueFromError(pkgPath, err).String()+"\n") + } + } case string: fmt.Fprint(stderr, issueFromError(pkgPath, errors.New(verr)).String()+"\n") default: diff --git a/gnovm/cmd/gno/lint_test.go b/gnovm/cmd/gno/lint_test.go index a5c0319cd00..20d21c05d05 100644 --- a/gnovm/cmd/gno/lint_test.go +++ b/gnovm/cmd/gno/lint_test.go @@ -23,6 +23,10 @@ func TestLintApp(t *testing.T) { args: []string{"lint", "../../tests/integ/several-lint-errors/main.gno"}, stderrShouldContain: "../../tests/integ/several-lint-errors/main.gno:5: expected ';', found example (code=2).\n../../tests/integ/several-lint-errors/main.gno:6", errShouldBe: "exit code: 1", + }, { + args: []string{"lint", "../../tests/integ/several-files-multiple-errors/main.gno"}, + stderrShouldContain: "../../tests/integ/several-files-multiple-errors/file2.gno:3: expected 'IDENT', found '{' (code=2).\n../../tests/integ/several-files-multiple-errors/file2.gno:5: expected type, found '}' (code=2).\n../../tests/integ/several-files-multiple-errors/main.gno:5: expected ';', found example (code=2).\n../../tests/integ/several-files-multiple-errors/main.gno:6: expected '}', found 'EOF' (code=2).\n", + errShouldBe: "exit code: 1", }, { args: []string{"lint", "../../tests/integ/run_main/"}, stderrShouldContain: "./../../tests/integ/run_main: missing 'gno.mod' file (code=1).", diff --git a/gnovm/cmd/gno/run_test.go b/gnovm/cmd/gno/run_test.go index 975868b7daf..e5aa1bd6279 100644 --- a/gnovm/cmd/gno/run_test.go +++ b/gnovm/cmd/gno/run_test.go @@ -83,6 +83,11 @@ func TestRunApp(t *testing.T) { args: []string{"run", "-expr", "Context()", "../../tests/integ/context/context.gno"}, stdoutShouldContain: "Context worked", }, + { + args: []string{"run", "../../tests/integ/several-files-multiple-errors/"}, + stderrShouldContain: "../../tests/integ/several-files-multiple-errors/file2.gno:3: expected 'IDENT', found '{' (code=2).\n../../tests/integ/several-files-multiple-errors/file2.gno:5: expected type, found '}' (code=2).\n../../tests/integ/several-files-multiple-errors/main.gno:5: expected ';', found example (code=2).\n../../tests/integ/several-files-multiple-errors/main.gno:6: expected '}', found 'EOF' (code=2).", + errShouldBe: "exit code: 1", + }, // TODO: a test file // TODO: args // TODO: nativeLibs VS stdlibs diff --git a/gnovm/cmd/gno/test.go b/gnovm/cmd/gno/test.go index 5884463a552..d54b12f6a4f 100644 --- a/gnovm/cmd/gno/test.go +++ b/gnovm/cmd/gno/test.go @@ -7,6 +7,7 @@ import ( "flag" "fmt" "log" + "math" "os" "path/filepath" "runtime/debug" @@ -17,14 +18,15 @@ import ( "go.uber.org/multierr" + "github.com/gnolang/gno/gnovm" "github.com/gnolang/gno/gnovm/pkg/gnoenv" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" "github.com/gnolang/gno/gnovm/pkg/gnomod" "github.com/gnolang/gno/gnovm/tests" + teststd "github.com/gnolang/gno/gnovm/tests/stdlibs/std" "github.com/gnolang/gno/tm2/pkg/commands" "github.com/gnolang/gno/tm2/pkg/errors" "github.com/gnolang/gno/tm2/pkg/random" - "github.com/gnolang/gno/tm2/pkg/std" "github.com/gnolang/gno/tm2/pkg/testutils" ) @@ -35,6 +37,7 @@ type testCfg struct { timeout time.Duration updateGoldenTests bool printRuntimeMetrics bool + printEvents bool withNativeFallback bool } @@ -149,6 +152,13 @@ func (c *testCfg) RegisterFlags(fs *flag.FlagSet) { false, "print runtime metrics (gas, memory, cpu cycles)", ) + + fs.BoolVar( + &c.printEvents, + "print-events", + false, + "print emitted events", + ) } func execTest(cfg *testCfg, args []string, io commands.IO) error { @@ -228,6 +238,7 @@ func gnoTestPkg( rootDir = cfg.rootDir runFlag = cfg.run printRuntimeMetrics = cfg.printRuntimeMetrics + printEvents = cfg.printEvents stdin = io.In() stdout = io.Out() @@ -290,12 +301,12 @@ func gnoTestPkg( if printRuntimeMetrics { // from tm2/pkg/sdk/vm/keeper.go // XXX: make maxAllocTx configurable. - maxAllocTx := int64(500 * 1000 * 1000) + maxAllocTx := int64(math.MaxInt64) m.Alloc = gno.NewAllocator(maxAllocTx) } m.RunMemPackage(memPkg, true) - err := runTestFiles(m, tfiles, memPkg.Name, verbose, printRuntimeMetrics, runFlag, io) + err := runTestFiles(m, tfiles, memPkg.Name, verbose, printRuntimeMetrics, printEvents, runFlag, io) if err != nil { errs = multierr.Append(errs, err) } @@ -314,7 +325,7 @@ func gnoTestPkg( m := tests.TestMachine(testStore, stdout, testPkgName) - memFiles := make([]*std.MemFile, 0, len(ifiles.FileNames())+1) + memFiles := make([]*gnovm.MemFile, 0, len(ifiles.FileNames())+1) for _, f := range memPkg.Files { for _, ifileName := range ifiles.FileNames() { if f.Name == "gno.mod" || f.Name == ifileName { @@ -329,7 +340,7 @@ func gnoTestPkg( memPkg.Path = memPkg.Path + "_test" m.RunMemPackage(memPkg, true) - err := runTestFiles(m, ifiles, testPkgName, verbose, printRuntimeMetrics, runFlag, io) + err := runTestFiles(m, ifiles, testPkgName, verbose, printRuntimeMetrics, printEvents, runFlag, io) if err != nil { errs = multierr.Append(errs, err) } @@ -419,6 +430,7 @@ func runTestFiles( pkgName string, verbose bool, printRuntimeMetrics bool, + printEvents bool, runFlag string, io commands.IO, ) (errs error) { @@ -448,10 +460,24 @@ func runTestFiles( m.RunFiles(n) for _, test := range testFuncs.Tests { + // cleanup machine between tests + tests.CleanupMachine(m) + testFuncStr := fmt.Sprintf("%q", test.Name) eval := m.Eval(gno.Call("runtest", testFuncStr)) + if printEvents { + events := m.Context.(*teststd.TestExecContext).EventLogger.Events() + if events != nil { + res, err := json.Marshal(events) + if err != nil { + panic(err) + } + io.ErrPrintfln("EVENTS: %s", string(res)) + } + } + ret := eval[0].GetString() if ret == "" { err := errors.New("failed to execute unit test: %q", test.Name) @@ -574,9 +600,10 @@ func loadTestFuncs(pkgName string, t *testFuncs, tfiles *gno.FileSet) *testFuncs // parseMemPackageTests is copied from gno.ParseMemPackageTests // for except to _filetest.gno -func parseMemPackageTests(memPkg *std.MemPackage) (tset, itset *gno.FileSet) { +func parseMemPackageTests(memPkg *gnovm.MemPackage) (tset, itset *gno.FileSet) { tset = &gno.FileSet{} itset = &gno.FileSet{} + var errs error for _, mfile := range memPkg.Files { if !strings.HasSuffix(mfile.Name, ".gno") { continue // skip this file. @@ -586,7 +613,8 @@ func parseMemPackageTests(memPkg *std.MemPackage) (tset, itset *gno.FileSet) { } n, err := gno.ParseFile(mfile.Name, mfile.Body) if err != nil { - panic(err) + errs = multierr.Append(errs, err) + continue } if n == nil { panic("should not happen") @@ -606,6 +634,9 @@ func parseMemPackageTests(memPkg *std.MemPackage) (tset, itset *gno.FileSet) { memPkg.Name, memPkg.Name, n.PkgName, mfile)) } } + if errs != nil { + panic(errs) + } return tset, itset } diff --git a/gnovm/cmd/gno/testdata/gno_test/filetest_events.txtar b/gnovm/cmd/gno/testdata/gno_test/filetest_events.txtar new file mode 100644 index 00000000000..0236872e78a --- /dev/null +++ b/gnovm/cmd/gno/testdata/gno_test/filetest_events.txtar @@ -0,0 +1,51 @@ +# Test with a valid _filetest.gno file + +gno test -print-events . + +! stdout .+ +stderr 'ok \. \d\.\d\ds' + +gno test -print-events -v . + +! stdout .+ +stderr '=== RUN file/valid_filetest.gno' +stderr '--- PASS: file/valid_filetest.gno \(\d\.\d\ds\)' +stderr 'ok \. \d\.\d\ds' + +-- valid.gno -- +package valid + +-- valid_filetest.gno -- +package main + +import "std" + +func main() { + println("test") + std.Emit("EventA") + std.Emit("EventB", "keyA", "valA") +} + +// Output: +// test + +// Events: +// [ +// { +// "type": "EventA", +// "attrs": [], +// "pkg_path": "", +// "func": "main" +// }, +// { +// "type": "EventB", +// "attrs": [ +// { +// "key": "keyA", +// "value": "valA" +// } +// ], +// "pkg_path": "", +// "func": "main" +// } +// ] diff --git a/gnovm/cmd/gno/testdata/gno_test/multitest_events.txtar b/gnovm/cmd/gno/testdata/gno_test/multitest_events.txtar new file mode 100644 index 00000000000..321c790561a --- /dev/null +++ b/gnovm/cmd/gno/testdata/gno_test/multitest_events.txtar @@ -0,0 +1,26 @@ +# Test with a valid _test.gno file + +gno test -print-events . + +! stdout .+ +stderr 'EVENTS: \[{\"type\":\"EventA\",\"attrs\":\[\],\"pkg_path\":\"gno.land/r/.*\",\"func\":\"TestA\"}\]' +stderr 'EVENTS: \[{\"type\":\"EventB\",\"attrs\":\[{\"key\":\"keyA\",\"value\":\"valA\"}\],\"pkg_path\":\"gno.land/r/.*\",\"func\":\"TestB\"},{\"type\":\"EventC\",\"attrs\":\[{\"key\":\"keyD\",\"value\":\"valD\"}\],\"pkg_path\":\"gno.land/r/.*\",\"func\":\"TestB\"}\]' +stderr 'ok \. \d\.\d\ds' + +-- valid.gno -- +package valid + +-- valid_test.gno -- +package valid + +import "testing" +import "std" + +func TestA(t *testing.T) { + std.Emit("EventA") +} + +func TestB(t *testing.T) { + std.Emit("EventB", "keyA", "valA") + std.Emit("EventC", "keyD", "valD") +} diff --git a/gnovm/cmd/gno/testdata/gno_test/test_with-native-fallback.txtar b/gnovm/cmd/gno/testdata/gno_test/test_with-native-fallback.txtar index 0954d1dd932..6099788a9a1 100644 --- a/gnovm/cmd/gno/testdata/gno_test/test_with-native-fallback.txtar +++ b/gnovm/cmd/gno/testdata/gno_test/test_with-native-fallback.txtar @@ -4,7 +4,7 @@ ! stdout .+ stderr 'panic: unknown import path net \[recovered\]' -stderr ' panic: gno.land/r/\w{8}/contract.gno:3:1: unknown import path net' +stderr ' panic: gno.land/r/\w{8}/contract.gno:3:8: unknown import path net' gno test -v --with-native-fallback . diff --git a/gnovm/cmd/gno/testdata/gno_test/unknow_lib.txtar b/gnovm/cmd/gno/testdata/gno_test/unknow_lib.txtar index 15125f695f5..37ef68f3d91 100644 --- a/gnovm/cmd/gno/testdata/gno_test/unknow_lib.txtar +++ b/gnovm/cmd/gno/testdata/gno_test/unknow_lib.txtar @@ -4,13 +4,13 @@ ! stdout .+ stderr 'panic: unknown import path foobarbaz \[recovered\]' -stderr ' panic: gno.land/r/\w{8}/contract.gno:3:1: unknown import path foobarbaz' +stderr ' panic: gno.land/r/\w{8}/contract.gno:3:8: unknown import path foobarbaz' ! gno test -v --with-native-fallback . ! stdout .+ stderr 'panic: unknown import path foobarbaz \[recovered\]' -stderr ' panic: gno.land/r/\w{8}/contract.gno:3:1: unknown import path foobarbaz' +stderr ' panic: gno.land/r/\w{8}/contract.gno:3:8: unknown import path foobarbaz' -- contract.gno -- package contract diff --git a/gnovm/gno.proto b/gnovm/gno.proto index 5f53c363b73..8a15ca96e14 100644 --- a/gnovm/gno.proto +++ b/gnovm/gno.proto @@ -1,7 +1,7 @@ syntax = "proto3"; package gno; -option go_package = "github.com/gnolang/gno/pb"; +option go_package = "github.com/gnolang/gno/gnovm/pb"; // imports import "google/protobuf/any.proto"; @@ -601,3 +601,15 @@ message tupleType { message RefType { string ID = 1; } + +// messages +message MemFile { + string name = 1; + string body = 2; +} + +message MemPackage { + string name = 1; + string path = 2; + repeated MemFile files = 3; +} diff --git a/gnovm/gnovm.proto b/gnovm/gnovm.proto new file mode 100644 index 00000000000..c9f0b23ae80 --- /dev/null +++ b/gnovm/gnovm.proto @@ -0,0 +1,16 @@ +syntax = "proto3"; +package gnovm; + +option go_package = "github.com/gnolang/gno/gnovm/pb"; + +// messages +message MemFile { + string name = 1; + string body = 2; +} + +message MemPackage { + string name = 1; + string path = 2; + repeated MemFile files = 3; +} \ No newline at end of file diff --git a/tm2/pkg/std/memfile.go b/gnovm/memfile.go similarity index 99% rename from tm2/pkg/std/memfile.go rename to gnovm/memfile.go index 01bc18c1487..a37bba6ef3d 100644 --- a/tm2/pkg/std/memfile.go +++ b/gnovm/memfile.go @@ -1,4 +1,4 @@ -package std +package gnovm import ( "fmt" diff --git a/tm2/pkg/std/memfile_test.go b/gnovm/memfile_test.go similarity index 99% rename from tm2/pkg/std/memfile_test.go rename to gnovm/memfile_test.go index 3e1fb49e131..c93c251b0e7 100644 --- a/tm2/pkg/std/memfile_test.go +++ b/gnovm/memfile_test.go @@ -1,4 +1,4 @@ -package std +package gnovm import ( "testing" diff --git a/gnovm/package.go b/gnovm/package.go new file mode 100644 index 00000000000..d6332b05709 --- /dev/null +++ b/gnovm/package.go @@ -0,0 +1,15 @@ +package gnovm + +import ( + "github.com/gnolang/gno/tm2/pkg/amino" +) + +var Package = amino.RegisterPackage(amino.NewPackage( + "github.com/gnolang/gno/gnovm", + "gnovm", + amino.GetCallersDirname(), +).WithDependencies().WithTypes( + // MemFile/MemPackage + MemFile{}, "MemFile", + MemPackage{}, "MemPackage", +)) diff --git a/gnovm/pkg/gnoenv/gnohome.go b/gnovm/pkg/gnoenv/gnohome.go index 52dd5e6adb4..9e0f1bab689 100644 --- a/gnovm/pkg/gnoenv/gnohome.go +++ b/gnovm/pkg/gnoenv/gnohome.go @@ -29,7 +29,5 @@ func HomeDir() string { } gnoHome := filepath.Join(dir, "gno") - // XXX: added april 2023 as a transitory measure - remove after test4 - fixOldDefaultGnoHome(gnoHome) return gnoHome } diff --git a/gnovm/pkg/gnoenv/migration.go b/gnovm/pkg/gnoenv/migration.go deleted file mode 100644 index 5b1d1fd1fa0..00000000000 --- a/gnovm/pkg/gnoenv/migration.go +++ /dev/null @@ -1,28 +0,0 @@ -package gnoenv - -import ( - "log" - "os" - "path/filepath" -) - -// XXX: added april 2023 as a transitory measure - remove after test4 -func fixOldDefaultGnoHome(newDir string) { - dir, err := os.UserHomeDir() - if err != nil { - return - } - oldDir := filepath.Join(dir, ".gno") - s, err := os.Stat(oldDir) - if err != nil || !s.IsDir() { - return - } - if err = os.Rename(oldDir, newDir); err != nil { - if os.IsExist(err) { - log.Printf("WARNING: attempted moving old default GNO_HOME (%q) to new (%q) but failed because directory exists.", oldDir, newDir) - log.Printf("You may need to move files from the old directory manually, or set the env var GNO_HOME to %q to retain the old directory.", oldDir) - } else { - log.Printf("WARNING: attempted moving old default GNO_HOME (%q) to new (%q) but failed with error: %v", oldDir, newDir, err) - } - } -} diff --git a/gnovm/pkg/gnoenv/migration_test.go b/gnovm/pkg/gnoenv/migration_test.go deleted file mode 100644 index 86edd8502a1..00000000000 --- a/gnovm/pkg/gnoenv/migration_test.go +++ /dev/null @@ -1,29 +0,0 @@ -package gnoenv - -import ( - "os" - "path/filepath" - "testing" - - "github.com/stretchr/testify/require" -) - -func TestFixOldDefaultGnoHome(t *testing.T) { - tempHomeDir := t.TempDir() - t.Setenv("HOME", tempHomeDir) - - oldGnoHome := filepath.Join(tempHomeDir, ".gno") - newGnoHome := filepath.Join(tempHomeDir, "gno") - - // Create a dummy old GNO_HOME - os.Mkdir(oldGnoHome, 0o755) - - // Test migration - fixOldDefaultGnoHome(newGnoHome) - - _, errOld := os.Stat(oldGnoHome) - require.NotNil(t, errOld) - _, errNew := os.Stat(newGnoHome) - require.True(t, os.IsNotExist(errOld), "invalid errors", errOld) - require.NoError(t, errNew) -} diff --git a/gnovm/pkg/gnolang/debugger.go b/gnovm/pkg/gnolang/debugger.go index 839b6a691de..f047a176af7 100644 --- a/gnovm/pkg/gnolang/debugger.go +++ b/gnovm/pkg/gnolang/debugger.go @@ -257,8 +257,10 @@ func debugUpdateLocation(m *Machine) { for i := nx - 1; i >= 0; i-- { expr := m.Exprs[i] if l := expr.GetLine(); l > 0 { - m.Debugger.loc.Line = l - m.Debugger.loc.Column = expr.GetColumn() + if col := expr.GetColumn(); col > 0 { + m.Debugger.loc.Line = l + m.Debugger.loc.Column = expr.GetColumn() + } return } } @@ -266,8 +268,10 @@ func debugUpdateLocation(m *Machine) { if len(m.Stmts) > 0 { if stmt := m.PeekStmt1(); stmt != nil { if l := stmt.GetLine(); l > 0 { - m.Debugger.loc.Line = l - m.Debugger.loc.Column = stmt.GetColumn() + if col := stmt.GetColumn(); col > 0 { + m.Debugger.loc.Line = l + m.Debugger.loc.Column = stmt.GetColumn() + } return } } @@ -648,7 +652,7 @@ func debugEvalExpr(m *Machine, node ast.Node) (tv TypedValue, err error) { return tv, fmt.Errorf("invalid selector: %s", n.Sel.Name) } for _, vp := range tr { - x = x.GetPointerTo(m.Alloc, m.Store, vp).Deref() + x = x.GetPointerToFromTV(m.Alloc, m.Store, vp).Deref() } return x, nil case *ast.IndexExpr: diff --git a/gnovm/pkg/gnolang/debugger_test.go b/gnovm/pkg/gnolang/debugger_test.go index fe059ba9f56..44786257d67 100644 --- a/gnovm/pkg/gnolang/debugger_test.go +++ b/gnovm/pkg/gnolang/debugger_test.go @@ -131,7 +131,7 @@ func TestDebug(t *testing.T) { {in: "p \"xxxx\"\n", out: `("xxxx" string)`}, {in: "si\n", out: "sample.gno:14"}, {in: "s\ns\n", out: `=> 14: var global = "test"`}, - {in: "s\n\n", out: "=> 33: num := 5"}, + {in: "s\n\n\n", out: "=> 33: num := 5"}, {in: "foo", out: "command not available: foo"}, {in: "\n\n", out: "dbg> "}, {in: "#\n", out: "dbg> "}, diff --git a/gnovm/pkg/gnolang/eval_test.go b/gnovm/pkg/gnolang/eval_test.go index 9acf4cc89f0..9b83d673767 100644 --- a/gnovm/pkg/gnolang/eval_test.go +++ b/gnovm/pkg/gnolang/eval_test.go @@ -40,8 +40,8 @@ func TestEvalFiles(t *testing.T) { if wantStacktrace != "" && !strings.Contains(stacktrace, wantStacktrace) { t.Fatalf("unexpected stacktrace\nWant: %s\n Got: %s", wantStacktrace, stacktrace) } - if wantOut != "" && out != wantOut { - t.Fatalf("unexpected output\nWant: %s\n Got: %s", wantOut, out) + if wantOut != "" && strings.TrimSpace(out) != strings.TrimSpace(wantOut) { + t.Fatalf("unexpected output\nWant: \"%s\"\n Got: \"%s\"", wantOut, out) } }) diff --git a/gnovm/pkg/gnolang/gno_test.go b/gnovm/pkg/gnolang/gno_test.go index 1f83303023c..3b15c018505 100644 --- a/gnovm/pkg/gnolang/gno_test.go +++ b/gnovm/pkg/gnolang/gno_test.go @@ -404,18 +404,6 @@ func BenchmarkBenchdata(b *testing.B) { name += "_param:" + param } b.Run(name, func(b *testing.B) { - if strings.HasPrefix(name, "matrix.gno_param") { - // CGO_ENABLED=0 go test -bench . -benchmem ./... -short -run=^$ -cpu 1,2 -count=1 ./... - // That is not just exposing test and benchmark traces as output, but these benchmarks are failing - // making the output unparseable: - /* - BenchmarkBenchdata/matrix.gno_param:3 panic: runtime error: index out of range [31] with length 25 [recovered] - panic: runtime error: index out of range [31] with length 25: - ... - */ - b.Skip("it panics causing an error when parsing benchmark results") - } - // Gen template with N and param. var buf bytes.Buffer require.NoError(b, tpl.Execute(&buf, bdataParams{ diff --git a/gnovm/pkg/gnolang/gnolang.proto b/gnovm/pkg/gnolang/gnolang.proto index eee9a0375e6..27c26534a5f 100644 --- a/gnovm/pkg/gnolang/gnolang.proto +++ b/gnovm/pkg/gnolang/gnolang.proto @@ -56,10 +56,11 @@ message FuncValue { google.protobuf.Any source = 3 [json_name = "Source"]; string name = 4 [json_name = "Name"]; google.protobuf.Any closure = 5 [json_name = "Closure"]; - string file_name = 6 [json_name = "FileName"]; - string pkg_path = 7 [json_name = "PkgPath"]; - string native_pkg = 8 [json_name = "NativePkg"]; - string native_name = 9 [json_name = "NativeName"]; + repeated TypedValue captures = 6 [json_name = "Captures"]; + string file_name = 7 [json_name = "FileName"]; + string pkg_path = 8 [json_name = "PkgPath"]; + string native_pkg = 9 [json_name = "NativePkg"]; + string native_name = 10 [json_name = "NativeName"]; } message MapValue { @@ -110,6 +111,11 @@ message RefValue { string hash = 4 [json_name = "Hash"]; } +message HeapItemValue { + ObjectInfo object_info = 1 [json_name = "ObjectInfo"]; + TypedValue value = 2 [json_name = "Value"]; +} + message ObjectID { string value = 1; } @@ -147,13 +153,15 @@ message Location { message Attributes { sint64 line = 1 [json_name = "Line"]; - string label = 2 [json_name = "Label"]; + sint64 column = 2 [json_name = "Column"]; + string label = 3 [json_name = "Label"]; } message NameExpr { Attributes attributes = 1 [json_name = "Attributes"]; ValuePath path = 2 [json_name = "Path"]; string name = 3 [json_name = "Name"]; + sint64 type = 4 [json_name = "Type"]; } message BasicLitExpr { @@ -239,6 +247,7 @@ message FuncLitExpr { StaticBlock static_block = 2 [json_name = "StaticBlock"]; FuncTypeExpr type = 3 [json_name = "Type"]; repeated google.protobuf.Any body = 4 [json_name = "Body"]; + repeated NameExpr heap_captures = 5 [json_name = "HeapCaptures"]; } message ConstExpr { @@ -602,4 +611,4 @@ message tupleType { message RefType { string id = 1 [json_name = "ID"]; -} +} \ No newline at end of file diff --git a/gnovm/pkg/gnolang/go2gno.go b/gnovm/pkg/gnolang/go2gno.go index efdfecf0289..99e051f7913 100644 --- a/gnovm/pkg/gnolang/go2gno.go +++ b/gnovm/pkg/gnolang/go2gno.go @@ -44,8 +44,8 @@ import ( "strings" "github.com/davecgh/go-spew/spew" + "github.com/gnolang/gno/gnovm" "github.com/gnolang/gno/tm2/pkg/errors" - "github.com/gnolang/gno/tm2/pkg/std" "go.uber.org/multierr" ) @@ -486,7 +486,7 @@ func Go2Gno(fs *token.FileSet, gon ast.Node) (n Node) { // MemPackageGetter implements the GetMemPackage() method. It is a subset of // [Store], separated for ease of testing. type MemPackageGetter interface { - GetMemPackage(path string) *std.MemPackage + GetMemPackage(path string) *gnovm.MemPackage } // TypeCheckMemPackage performs type validation and checking on the given @@ -496,7 +496,7 @@ type MemPackageGetter interface { // // If format is true, the code will be automatically updated with the // formatted source code. -func TypeCheckMemPackage(mempkg *std.MemPackage, getter MemPackageGetter, format bool) error { +func TypeCheckMemPackage(mempkg *gnovm.MemPackage, getter MemPackageGetter, format bool) error { var errs error imp := &gnoImporter{ getter: getter, @@ -556,7 +556,7 @@ func (g *gnoImporter) ImportFrom(path, _ string, _ types.ImportMode) (*types.Pac return result, err } -func (g *gnoImporter) parseCheckMemPackage(mpkg *std.MemPackage, fmt bool) (*types.Package, error) { +func (g *gnoImporter) parseCheckMemPackage(mpkg *gnovm.MemPackage, fmt bool) (*types.Package, error) { fset := token.NewFileSet() files := make([]*ast.File, 0, len(mpkg.Files)) var errs error @@ -754,11 +754,13 @@ func toDecls(fs *token.FileSet, gd *ast.GenDecl) (ds Decls) { name := toName(s.Name) tipe := toExpr(fs, s.Type) alias := s.Assign != 0 - ds = append(ds, &TypeDecl{ + td := &TypeDecl{ NameExpr: NameExpr{Name: name}, Type: tipe, IsAlias: alias, - }) + } + setLoc(fs, s.Pos(), td) + ds = append(ds, td) case *ast.ValueSpec: if gd.Tok == token.CONST { var names []NameExpr diff --git a/gnovm/pkg/gnolang/go2gno_test.go b/gnovm/pkg/gnolang/go2gno_test.go index d85c142ca52..8aba5d7f293 100644 --- a/gnovm/pkg/gnolang/go2gno_test.go +++ b/gnovm/pkg/gnolang/go2gno_test.go @@ -4,7 +4,7 @@ import ( "fmt" "testing" - "github.com/gnolang/gno/tm2/pkg/std" + "github.com/gnolang/gno/gnovm" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/multierr" @@ -29,9 +29,9 @@ func main(){ fmt.Printf("AST.String():\n%s\n", n.String()) } -type mockPackageGetter []*std.MemPackage +type mockPackageGetter []*gnovm.MemPackage -func (mi mockPackageGetter) GetMemPackage(path string) *std.MemPackage { +func (mi mockPackageGetter) GetMemPackage(path string) *gnovm.MemPackage { for _, pkg := range mi { if pkg.Path == path { return pkg @@ -45,7 +45,7 @@ type mockPackageGetterCounts struct { counts map[string]int } -func (mpg mockPackageGetterCounts) GetMemPackage(path string) *std.MemPackage { +func (mpg mockPackageGetterCounts) GetMemPackage(path string) *gnovm.MemPackage { mpg.counts[path]++ return mpg.mockPackageGetter.GetMemPackage(path) } @@ -77,17 +77,17 @@ func TestTypeCheckMemPackage(t *testing.T) { type testCase struct { name string - pkg *std.MemPackage + pkg *gnovm.MemPackage getter MemPackageGetter check func(*testing.T, error) } tt := []testCase{ { "Simple", - &std.MemPackage{ + &gnovm.MemPackage{ Name: "hello", Path: "gno.land/p/demo/hello", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "hello.gno", Body: ` @@ -103,10 +103,10 @@ func TestTypeCheckMemPackage(t *testing.T) { }, { "WrongReturn", - &std.MemPackage{ + &gnovm.MemPackage{ Name: "hello", Path: "gno.land/p/demo/hello", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "hello.gno", Body: ` @@ -122,10 +122,10 @@ func TestTypeCheckMemPackage(t *testing.T) { }, { "ParseError", - &std.MemPackage{ + &gnovm.MemPackage{ Name: "hello", Path: "gno.land/p/demo/hello", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "hello.gno", Body: ` @@ -139,10 +139,10 @@ func TestTypeCheckMemPackage(t *testing.T) { }, { "MultiError", - &std.MemPackage{ + &gnovm.MemPackage{ Name: "main", Path: "gno.land/p/demo/main", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "hello.gno", Body: ` @@ -159,10 +159,10 @@ func TestTypeCheckMemPackage(t *testing.T) { }, { "TestsIgnored", - &std.MemPackage{ + &gnovm.MemPackage{ Name: "hello", Path: "gno.land/p/demo/hello", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "hello.gno", Body: ` @@ -181,10 +181,10 @@ func TestTypeCheckMemPackage(t *testing.T) { }, { "ImportFailed", - &std.MemPackage{ + &gnovm.MemPackage{ Name: "hello", Path: "gno.land/p/demo/hello", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "hello.gno", Body: ` @@ -199,10 +199,10 @@ func TestTypeCheckMemPackage(t *testing.T) { }, { "ImportSucceeded", - &std.MemPackage{ + &gnovm.MemPackage{ Name: "hello", Path: "gno.land/p/demo/hello", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "hello.gno", Body: ` @@ -213,12 +213,12 @@ func TestTypeCheckMemPackage(t *testing.T) { }, }, mockPackageGetter{ - &std.MemPackage{ + &gnovm.MemPackage{ Name: "std", Path: "std", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { - Name: "std.gno", + Name: "gnovm.gno", Body: ` package std type Address string`, @@ -230,10 +230,10 @@ func TestTypeCheckMemPackage(t *testing.T) { }, { "ImportBadIdent", - &std.MemPackage{ + &gnovm.MemPackage{ Name: "hello", Path: "gno.land/p/demo/hello", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "hello.gno", Body: ` @@ -244,12 +244,12 @@ func TestTypeCheckMemPackage(t *testing.T) { }, }, mockPackageGetter{ - &std.MemPackage{ + &gnovm.MemPackage{ Name: "a_completely_different_identifier", Path: "std", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { - Name: "std.gno", + Name: "gnovm.gno", Body: ` package a_completely_different_identifier type Address string`, @@ -263,10 +263,10 @@ func TestTypeCheckMemPackage(t *testing.T) { cacheMpg := mockPackageGetterCounts{ mockPackageGetter{ - &std.MemPackage{ + &gnovm.MemPackage{ Name: "bye", Path: "bye", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "bye.gno", Body: ` @@ -276,12 +276,12 @@ func TestTypeCheckMemPackage(t *testing.T) { }, }, }, - &std.MemPackage{ + &gnovm.MemPackage{ Name: "std", Path: "std", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { - Name: "std.gno", + Name: "gnovm.gno", Body: ` package std type Address string`, @@ -295,10 +295,10 @@ func TestTypeCheckMemPackage(t *testing.T) { tt = append(tt, testCase{ "ImportWithCache", // This test will make use of the importer's internal cache for package `std`. - &std.MemPackage{ + &gnovm.MemPackage{ Name: "hello", Path: "gno.land/p/demo/hello", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "hello.gno", Body: ` @@ -347,10 +347,10 @@ func TestTypeCheckMemPackage_format(t *testing.T) { ` - pkg := &std.MemPackage{ + pkg := &gnovm.MemPackage{ Name: "hello", Path: "gno.land/p/demo/hello", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "hello.gno", Body: input, diff --git a/gnovm/pkg/gnolang/gonative.go b/gnovm/pkg/gnolang/gonative.go index 6127fa42b07..fe92f5bcd23 100644 --- a/gnovm/pkg/gnolang/gonative.go +++ b/gnovm/pkg/gnolang/gonative.go @@ -866,7 +866,7 @@ func gno2GoType(t Type) reflect.Type { return rt } else { // NOTE: can this be implemented in go1.15? i think not. - panic("not yet supported") + panic("gno2go conversion of type not yet supported: " + ct.String()) } case *TypeType: panic("should not happen") @@ -1258,16 +1258,25 @@ func (x *PackageNode) DefineGoNativeType(rt reflect.Type) { x.Define(Name(name), asValue(nt)) } -func (x *PackageNode) DefineGoNativeValue(n Name, nv interface{}) { +func (x *PackageNode) DefineGoNativeValue(name Name, nv interface{}) { + x.defineGoNativeValue(false, name, nv) +} + +func (x *PackageNode) DefineGoNativeConstValue(name Name, nv interface{}) { + x.defineGoNativeValue(true, name, nv) +} + +func (x *PackageNode) defineGoNativeValue(isConst bool, n Name, nv interface{}) { if debug { - debug.Printf("*PackageNode.DefineGoNativeValue(%s)\n", reflect.ValueOf(nv).String()) + debug.Printf("*PackageNode.defineGoNativeValue(%s)\n", reflect.ValueOf(nv).String()) } rv := reflect.ValueOf(nv) // rv is not settable, so create something that is. rt := rv.Type() rv2 := reflect.New(rt).Elem() rv2.Set(rv) - x.Define(n, go2GnoValue(nilAllocator, rv2)) + tv := go2GnoValue(nilAllocator, rv2) + x.Define2(isConst, n, tv.T, tv) } // ---------------------------------------- diff --git a/gnovm/pkg/gnolang/kind_string.go b/gnovm/pkg/gnolang/kind_string.go index cbe6bfa8e33..12e95829b20 100644 --- a/gnovm/pkg/gnolang/kind_string.go +++ b/gnovm/pkg/gnolang/kind_string.go @@ -36,13 +36,14 @@ func _() { _ = x[MapKind-25] _ = x[TypeKind-26] _ = x[BlockKind-27] - _ = x[TupleKind-28] - _ = x[RefTypeKind-29] + _ = x[HeapItemKind-28] + _ = x[TupleKind-29] + _ = x[RefTypeKind-30] } -const _Kind_name = "InvalidKindBoolKindStringKindIntKindInt8KindInt16KindInt32KindInt64KindUintKindUint8KindUint16KindUint32KindUint64KindFloat32KindFloat64KindBigintKindBigdecKindArrayKindSliceKindPointerKindStructKindPackageKindInterfaceKindChanKindFuncKindMapKindTypeKindBlockKindTupleKindRefTypeKind" +const _Kind_name = "InvalidKindBoolKindStringKindIntKindInt8KindInt16KindInt32KindInt64KindUintKindUint8KindUint16KindUint32KindUint64KindFloat32KindFloat64KindBigintKindBigdecKindArrayKindSliceKindPointerKindStructKindPackageKindInterfaceKindChanKindFuncKindMapKindTypeKindBlockKindHeapItemKindTupleKindRefTypeKind" -var _Kind_index = [...]uint16{0, 11, 19, 29, 36, 44, 53, 62, 71, 79, 88, 98, 108, 118, 129, 140, 150, 160, 169, 178, 189, 199, 210, 223, 231, 239, 246, 254, 263, 272, 283} +var _Kind_index = [...]uint16{0, 11, 19, 29, 36, 44, 53, 62, 71, 79, 88, 98, 108, 118, 129, 140, 150, 160, 169, 178, 189, 199, 210, 223, 231, 239, 246, 254, 263, 275, 284, 295} func (i Kind) String() string { if i >= Kind(len(_Kind_index)-1) { diff --git a/gnovm/pkg/gnolang/machine.go b/gnovm/pkg/gnolang/machine.go index a0542bf9713..09be71682a5 100644 --- a/gnovm/pkg/gnolang/machine.go +++ b/gnovm/pkg/gnolang/machine.go @@ -8,14 +8,16 @@ import ( "io" "os" "reflect" + "slices" + "strconv" "strings" "sync" "testing" "github.com/gnolang/overflow" + "github.com/gnolang/gno/gnovm" "github.com/gnolang/gno/tm2/pkg/errors" - "github.com/gnolang/gno/tm2/pkg/std" "github.com/gnolang/gno/tm2/pkg/store" ) @@ -263,7 +265,7 @@ func (m *Machine) PreprocessAllFilesAndSaveBlockNodes() { // Parses files, sets the package if doesn't exist, runs files, saves mempkg // and corresponding package node, package value, and types to store. Save // is set to false for tests where package values may be native. -func (m *Machine) RunMemPackage(memPkg *std.MemPackage, save bool) (*PackageNode, *PackageValue) { +func (m *Machine) RunMemPackage(memPkg *gnovm.MemPackage, save bool) (*PackageNode, *PackageValue) { return m.runMemPackage(memPkg, save, false) } @@ -271,15 +273,17 @@ func (m *Machine) RunMemPackage(memPkg *std.MemPackage, save bool) (*PackageNode // declarations are filtered removing duplicate declarations. // To control which declaration overrides which, use [ReadMemPackageFromList], // putting the overrides at the top of the list. -func (m *Machine) RunMemPackageWithOverrides(memPkg *std.MemPackage, save bool) (*PackageNode, *PackageValue) { +func (m *Machine) RunMemPackageWithOverrides(memPkg *gnovm.MemPackage, save bool) (*PackageNode, *PackageValue) { return m.runMemPackage(memPkg, save, true) } -func (m *Machine) runMemPackage(memPkg *std.MemPackage, save, overrides bool) (*PackageNode, *PackageValue) { +func (m *Machine) runMemPackage(memPkg *gnovm.MemPackage, save, overrides bool) (*PackageNode, *PackageValue) { // parse files. files := ParseMemPackage(memPkg) - if !overrides && checkDuplicates(files) { - panic(fmt.Errorf("running package %q: duplicate declarations not allowed", memPkg.Path)) + if !overrides { + if err := checkDuplicates(files); err != nil { + panic(fmt.Errorf("running package %q: %w", memPkg.Path, err)) + } } // make and set package if doesn't exist. pn := (*PackageNode)(nil) @@ -322,9 +326,31 @@ func (m *Machine) runMemPackage(memPkg *std.MemPackage, save, overrides bool) (* return pn, pv } -// checkDuplicates returns true if there duplicate declarations in the fset. -func checkDuplicates(fset *FileSet) bool { +type redeclarationErrors []Name + +func (r redeclarationErrors) Error() string { + var b strings.Builder + b.WriteString("redeclarations for identifiers: ") + for idx, s := range r { + b.WriteString(strconv.Quote(string(s))) + if idx != len(r)-1 { + b.WriteString(", ") + } + } + return b.String() +} + +func (r redeclarationErrors) add(newI Name) redeclarationErrors { + if slices.Contains(r, newI) { + return r + } + return append(r, newI) +} + +// checkDuplicates returns an error if there are duplicate declarations in the fset. +func checkDuplicates(fset *FileSet) error { defined := make(map[Name]struct{}, 128) + var duplicated redeclarationErrors for _, f := range fset.Files { for _, d := range f.Decls { var name Name @@ -345,7 +371,7 @@ func checkDuplicates(fset *FileSet) bool { continue } if _, ok := defined[nx.Name]; ok { - return true + duplicated = duplicated.add(nx.Name) } defined[nx.Name] = struct{}{} } @@ -357,12 +383,15 @@ func checkDuplicates(fset *FileSet) bool { continue } if _, ok := defined[name]; ok { - return true + duplicated = duplicated.add(name) } defined[name] = struct{}{} } } - return false + if len(duplicated) > 0 { + return duplicated + } + return nil } func destar(x Expr) Expr { @@ -377,7 +406,7 @@ func destar(x Expr) Expr { // The resulting package value and node become injected with TestMethods and // other declarations, so it is expected that non-test code will not be run // afterwards from the same store. -func (m *Machine) TestMemPackage(t *testing.T, memPkg *std.MemPackage) { +func (m *Machine) TestMemPackage(t *testing.T, memPkg *gnovm.MemPackage) { defer m.injectLocOnPanic() DisableDebug() fmt.Println("DEBUG DISABLED (FOR TEST DEPENDENCIES INIT)") @@ -670,7 +699,7 @@ func (m *Machine) runFileDecls(fns ...*FileNode) []TypedValue { } } // if dep already in loopfindr, abort. - if hasName(dep, loopfindr) { + if slices.Contains(loopfindr, dep) { if _, ok := (*depdecl).(*FuncDecl); ok { // recursive function dependencies // are OK with func decls. @@ -2083,15 +2112,25 @@ func (m *Machine) PushForPointer(lx Expr) { func (m *Machine) PopAsPointer(lx Expr) PointerValue { switch lx := lx.(type) { case *NameExpr: - lb := m.LastBlock() - return lb.GetPointerTo(m.Store, lx.Path) + switch lx.Type { + case NameExprTypeNormal: + lb := m.LastBlock() + return lb.GetPointerTo(m.Store, lx.Path) + case NameExprTypeHeapUse: + lb := m.LastBlock() + return lb.GetPointerToHeapUse(m.Store, lx.Path) + case NameExprTypeHeapClosure: + panic("should not happen") + default: + panic("unexpected NameExpr in PopAsPointer") + } case *IndexExpr: iv := m.PopValue() xv := m.PopValue() return xv.GetPointerAtIndex(m.Alloc, m.Store, iv) case *SelectorExpr: xv := m.PopValue() - return xv.GetPointerTo(m.Alloc, m.Store, lx.Path) + return xv.GetPointerToFromTV(m.Alloc, m.Store, lx.Path) case *StarExpr: ptr := m.PopValue().V.(PointerValue) return ptr @@ -2319,15 +2358,3 @@ func (m *Machine) ExceptionsStacktrace() string { return builder.String() } - -//---------------------------------------- -// utility - -func hasName(n Name, ns []Name) bool { - for _, n2 := range ns { - if n == n2 { - return true - } - } - return false -} diff --git a/gnovm/pkg/gnolang/machine_test.go b/gnovm/pkg/gnolang/machine_test.go index 8e27b127fbb..c3b2118f099 100644 --- a/gnovm/pkg/gnolang/machine_test.go +++ b/gnovm/pkg/gnolang/machine_test.go @@ -4,8 +4,8 @@ import ( "fmt" "testing" + "github.com/gnolang/gno/gnovm" "github.com/gnolang/gno/tm2/pkg/db/memdb" - "github.com/gnolang/gno/tm2/pkg/std" "github.com/gnolang/gno/tm2/pkg/store/dbadapter" "github.com/gnolang/gno/tm2/pkg/store/iavl" stypes "github.com/gnolang/gno/tm2/pkg/store/types" @@ -27,10 +27,10 @@ func TestRunMemPackageWithOverrides_revertToOld(t *testing.T) { iavlStore := iavl.StoreConstructor(db, stypes.StoreOptions{}) store := NewStore(nil, baseStore, iavlStore) m := NewMachine("std", store) - m.RunMemPackageWithOverrides(&std.MemPackage{ + m.RunMemPackageWithOverrides(&gnovm.MemPackage{ Name: "std", Path: "std", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ {Name: "a.gno", Body: `package std; func Redecl(x int) string { return "1" }`}, }, }, true) @@ -38,10 +38,10 @@ func TestRunMemPackageWithOverrides_revertToOld(t *testing.T) { defer func() { p = fmt.Sprint(recover()) }() - m.RunMemPackageWithOverrides(&std.MemPackage{ + m.RunMemPackageWithOverrides(&gnovm.MemPackage{ Name: "std", Path: "std", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ {Name: "b.gno", Body: `package std; func Redecl(x int) string { var y string; _, _ = y; return "2" }`}, }, }, true) diff --git a/gnovm/pkg/gnolang/nodes.go b/gnovm/pkg/gnolang/nodes.go index b18ed157ca6..c282b619fdc 100644 --- a/gnovm/pkg/gnolang/nodes.go +++ b/gnovm/pkg/gnolang/nodes.go @@ -12,8 +12,9 @@ import ( "strconv" "strings" + "github.com/gnolang/gno/gnovm" "github.com/gnolang/gno/tm2/pkg/errors" - "github.com/gnolang/gno/tm2/pkg/std" + "go.uber.org/multierr" ) // ---------------------------------------- @@ -145,11 +146,26 @@ func (loc Location) IsZero() bool { // even after preprocessing. Temporary attributes (e.g. those // for preprocessing) are stored in .data. +type GnoAttribute string + +const ( + ATTR_PREPROCESSED GnoAttribute = "ATTR_PREPROCESSED" + ATTR_PREDEFINED GnoAttribute = "ATTR_PREDEFINED" + ATTR_TYPE_VALUE GnoAttribute = "ATTR_TYPE_VALUE" + ATTR_TYPEOF_VALUE GnoAttribute = "ATTR_TYPEOF_VALUE" + ATTR_IOTA GnoAttribute = "ATTR_IOTA" + ATTR_LOCATIONED GnoAttribute = "ATTR_LOCATIONE" // XXX DELETE + ATTR_GOTOLOOP_STMT GnoAttribute = "ATTR_GOTOLOOP_STMT" // XXX delete? + ATTR_LOOP_DEFINES GnoAttribute = "ATTR_LOOP_DEFINES" // []Name defined within loops. + ATTR_LOOP_USES GnoAttribute = "ATTR_LOOP_USES" // []Name loop defines actually used. + ATTR_SHIFT_RHS GnoAttribute = "ATTR_SHIFT_RHS" +) + type Attributes struct { Line int Column int Label Name - data map[interface{}]interface{} // not persisted + data map[GnoAttribute]interface{} // not persisted } func (attr *Attributes) GetLine() int { @@ -176,22 +192,31 @@ func (attr *Attributes) SetLabel(label Name) { attr.Label = label } -func (attr *Attributes) HasAttribute(key interface{}) bool { +func (attr *Attributes) HasAttribute(key GnoAttribute) bool { _, ok := attr.data[key] return ok } -func (attr *Attributes) GetAttribute(key interface{}) interface{} { +// GnoAttribute must not be user provided / arbitrary, +// otherwise will create potential exploits. +func (attr *Attributes) GetAttribute(key GnoAttribute) interface{} { return attr.data[key] } -func (attr *Attributes) SetAttribute(key interface{}, value interface{}) { +func (attr *Attributes) SetAttribute(key GnoAttribute, value interface{}) { if attr.data == nil { - attr.data = make(map[interface{}]interface{}) + attr.data = make(map[GnoAttribute]interface{}) } attr.data[key] = value } +func (attr *Attributes) DelAttribute(key GnoAttribute) { + if debug && attr.data == nil { + panic("should not happen, attribute is expected to be non-empty.") + } + delete(attr.data, key) +} + // ---------------------------------------- // Node @@ -205,9 +230,10 @@ type Node interface { SetColumn(int) GetLabel() Name SetLabel(Name) - HasAttribute(key interface{}) bool - GetAttribute(key interface{}) interface{} - SetAttribute(key interface{}, value interface{}) + HasAttribute(key GnoAttribute) bool + GetAttribute(key GnoAttribute) interface{} + SetAttribute(key GnoAttribute, value interface{}) + DelAttribute(key GnoAttribute) } // non-pointer receiver to help make immutable. @@ -367,11 +393,22 @@ var ( _ Expr = &ConstExpr{} ) +type NameExprType int + +const ( + NameExprTypeNormal NameExprType = iota // default + NameExprTypeDefine // when defining normally + NameExprTypeHeapDefine // when defining escaped name in loop + NameExprTypeHeapUse // when above used in non-define lhs/rhs + NameExprTypeHeapClosure // when closure captures name +) + type NameExpr struct { Attributes // TODO rename .Path's to .ValuePaths. Path ValuePath // set by preprocessor. Name + Type NameExprType } type NameExprs []NameExpr @@ -498,8 +535,9 @@ type KeyValueExprs []KeyValueExpr type FuncLitExpr struct { Attributes StaticBlock - Type FuncTypeExpr // function type - Body // function body + Type FuncTypeExpr // function type + Body // function body + HeapCaptures NameExprs // filled in findLoopUses1 } // The preprocessor replaces const expressions @@ -580,11 +618,15 @@ func (ftxz FieldTypeExprs) IsNamed() bool { named := false for i, ftx := range ftxz { if i == 0 { - named = ftx.Name != "" + if ftx.Name == "" || isHiddenResultVariable(string(ftx.Name)) { + named = false + } else { + named = true + } } else { if named && ftx.Name == "" { panic("[]FieldTypeExpr has inconsistent namedness (starts named)") - } else if !named && ftx.Name != "" { + } else if !named && (ftx.Name != "" || !isHiddenResultVariable(string(ftx.Name))) { panic("[]FieldTypeExpr has inconsistent namedness (starts unnamed)") } } @@ -1110,7 +1152,7 @@ func PackageNameFromFileBody(name, body string) Name { // // NOTE: panics if package name is invalid (characters must be alphanumeric or _, // lowercase, and must start with a letter). -func ReadMemPackage(dir string, pkgPath string) *std.MemPackage { +func ReadMemPackage(dir string, pkgPath string) *gnovm.MemPackage { files, err := os.ReadDir(dir) if err != nil { panic(err) @@ -1144,14 +1186,14 @@ func ReadMemPackage(dir string, pkgPath string) *std.MemPackage { return ReadMemPackageFromList(list, pkgPath) } -// ReadMemPackageFromList creates a new [std.MemPackage] with the specified pkgPath, +// ReadMemPackageFromList creates a new [gnovm.MemPackage] with the specified pkgPath, // containing the contents of all the files provided in the list slice. // No parsing or validation is done on the filenames. // // NOTE: panics if package name is invalid (characters must be alphanumeric or _, // lowercase, and must start with a letter). -func ReadMemPackageFromList(list []string, pkgPath string) *std.MemPackage { - memPkg := &std.MemPackage{Path: pkgPath} +func ReadMemPackageFromList(list []string, pkgPath string) *gnovm.MemPackage { + memPkg := &gnovm.MemPackage{Path: pkgPath} var pkgName Name for _, fpath := range list { fname := filepath.Base(fpath) @@ -1167,7 +1209,7 @@ func ReadMemPackageFromList(list []string, pkgPath string) *std.MemPackage { } } memPkg.Files = append(memPkg.Files, - &std.MemFile{ + &gnovm.MemFile{ Name: fname, Body: string(bz), }) @@ -1187,8 +1229,9 @@ func ReadMemPackageFromList(list []string, pkgPath string) *std.MemPackage { // // If one of the files has a different package name than memPkg.Name, // or [ParseFile] returns an error, ParseMemPackage panics. -func ParseMemPackage(memPkg *std.MemPackage) (fset *FileSet) { +func ParseMemPackage(memPkg *gnovm.MemPackage) (fset *FileSet) { fset = &FileSet{} + var errs error for _, mfile := range memPkg.Files { if !strings.HasSuffix(mfile.Name, ".gno") || endsWith(mfile.Name, []string{"_test.gno", "_filetest.gno"}) { @@ -1196,7 +1239,8 @@ func ParseMemPackage(memPkg *std.MemPackage) (fset *FileSet) { } n, err := ParseFile(mfile.Name, mfile.Body) if err != nil { - panic(err) + errs = multierr.Append(errs, err) + continue } if memPkg.Name != string(n.PkgName) { panic(fmt.Sprintf( @@ -1206,10 +1250,13 @@ func ParseMemPackage(memPkg *std.MemPackage) (fset *FileSet) { // add package file. fset.AddFiles(n) } + if errs != nil { + panic(errs) + } return fset } -func ParseMemPackageTests(memPkg *std.MemPackage) (tset, itset *FileSet) { +func ParseMemPackageTests(memPkg *gnovm.MemPackage) (tset, itset *FileSet) { tset = &FileSet{} itset = &FileSet{} for _, mfile := range memPkg.Files { @@ -1483,6 +1530,7 @@ type BlockNode interface { GetNumNames() uint16 GetParentNode(Store) BlockNode GetPathForName(Store, Name) ValuePath + GetBlockNodeForPath(Store, ValuePath) BlockNode GetIsConst(Store, Name) bool GetLocalIndex(Name) (uint16, bool) GetValueRef(Store, Name, bool) *TypedValue @@ -1582,6 +1630,8 @@ func (sb *StaticBlock) GetBlockNames() (ns []Name) { } // Implements BlockNode. +// NOTE: Extern names may also be local, if declared after usage as an extern +// (thus shadowing the extern name). func (sb *StaticBlock) GetExternNames() (ns []Name) { return sb.Externs // copy? } @@ -1623,6 +1673,9 @@ func (sb *StaticBlock) GetPathForName(store Store, n Name) ValuePath { } // Register as extern. // NOTE: uverse names are externs too. + // NOTE: externs may also be shadowed later in the block. Thus, usages + // before the declaration will have depth > 1; following it, depth == 1, + // matching the two different identifiers they refer to. if !isFile(sb.GetSource(store)) { sb.GetStaticBlock().addExternName(n) } @@ -1651,6 +1704,21 @@ func (sb *StaticBlock) GetPathForName(store Store, n Name) ValuePath { panic(fmt.Sprintf("name %s not declared", n)) } +// Get the containing block node for node with path relative to this containing block. +func (sb *StaticBlock) GetBlockNodeForPath(store Store, path ValuePath) BlockNode { + if path.Type != VPBlock { + panic("expected block type value path but got " + path.Type.String()) + } + + // NOTE: path.Depth == 1 means it's in bn. + bn := sb.GetSource(store) + for i := 1; i < int(path.Depth); i++ { + bn = bn.GetParentNode(store) + } + + return bn +} + // Returns whether a name defined here in in ancestry is a const. // This is not the same as whether a name's static type is // untyped -- as in c := a == b, a name may be an untyped non-const. @@ -1707,21 +1775,12 @@ func (sb *StaticBlock) GetStaticTypeOf(store Store, n Name) Type { // Implements BlockNode. func (sb *StaticBlock) GetStaticTypeOfAt(store Store, path ValuePath) Type { if debug { - if path.Type != VPBlock { - panic("should not happen") - } if path.Depth == 0 { panic("should not happen") } } - for { - if path.Depth == 1 { - return sb.Types[path.Index] - } else { - sb = sb.GetParentNode(store).GetStaticBlock() - path.Depth -= 1 - } - } + bn := sb.GetBlockNodeForPath(store, path) + return bn.GetStaticBlock().Types[path.Index] } // Implements BlockNode. @@ -2109,18 +2168,6 @@ func (x *BasicLitExpr) GetInt() int { return i } -type GnoAttribute string - -const ( - ATTR_PREPROCESSED GnoAttribute = "ATTR_PREPROCESSED" - ATTR_PREDEFINED GnoAttribute = "ATTR_PREDEFINED" - ATTR_TYPE_VALUE GnoAttribute = "ATTR_TYPE_VALUE" - ATTR_TYPEOF_VALUE GnoAttribute = "ATTR_TYPEOF_VALUE" - ATTR_IOTA GnoAttribute = "ATTR_IOTA" - ATTR_LOCATIONED GnoAttribute = "ATTR_LOCATIONED" - ATTR_INJECTED GnoAttribute = "ATTR_INJECTED" -) - var rePkgName = regexp.MustCompile(`^[a-z][a-z0-9_]+$`) // TODO: consider length restrictions. @@ -2130,3 +2177,12 @@ func validatePkgName(name string) { panic(fmt.Sprintf("cannot create package with invalid name %q", name)) } } + +const hiddenResultVariable = ".res_" + +func isHiddenResultVariable(name string) bool { + if strings.HasPrefix(name, hiddenResultVariable) { + return true + } + return false +} diff --git a/gnovm/pkg/gnolang/nodes_string.go b/gnovm/pkg/gnolang/nodes_string.go index 547ad83294d..e16e2f182a5 100644 --- a/gnovm/pkg/gnolang/nodes_string.go +++ b/gnovm/pkg/gnolang/nodes_string.go @@ -96,7 +96,20 @@ func (vp ValuePath) String() string { } func (x NameExpr) String() string { - return fmt.Sprintf("%s<%s>", x.Name, x.Path.String()) + switch x.Type { + case NameExprTypeNormal: + return fmt.Sprintf("%s<%s>", x.Name, x.Path.String()) + case NameExprTypeDefine: + return fmt.Sprintf("%s", x.Name, x.Path.String()) + case NameExprTypeHeapDefine: + return fmt.Sprintf("%s", x.Name, x.Path.String()) + case NameExprTypeHeapUse: + return fmt.Sprintf("%s<~%s>", x.Name, x.Path.String()) + case NameExprTypeHeapClosure: + return fmt.Sprintf("%s<()~%s>", x.Name, x.Path.String()) + default: + panic("unexpected NameExpr type") + } } func (x BasicLitExpr) String() string { @@ -172,7 +185,11 @@ func (x CompositeLitExpr) String() string { } func (x FuncLitExpr) String() string { - return fmt.Sprintf("func %s{ %s }", x.Type, x.Body.String()) + heapCaptures := "" + if len(x.HeapCaptures) > 0 { + heapCaptures = "<" + x.HeapCaptures.String() + ">" + } + return fmt.Sprintf("func %s{ %s }%s", x.Type, x.Body.String(), heapCaptures) } func (x KeyValueExpr) String() string { diff --git a/gnovm/pkg/gnolang/op_assign.go b/gnovm/pkg/gnolang/op_assign.go index eb67ffcc351..8caacbfd1e6 100644 --- a/gnovm/pkg/gnolang/op_assign.go +++ b/gnovm/pkg/gnolang/op_assign.go @@ -11,7 +11,7 @@ func (m *Machine) doOpDefine() { // Get name and value of i'th term. nx := s.Lhs[i].(*NameExpr) // Finally, define (or assign if loop block). - ptr := lb.GetPointerTo(m.Store, nx.Path) + ptr := lb.GetPointerToMaybeHeapDefine(m.Store, nx) // XXX HACK (until value persistence impl'd) if m.ReadOnly { if oo, ok := ptr.Base.(Object); ok { diff --git a/gnovm/pkg/gnolang/op_binary.go b/gnovm/pkg/gnolang/op_binary.go index db3c1e5695c..24123d285ad 100644 --- a/gnovm/pkg/gnolang/op_binary.go +++ b/gnovm/pkg/gnolang/op_binary.go @@ -1097,6 +1097,7 @@ func xorAssign(lv, rv *TypedValue) { // for doOpShl and doOpShlAssign. func shlAssign(lv, rv *TypedValue) { + rv.AssertNonNegative("runtime error: negative shift amount") // set the result in lv. // NOTE: baseOf(rv.T) is always UintType. switch baseOf(lv.T) { @@ -1136,6 +1137,7 @@ func shlAssign(lv, rv *TypedValue) { // for doOpShr and doOpShrAssign. func shrAssign(lv, rv *TypedValue) { + rv.AssertNonNegative("runtime error: negative shift amount") // set the result in lv. // NOTE: baseOf(rv.T) is always UintType. switch baseOf(lv.T) { diff --git a/gnovm/pkg/gnolang/op_call.go b/gnovm/pkg/gnolang/op_call.go index 15531ec610d..ba5b7507cff 100644 --- a/gnovm/pkg/gnolang/op_call.go +++ b/gnovm/pkg/gnolang/op_call.go @@ -27,6 +27,11 @@ func (m *Machine) doOpPrecall() { case TypeValue: // Do not pop type yet. // No need for frames. + xv := m.PeekValue(1) + if cx.GetAttribute(ATTR_SHIFT_RHS) == true { + xv.AssertNonNegative("runtime error: negative shift amount") + } + m.PushOp(OpConvert) if debug { if len(cx.Args) != 1 { @@ -57,6 +62,18 @@ func (m *Machine) doOpCall() { // Create new block scope. clo := fr.Func.GetClosure(m.Store) b := m.Alloc.NewBlock(fr.Func.GetSource(m.Store), clo) + + // Copy *FuncValue.Captures into block + // NOTE: addHeapCapture in preprocess ensures order. + if len(fv.Captures) != 0 { + if len(fv.Captures) > len(b.Values) { + panic("should not happen, length of captured variables must not exceed the number of values") + } + for i := 0; i < len(fv.Captures); i++ { + b.Values[len(b.Values)-len(fv.Captures)+i] = fv.Captures[i].Copy(m.Alloc) + } + } + m.PushBlock(b) if fv.nativeBody == nil && fv.NativePkg != "" { // native function, unmarshaled so doesn't have nativeBody yet @@ -78,6 +95,7 @@ func (m *Machine) doOpCall() { // Initialize return variables with default value. numParams := len(ft.Params) for i, rt := range ft.Results { + // results/parameters never are heap use/closure. ptr := b.GetPointerToInt(nil, numParams+i) dtv := defaultTypedValue(m.Alloc, rt.Type) ptr.Assign2(m.Alloc, nil, nil, dtv, false) @@ -287,6 +305,15 @@ func (m *Machine) doOpReturnCallDefers() { // Create new block scope for defer. clo := dfr.Func.GetClosure(m.Store) b := m.Alloc.NewBlock(fv.GetSource(m.Store), clo) + // copy values from captures + if len(fv.Captures) != 0 { + if len(fv.Captures) > len(b.Values) { + panic("should not happen, length of captured variables must not exceed the number of values") + } + for i := 0; i < len(fv.Captures); i++ { + b.Values[len(b.Values)-len(fv.Captures)+i] = fv.Captures[i].Copy(m.Alloc) + } + } m.PushBlock(b) if fv.nativeBody == nil { fbody := fv.GetBodyFromSource(m.Store) diff --git a/gnovm/pkg/gnolang/op_decl.go b/gnovm/pkg/gnolang/op_decl.go index 2c20c43ae2f..c9c04ccf76d 100644 --- a/gnovm/pkg/gnolang/op_decl.go +++ b/gnovm/pkg/gnolang/op_decl.go @@ -58,8 +58,8 @@ func (m *Machine) doOpValueDecl() { } else if isUntyped(tv.T) { ConvertUntypedTo(&tv, nil) } - nx := s.NameExprs[i] - ptr := lb.GetPointerTo(m.Store, nx.Path) + nx := &s.NameExprs[i] + ptr := lb.GetPointerToMaybeHeapDefine(m.Store, nx) ptr.Assign2(m.Alloc, m.Store, m.Realm, tv, false) } } diff --git a/gnovm/pkg/gnolang/op_eval.go b/gnovm/pkg/gnolang/op_eval.go index 701615fff13..1beba1d6e3f 100644 --- a/gnovm/pkg/gnolang/op_eval.go +++ b/gnovm/pkg/gnolang/op_eval.go @@ -36,7 +36,7 @@ func (m *Machine) doOpEval() { // Get value from scope. lb := m.LastBlock() // Push value, done. - ptr := lb.GetPointerTo(m.Store, nx.Path) + ptr := lb.GetPointerToMaybeHeapUse(m.Store, nx) m.PushValue(ptr.Deref()) return } diff --git a/gnovm/pkg/gnolang/op_exec.go b/gnovm/pkg/gnolang/op_exec.go index c7e8ffd600c..a61349b0806 100644 --- a/gnovm/pkg/gnolang/op_exec.go +++ b/gnovm/pkg/gnolang/op_exec.go @@ -171,8 +171,8 @@ func (m *Machine) doOpExec(op Op) { case ASSIGN: m.PopAsPointer(bs.Key).Assign2(m.Alloc, m.Store, m.Realm, iv, false) case DEFINE: - knxp := bs.Key.(*NameExpr).Path - ptr := m.LastBlock().GetPointerTo(m.Store, knxp) + knx := bs.Key.(*NameExpr) + ptr := m.LastBlock().GetPointerToMaybeHeapDefine(m.Store, knx) ptr.TV.Assign(m.Alloc, iv, false) default: panic("should not happen") @@ -186,8 +186,8 @@ func (m *Machine) doOpExec(op Op) { case ASSIGN: m.PopAsPointer(bs.Value).Assign2(m.Alloc, m.Store, m.Realm, ev, false) case DEFINE: - vnxp := bs.Value.(*NameExpr).Path - ptr := m.LastBlock().GetPointerTo(m.Store, vnxp) + vnx := bs.Value.(*NameExpr) + ptr := m.LastBlock().GetPointerToMaybeHeapDefine(m.Store, vnx) ptr.TV.Assign(m.Alloc, ev, false) default: panic("should not happen") @@ -267,8 +267,8 @@ func (m *Machine) doOpExec(op Op) { case ASSIGN: m.PopAsPointer(bs.Key).Assign2(m.Alloc, m.Store, m.Realm, iv, false) case DEFINE: - knxp := bs.Key.(*NameExpr).Path - ptr := m.LastBlock().GetPointerTo(m.Store, knxp) + knx := bs.Key.(*NameExpr) + ptr := m.LastBlock().GetPointerToMaybeHeapDefine(m.Store, knx) ptr.TV.Assign(m.Alloc, iv, false) default: panic("should not happen") @@ -280,8 +280,8 @@ func (m *Machine) doOpExec(op Op) { case ASSIGN: m.PopAsPointer(bs.Value).Assign2(m.Alloc, m.Store, m.Realm, ev, false) case DEFINE: - vnxp := bs.Value.(*NameExpr).Path - ptr := m.LastBlock().GetPointerTo(m.Store, vnxp) + vnx := bs.Value.(*NameExpr) + ptr := m.LastBlock().GetPointerToMaybeHeapDefine(m.Store, vnx) ptr.TV.Assign(m.Alloc, ev, false) default: panic("should not happen") @@ -360,8 +360,8 @@ func (m *Machine) doOpExec(op Op) { case ASSIGN: m.PopAsPointer(bs.Key).Assign2(m.Alloc, m.Store, m.Realm, kv, false) case DEFINE: - knxp := bs.Key.(*NameExpr).Path - ptr := m.LastBlock().GetPointerTo(m.Store, knxp) + knx := bs.Key.(*NameExpr) + ptr := m.LastBlock().GetPointerToMaybeHeapDefine(m.Store, knx) ptr.TV.Assign(m.Alloc, kv, false) default: panic("should not happen") @@ -373,8 +373,8 @@ func (m *Machine) doOpExec(op Op) { case ASSIGN: m.PopAsPointer(bs.Value).Assign2(m.Alloc, m.Store, m.Realm, vv, false) case DEFINE: - vnxp := bs.Value.(*NameExpr).Path - ptr := m.LastBlock().GetPointerTo(m.Store, vnxp) + vnx := bs.Value.(*NameExpr) + ptr := m.LastBlock().GetPointerToMaybeHeapDefine(m.Store, vnx) ptr.TV.Assign(m.Alloc, vv, false) default: panic("should not happen") @@ -884,6 +884,8 @@ func (m *Machine) doOpTypeSwitch() { // NOTE: assumes the var is first in block. vp := NewValuePath( VPBlock, 1, 0, ss.VarName) + // NOTE: GetPointerToMaybeHeapDefine not needed, + // because this type is in new type switch clause block. ptr := b.GetPointerTo(m.Store, vp) ptr.TV.Assign(m.Alloc, *xv, false) } diff --git a/gnovm/pkg/gnolang/op_expressions.go b/gnovm/pkg/gnolang/op_expressions.go index 8ff0b5bd538..a1d677ca878 100644 --- a/gnovm/pkg/gnolang/op_expressions.go +++ b/gnovm/pkg/gnolang/op_expressions.go @@ -78,7 +78,7 @@ func (m *Machine) doOpIndex2() { func (m *Machine) doOpSelector() { sx := m.PopExpr().(*SelectorExpr) xv := m.PeekValue(1) - res := xv.GetPointerTo(m.Alloc, m.Store, sx.Path).Deref() + res := xv.GetPointerToFromTV(m.Alloc, m.Store, sx.Path).Deref() if debug { m.Printf("-v[S] %v\n", xv) m.Printf("+v[S] %v\n", res) @@ -758,6 +758,25 @@ func (m *Machine) doOpFuncLit() { ft := m.PopValue().V.(TypeValue).Type.(*FuncType) lb := m.LastBlock() m.Alloc.AllocateFunc() + + // First copy closure captured heap values + // to *FuncValue. Later during doOpCall a block + // will be created that copies these values for + // every invocation of the function. + captures := []TypedValue(nil) + for _, nx := range x.HeapCaptures { + ptr := lb.GetPointerTo(m.Store, nx.Path) + // check that ptr.TV is a heap item value. + // it must be in the form of: + // {T:heapItemType{},V:HeapItemValue{...}} + if _, ok := ptr.TV.T.(heapItemType); !ok { + panic("should not happen, should be heapItemType") + } + if _, ok := ptr.TV.V.(*HeapItemValue); !ok { + panic("should not happen, should be heapItemValue") + } + captures = append(captures, *ptr.TV) + } m.PushValue(TypedValue{ T: ft, V: &FuncValue{ @@ -766,6 +785,7 @@ func (m *Machine) doOpFuncLit() { Source: x, Name: "", Closure: lb, + Captures: captures, PkgPath: m.Package.PkgPath, body: x.Body, nativeBody: nil, diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 9168fc6f7c1..a7a1e15bbf3 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -2,8 +2,10 @@ package gnolang import ( "fmt" + "math" "math/big" "reflect" + "slices" "strings" "sync/atomic" @@ -23,7 +25,8 @@ func PredefineFileSet(store Store, pn *PackageNode, fset *FileSet) { // This will also reserve names on BlockNode.StaticBlock by // calling StaticBlock.Predefine(). for _, fn := range fset.Files { - SetNodeLocations(pn.PkgPath, string(fn.Name), fn) + setNodeLines(fn) + setNodeLocations(pn.PkgPath, string(fn.Name), fn) initStaticBlocks(store, pn, fn) } // NOTE: The calls to .Predefine() above is more of a name reservation, @@ -92,7 +95,7 @@ func PredefineFileSet(store Store, pn *PackageNode, fset *FileSet) { } } } - // Finally, predefine other decls and + // Then, predefine other decls and // preprocess ValueDecls.. for _, fn := range fset.Files { for i := 0; i < len(fn.Decls); i++ { @@ -143,32 +146,7 @@ func initStaticBlocks(store Store, ctx BlockNode, bn BlockNode) { // iterate over all nodes recursively. _ = Transcribe(bn, func(ns []Node, ftype TransField, index int, n Node, stage TransStage) (Node, TransCtrl) { - defer func() { - if r := recover(); r != nil { - // before re-throwing the error, append location information to message. - loc := last.GetLocation() - if nline := n.GetLine(); nline > 0 { - loc.Line = nline - } - - var err error - rerr, ok := r.(error) - if ok { - // NOTE: gotuna/gorilla expects error exceptions. - err = errors.Wrap(rerr, loc.String()) - } else { - // NOTE: gotuna/gorilla expects error exceptions. - err = fmt.Errorf("%s: %v", loc.String(), r) - } - - // Re-throw the error after wrapping it with the preprocessing stack information. - panic(&PreprocessError{ - err: err, - stack: stack, - }) - } - }() - + defer doRecover(stack, n) if debug { debug.Printf("initStaticBlocks %s (%v) stage:%v\n", n.String(), reflect.TypeOf(n), stage) } @@ -179,47 +157,54 @@ func initStaticBlocks(store Store, ctx BlockNode, bn BlockNode) { switch n := n.(type) { case *AssignStmt: if n.Op == DEFINE { - var defined bool for _, lx := range n.Lhs { - ln := lx.(*NameExpr).Name + nx := lx.(*NameExpr) + ln := nx.Name if ln == blankIdentifier { continue } - last.Predefine(false, ln) - defined = true - } - if !defined { - panic(fmt.Sprintf("nothing defined in assignment %s", n.String())) + if !isLocallyDefined2(last, ln) { + // if loop extern, will promote to + // NameExprTypeHeapDefine later. + nx.Type = NameExprTypeDefine + last.Predefine(false, ln) + } } } case *ImportDecl: - name := n.Name - if name == "." { + nx := &n.NameExpr + nn := nx.Name + if nn == "." { panic("dot imports not allowed in gno") } - if name == "" { // use default + if nn == "" { // use default pv := store.GetPackage(n.PkgPath, true) if pv == nil { panic(fmt.Sprintf( "unknown import path %s", n.PkgPath)) } - name = pv.PkgName + nn = pv.PkgName } - if name != blankIdentifier { - last.Predefine(false, name) + if nn != blankIdentifier { + nx.Type = NameExprTypeDefine + last.Predefine(false, nn) } case *ValueDecl: last2 := skipFile(last) for i := 0; i < len(n.NameExprs); i++ { nx := &n.NameExprs[i] - if nx.Name == blankIdentifier { + nn := nx.Name + if nn == blankIdentifier { continue } - last2.Predefine(n.Const, nx.Name) + nx.Type = NameExprTypeDefine + last2.Predefine(n.Const, nn) } case *TypeDecl: last2 := skipFile(last) + nx := &n.NameExpr + nx.Type = NameExprTypeDefine last2.Predefine(false, n.Name) case *FuncDecl: if n.IsMethod { @@ -238,7 +223,8 @@ func initStaticBlocks(store Store, ctx BlockNode, bn BlockNode) { dname := Name(fmt.Sprintf("init.%d", idx)) n.Name = dname } - + nx := &n.NameExpr + nx.Type = NameExprTypeDefine pkg.Predefine(false, n.Name) } case *FuncTypeExpr: @@ -256,7 +242,7 @@ func initStaticBlocks(store Store, ctx BlockNode, bn BlockNode) { if r.Name == blankIdentifier { // create a hidden var with leading dot. // NOTE: document somewhere. - rn := fmt.Sprintf(".res_%d", i) + rn := fmt.Sprintf("%s%d", hiddenResultVariable, i) r.Name = Name(rn) } } @@ -265,15 +251,9 @@ func initStaticBlocks(store Store, ctx BlockNode, bn BlockNode) { // ---------------------------------------- case TRANS_BLOCK: + pushInitBlock(n.(BlockNode), &last, &stack) switch n := n.(type) { - case *BlockStmt: - pushInitBlock(n, &last, &stack) - case *ForStmt: - pushInitBlock(n, &last, &stack) - case *IfStmt: - pushInitBlock(n, &last, &stack) case *IfCaseStmt: - pushInitRealBlock(n, &last, &stack) // parent if statement. ifs := ns[len(ns)-1].(*IfStmt) // anything declared in ifs are copied. @@ -281,17 +261,27 @@ func initStaticBlocks(store Store, ctx BlockNode, bn BlockNode) { last.Predefine(false, n) } case *RangeStmt: - pushInitBlock(n, &last, &stack) if n.Op == DEFINE { if n.Key != nil { - last.Predefine(false, n.Key.(*NameExpr).Name) + nx := n.Key.(*NameExpr) + if nx.Name != blankIdentifier { + // XXX, this should be uncommented when fully + // support Go1.22 loopvar, to make it consistent + // with for i := 0; i < 10; i++ {...}. + // nx.Type = NameExprTypeDefine + + last.Predefine(false, nx.Name) + } } if n.Value != nil { - last.Predefine(false, n.Value.(*NameExpr).Name) + nx := n.Value.(*NameExpr) + if nx.Name != blankIdentifier { + // nx.Type = NameExprTypeDefine // XXX,ditto + last.Predefine(false, nx.Name) + } } } case *FuncLitExpr: - pushInitBlock(n, &last, &stack) for _, p := range n.Type.Params { last.Predefine(false, p.Name) } @@ -300,10 +290,7 @@ func initStaticBlocks(store Store, ctx BlockNode, bn BlockNode) { last.Predefine(false, rf.Name) } } - case *SelectCaseStmt: - pushInitBlock(n, &last, &stack) case *SwitchStmt: - pushInitBlock(n, &last, &stack) if n.VarName != "" { // NOTE: this defines for default clauses too, // see comment on block copying @ @@ -311,7 +298,6 @@ func initStaticBlocks(store Store, ctx BlockNode, bn BlockNode) { last.Predefine(false, n.VarName) } case *SwitchClauseStmt: - pushInitRealBlock(n, &last, &stack) // parent switch statement. ss := ns[len(ns)-1].(*SwitchStmt) // anything declared in ss are copied, @@ -329,7 +315,6 @@ func initStaticBlocks(store Store, ctx BlockNode, bn BlockNode) { } } case *FuncDecl: - pushInitBlock(n, &last, &stack) if n.IsMethod { n.Predefine(false, n.Recv.Name) } @@ -339,23 +324,24 @@ func initStaticBlocks(store Store, ctx BlockNode, bn BlockNode) { } n.Predefine(false, pte.Name) } - for _, rte := range n.Type.Results { - if rte.Name != "" { - n.Predefine(false, rte.Name) + for i, rte := range n.Type.Results { + if rte.Name == "" { + rn := fmt.Sprintf("%s%d", hiddenResultVariable, i) + rte.Name = Name(rn) } + n.Predefine(false, rte.Name) } - case *FileNode: - pushInitBlock(n, &last, &stack) - default: - panic("should not happen") } return n, TRANS_CONTINUE // ---------------------------------------- case TRANS_LEAVE: - // finalization. - if _, ok := n.(BlockNode); ok { - // Pop block. + // Pop block from stack. + // NOTE: DO NOT USE TRANS_SKIP WITHIN BLOCK + // NODES, AS TRANS_LEAVE WILL BE SKIPPED; OR + // POP BLOCK YOURSELF. + switch n.(type) { + case BlockNode: stack = stack[:len(stack)-1] last = stack[len(stack)-1] } @@ -365,6 +351,34 @@ func initStaticBlocks(store Store, ctx BlockNode, bn BlockNode) { }) } +func doRecover(stack []BlockNode, n Node) { + if r := recover(); r != nil { + // before re-throwing the error, append location information to message. + last := stack[len(stack)-1] + loc := last.GetLocation() + if nline := n.GetLine(); nline > 0 { + loc.Line = nline + loc.Column = n.GetColumn() + } + + var err error + rerr, ok := r.(error) + if ok { + // NOTE: gotuna/gorilla expects error exceptions. + err = errors.Wrap(rerr, loc.String()) + } else { + // NOTE: gotuna/gorilla expects error exceptions. + err = fmt.Errorf("%s: %v", loc.String(), r) + } + + // Re-throw the error after wrapping it with the preprocessing stack information. + panic(&PreprocessError{ + err: err, + stack: stack, + }) + } +} + // This counter ensures (during testing) that certain functions // (like ConvertUntypedTo() for bigints and strings) // are only called during the preprocessing stage. @@ -390,6 +404,27 @@ var preprocessing atomic.Int32 // - Assigns BlockValuePath to NameExprs. // - TODO document what it does. func Preprocess(store Store, ctx BlockNode, n Node) Node { + // If initStaticBlocks doesn't happen here, + // it means Preprocess on blocks might fail. + // it works for now because preprocess also does pushInitBlock, + // but it's kinda weird. + // maybe consider moving initStaticBlocks here and ensure idempotency of it. + n = preprocess1(store, ctx, n) + // XXX check node lines and locations + checkNodeLinesLocations("XXXpkgPath", "XXXfileName", n) + // XXX what about the fact that preprocess1 sets the PREPROCESSED attr on all nodes? + // XXX do any of the following need the attr, or similar attrs? + // XXX well the following may be isn't idempotent, + // XXX so it is currently strange. + if bn, ok := n.(BlockNode); ok { + findGotoLoopDefines(ctx, bn) + findLoopUses1(ctx, bn) + findLoopUses2(ctx, bn) + } + return n +} + +func preprocess1(store Store, ctx BlockNode, n Node) Node { // Increment preprocessing counter while preprocessing. preprocessing.Add(1) defer preprocessing.Add(-1) @@ -403,7 +438,8 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if fn, ok := n.(*FileNode); ok { pkgPath := ctx.(*PackageNode).PkgPath fileName := string(fn.Name) - SetNodeLocations(pkgPath, fileName, fn) + setNodeLines(fn) + setNodeLocations(pkgPath, fileName, fn) } // create stack of BlockNodes. @@ -419,32 +455,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { return n, TRANS_SKIP } - defer func() { - if r := recover(); r != nil { - // before re-throwing the error, append location information to message. - loc := last.GetLocation() - if nline := n.GetLine(); nline > 0 { - loc.Line = nline - loc.Column = n.GetColumn() - } - - var err error - rerr, ok := r.(error) - if ok { - // NOTE: gotuna/gorilla expects error exceptions. - err = errors.Wrap(rerr, loc.String()) - } else { - // NOTE: gotuna/gorilla expects error exceptions. - err = fmt.Errorf("%s: %v", loc.String(), r) - } - - // Re-throw the error after wrapping it with the preprocessing stack information. - panic(&PreprocessError{ - err: err, - stack: stack, - }) - } - }() + defer doRecover(stack, n) if debug { debug.Printf("Preprocess %s (%v) stage:%v\n", n.String(), reflect.TypeOf(n), stage) } @@ -540,7 +551,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_BLOCK ----------------------- case *IfCaseStmt: - pushInitRealBlockAndCopy(n, &last, &stack) + pushInitBlockAndCopy(n, &last, &stack) // parent if statement. ifs := ns[len(ns)-1].(*IfStmt) // anything declared in ifs are copied. @@ -624,7 +635,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } else { // create a hidden var with leading dot. // NOTE: document somewhere. - rn := fmt.Sprintf(".res_%d", i) + rn := fmt.Sprintf("%s%d", hiddenResultVariable, i) last.Define(Name(rn), anyValue(rf.Type)) } } @@ -656,7 +667,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_BLOCK ----------------------- case *SwitchClauseStmt: - pushInitRealBlockAndCopy(n, &last, &stack) + pushInitBlockAndCopy(n, &last, &stack) // parent switch statement. ss := ns[len(ns)-1].(*SwitchStmt) // anything declared in ss are copied, @@ -723,12 +734,8 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // TRANS_BLOCK ----------------------- case *FuncDecl: // retrieve cached function type. + // the type and receiver are already set in predefineNow. ft := getType(&n.Type).(*FuncType) - if n.IsMethod { - // recv/type set @ predefineNow(). - } else { - // type set @ predefineNow(). - } // push func body block. pushInitBlock(n, &last, &stack) @@ -750,7 +757,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { last.Define(rf.Name, anyValue(rf.Type)) } else { // create a hidden var with leading dot. - rn := fmt.Sprintf(".res_%d", i) + rn := fmt.Sprintf("%s%d", hiddenResultVariable, i) last.Define(Name(rn), anyValue(rf.Type)) } } @@ -869,15 +876,23 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // in evalStaticType(store,). n.SetAttribute(ATTR_PREPROCESSED, true) - // -There is still work to be done while leaving, but - // once the logic of that is done, we will have to - // perform additionally deferred logic that is best - // handled with orthogonal switch conditions. - // -For example, while leaving nodes w/ - // TRANS_COMPOSITE_TYPE, (regardless of whether name or - // literal), any elided type names are inserted. (This - // works because the transcriber leaves the composite - // type before entering the kv elements.) + // Defer pop block from stack. + // NOTE: DO NOT USE TRANS_SKIP WITHIN BLOCK + // NODES, AS TRANS_LEAVE WILL BE SKIPPED; OR + // POP BLOCK YOURSELF. + defer func() { + switch n.(type) { + case BlockNode: + stack = stack[:len(stack)-1] + last = stack[len(stack)-1] + } + }() + + // While leaving nodes w/ TRANS_COMPOSITE_TYPE, + // (regardless of whether name or literal), any elided + // type names are inserted. (This works because the + // transcriber leaves the composite type before + // entering the kv elements.) defer func() { switch ftype { // TRANS_LEAVE (deferred)--------- @@ -963,6 +978,10 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if ftype == TRANS_ASSIGN_LHS { as := ns[len(ns)-1].(*AssignStmt) fillNameExprPath(last, n, as.Op == DEFINE) + return n, TRANS_CONTINUE + } else if ftype == TRANS_VAR_NAME { + fillNameExprPath(last, n, true) + return n, TRANS_CONTINUE } else { fillNameExprPath(last, n, false) } @@ -1025,7 +1044,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { isShift := n.Op == SHL || n.Op == SHR if isShift { // check LHS type compatibility - n.checkShiftLhs(lt) + n.assertShiftExprCompatible1(store, last, lt, rt) // checkOrConvert RHS if baseOf(rt) != UintType { // convert n.Right to (gno) uint type, @@ -1036,6 +1055,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { Op: n.Op, Right: rn, } + n2.Right.SetAttribute(ATTR_SHIFT_RHS, true) resn := Preprocess(store, last, n2) return resn, TRANS_CONTINUE } @@ -1097,12 +1117,34 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // NOTE: binary operations are always computed in // gno, never with reflect. } else { - // convert n.Left to right type. - checkOrConvertType(store, last, &n.Left, rt, false) + // right is untyped const, left is not const, typed/untyped + checkUntypedShiftExpr := func(x Expr) { + if bx, ok := x.(*BinaryExpr); ok { + slt := evalStaticTypeOf(store, last, bx.Left) + if bx.Op == SHL || bx.Op == SHR { + srt := evalStaticTypeOf(store, last, bx.Right) + bx.assertShiftExprCompatible1(store, last, slt, srt) + } + } + } + + if !isUntyped(rt) { // right is typed + checkOrConvertType(store, last, &n.Left, rt, false) + } else { + if shouldSwapOnSpecificity(lt, rt) { + checkUntypedShiftExpr(n.Right) + } else { + checkUntypedShiftExpr(n.Left) + } + } } } else if lcx.T == nil { // LHS is nil. // convert n.Left to typed-nil type. checkOrConvertType(store, last, &n.Left, rt, false) + } else { + if isUntyped(rt) { + checkOrConvertType(store, last, &n.Right, lt, false) + } } } else if ric { // right is const, left is not if isUntyped(rcx.T) { @@ -1134,12 +1176,33 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // NOTE: binary operations are always computed in // gno, never with reflect. } else { - // convert n.Right to left type. - checkOrConvertType(store, last, &n.Right, lt, false) + // right is untyped const, left is not const, typed or untyped + checkUntypedShiftExpr := func(x Expr) { + if bx, ok := x.(*BinaryExpr); ok { + if bx.Op == SHL || bx.Op == SHR { + srt := evalStaticTypeOf(store, last, bx.Right) + bx.assertShiftExprCompatible1(store, last, rt, srt) + } + } + } + // both untyped, e.g. 1<>=. convertType(store, last, &n.Rhs[0], UintType) } else if n.Op == ADD_ASSIGN || n.Op == SUB_ASSIGN || n.Op == MUL_ASSIGN || n.Op == QUO_ASSIGN || n.Op == REM_ASSIGN { @@ -2031,6 +2120,10 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // General case: a, b = x, y. for i, lx := range n.Lhs { lt := evalStaticTypeOf(store, last, lx) + if nt, ok := lt.(*NativeType); ok && nt.Kind() == FuncKind { + panic(fmt.Sprintf("cannot assign to %s (neither addressable nor a map index expression)", lx)) + } + // if lt is interface, nothing will happen checkOrConvertType(store, last, &n.Rhs[i], lt, true) } @@ -2042,14 +2135,28 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { case *BranchStmt: switch n.Op { case BREAK: - if !isSwitchLabel(ns, n.Label) { - findBranchLabel(last, n.Label) + if n.Label == "" { + if !findBreakableNode(ns) { + panic("cannot break with no parent loop or switch") + } + } else { + // Make sure that the label exists, either for a switch or a + // BranchStmt. + if !isSwitchLabel(ns, n.Label) { + findBranchLabel(last, n.Label) + } } case CONTINUE: - if isSwitchLabel(ns, n.Label) { - panic(fmt.Sprintf("invalid continue label %q\n", n.Label)) + if n.Label == "" { + if !findContinuableNode(ns) { + panic("cannot continue with no parent loop") + } + } else { + if isSwitchLabel(ns, n.Label) { + panic(fmt.Sprintf("invalid continue label %q\n", n.Label)) + } + findBranchLabel(last, n.Label) } - findBranchLabel(last, n.Label) case GOTO: _, depth, index := findGotoLabel(last, n.Label) n.Depth = depth @@ -2072,6 +2179,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { panic("should not happen") } + // TRANS_LEAVE ----------------------- case *IncDecStmt: xt := evalStaticTypeOf(store, last, n.X) n.AssertCompatible(xt) @@ -2281,10 +2389,15 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { vt := evalStaticTypeOf(store, last, vx) sts[i] = vt } - } else { + } else { // T is nil, n not const // convert n.Value to default type. for i, vx := range n.Values { - convertIfConst(store, last, vx) + if cx, ok := vx.(*ConstExpr); ok { + convertConst(store, last, cx, nil) + // convertIfConst(store, last, vx) + } else { + checkOrConvertType(store, last, &vx, nil, false) + } vt := evalStaticTypeOf(store, last, vx) sts[i] = vt } @@ -2394,13 +2507,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } // end type switch statement // END TRANS_LEAVE ----------------------- - - // finalization (during leave). - if _, ok := n.(BlockNode); ok { - // Pop block. - stack = stack[:len(stack)-1] - last = stack[len(stack)-1] - } return n, TRANS_CONTINUE } @@ -2411,6 +2517,458 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { return nn } +// Identifies NameExprTypeHeapDefines. +// Also finds GotoLoopStmts, XXX but probably remove, not needed. +func findGotoLoopDefines(ctx BlockNode, bn BlockNode) { + // create stack of BlockNodes. + var stack []BlockNode = make([]BlockNode, 0, 32) + var last BlockNode = ctx + stack = append(stack, last) + + // iterate over all nodes recursively. + _ = Transcribe(bn, func(ns []Node, ftype TransField, index int, n Node, stage TransStage) (Node, TransCtrl) { + defer doRecover(stack, n) + + if debug { + debug.Printf("findGotoLoopDefines %s (%v) stage:%v\n", n.String(), reflect.TypeOf(n), stage) + } + + switch stage { + // ---------------------------------------- + case TRANS_ENTER: + return n, TRANS_CONTINUE + + // ---------------------------------------- + case TRANS_BLOCK: + pushInitBlock(n.(BlockNode), &last, &stack) + return n, TRANS_CONTINUE + + // ---------------------------------------- + case TRANS_LEAVE: + + // Defer pop block from stack. + // NOTE: DO NOT USE TRANS_SKIP WITHIN BLOCK + // NODES, AS TRANS_LEAVE WILL BE SKIPPED; OR + // POP BLOCK YOURSELF. + defer func() { + switch n.(type) { + case BlockNode: + stack = stack[:len(stack)-1] + last = stack[len(stack)-1] + } + }() + + switch n := n.(type) { + case *ForStmt, *RangeStmt: + Transcribe(n, + func(ns []Node, ftype TransField, index int, n Node, stage TransStage) (Node, TransCtrl) { + switch stage { + case TRANS_ENTER: + switch n := n.(type) { + case *FuncLitExpr: + // inner funcs. + return n, TRANS_SKIP + case *FuncDecl: + panic("unexpected inner func decl") + case *NameExpr: + if n.Type == NameExprTypeDefine { + n.Type = NameExprTypeHeapDefine + } + } + } + return n, TRANS_CONTINUE + }) + case *BranchStmt: + switch n.Op { + case GOTO: + bn, _, _ := findGotoLabel(last, n.Label) + // already done in Preprocess: + // n.Depth = depth + // n.BodyIndex = index + + // NOTE: we must not use line numbers + // for logic, as line numbers are not + // guaranteed (see checkNodeLinesLocations). + // Instead we rely on the transcribe order + // and keep track of whether we've seen + // the label and goto stmts respectively. + // + // DOES NOT WORK: + // gotoLine := n.GetLine() + // if labelLine >= gotoLine { + // return n, TRANS_SKIP + // } + var ( + label = n.Label + labelReached bool + origGoto = n + ) + + // Recurse and mark stmts as ATTR_GOTOLOOP_STMT. + // NOTE: ATTR_GOTOLOOP_STMT is not used. + Transcribe(bn, + func(ns []Node, ftype TransField, index int, n Node, stage TransStage) (Node, TransCtrl) { + switch stage { + case TRANS_ENTER: + // Check to see if label reached. + if _, ok := n.(Stmt); ok { + // XXX HasLabel + if n.GetLabel() == label { + labelReached = true + } + // If goto < label, + // then not a goto loop. + if n == origGoto && !labelReached { + return n, TRANS_EXIT + } + } + + // If label not reached, continue. + if !labelReached { + return n, TRANS_CONTINUE + } + + // NOTE: called redundantly + // for many goto stmts, + // idempotenct updates only. + switch n := n.(type) { + // Skip the body of these: + case *FuncLitExpr: + if len(ns) > 0 { + // inner funcs. + return n, TRANS_SKIP + } + return n, TRANS_CONTINUE + case *FuncDecl: + if len(ns) > 0 { + panic("unexpected inner func decl") + } + return n, TRANS_CONTINUE + // Otherwise mark stmt as gotoloop. + case Stmt: + // we're done if we + // re-encounter origGotoStmtm. + if n == origGoto { + n.SetAttribute( + ATTR_GOTOLOOP_STMT, + true) + return n, TRANS_EXIT // done + } + // otherwise set attribute. + n.SetAttribute( + ATTR_GOTOLOOP_STMT, + true) + return n, TRANS_CONTINUE + // Special case, maybe convert + // NameExprTypeDefine to + // NameExprTypeHeapDefine. + case *NameExpr: + if n.Type == NameExprTypeDefine { + n.Type = NameExprTypeHeapDefine + } + } + return n, TRANS_CONTINUE + } + return n, TRANS_CONTINUE + }) + } + } + return n, TRANS_CONTINUE + } + return n, TRANS_CONTINUE + }) +} + +// Find uses of loop names; those names that are defined as loop defines; +// defines within loops that are used as reference or captured in a closure +// later. Also happens to adjust the type (but not paths) of such usage. +// If there is no usage of the &name or as closure capture, a +// NameExprTypeHeapDefine gets demoted to NameExprTypeDefine in demoteHeapDefines(). +func findLoopUses1(ctx BlockNode, bn BlockNode) { + // create stack of BlockNodes. + var stack []BlockNode = make([]BlockNode, 0, 32) + var last BlockNode = ctx + stack = append(stack, last) + + // Iterate over all nodes recursively. + _ = Transcribe(bn, func(ns []Node, ftype TransField, index int, n Node, stage TransStage) (Node, TransCtrl) { + defer doRecover(stack, n) + + if debug { + debug.Printf("findLoopUses1 %s (%v) stage:%v\n", n.String(), reflect.TypeOf(n), stage) + } + + switch stage { + // ---------------------------------------- + case TRANS_BLOCK: + pushInitBlock(n.(BlockNode), &last, &stack) + + // ---------------------------------------- + case TRANS_ENTER: + switch n := n.(type) { + case *NameExpr: + // Ignore non-block type paths + if n.Path.Type != VPBlock { + return n, TRANS_CONTINUE + } + switch n.Type { + case NameExprTypeNormal: + // Find the block where name is defined + dbn := last.GetBlockNodeForPath(nil, n.Path) + // if the name is loop defined, + lds, _ := dbn.GetAttribute(ATTR_LOOP_DEFINES).([]Name) + if slices.Contains(lds, n.Name) { + fle, depth, found := findFirstClosure(stack, dbn) + if found { + // If across a closure, + // mark name as loop used. + addAttrHeapUse(dbn, n.Name) + // The path must stay same for now, + // used later in findLoopUses2. + idx := addHeapCapture(dbn, fle, n.Name) + // adjust NameExpr type. + n.Type = NameExprTypeHeapUse + n.Path.Depth = uint8(depth) + n.Path.Index = idx + } else { + if ftype == TRANS_REF_X { + // if used as a reference, + // mark name as loop used. + addAttrHeapUse(dbn, n.Name) + // Also adjust NameExpr type. + // We could do this later too. + n.Type = NameExprTypeHeapUse + } + } + } else { + // if the name is not loop defined, + // do nothing. + } + case NameExprTypeDefine: + // nothing to do. + case NameExprTypeHeapDefine: + // Set name in attribute, so later matches + // on NameExpr can know that this was loop defined + // on this block. + setAttrHeapDefine(last, n.Name) + case NameExprTypeHeapUse, NameExprTypeHeapClosure: + panic("unexpected node type") + } + } + return n, TRANS_CONTINUE + + // ---------------------------------------- + case TRANS_LEAVE: + // Pop block from stack. + // NOTE: DO NOT USE TRANS_SKIP WITHIN BLOCK + // NODES, AS TRANS_LEAVE WILL BE SKIPPED; OR + // POP BLOCK YOURSELF. + switch n.(type) { + case BlockNode: + stack = stack[:len(stack)-1] + last = stack[len(stack)-1] + } + + return n, TRANS_CONTINUE + } + return n, TRANS_CONTINUE + }) +} + +func assertNotHasName(names []Name, name Name) { + if slices.Contains(names, name) { + panic(fmt.Sprintf("name: %s already contained in names: %v", name, names)) + } +} + +func setAttrHeapDefine(bn BlockNode, name Name) { + bnLDs, _ := bn.GetAttribute(ATTR_LOOP_DEFINES).([]Name) + assertNotHasName(bnLDs, name) + bnLDs = append(bnLDs, name) + bn.SetAttribute(ATTR_LOOP_DEFINES, bnLDs) +} + +func addAttrHeapUse(bn BlockNode, name Name) { + bnLUs, _ := bn.GetAttribute(ATTR_LOOP_USES).([]Name) + if slices.Contains(bnLUs, name) { + return + } else { + bnLUs = append(bnLUs, name) + bn.SetAttribute(ATTR_LOOP_USES, bnLUs) + return + } +} + +// adds ~name to fle static block and to heap captures atomically. +func addHeapCapture(dbn BlockNode, fle *FuncLitExpr, name Name) (idx uint16) { + for _, ne := range fle.HeapCaptures { + if ne.Name == name { + // assert ~name also already defined. + var ok bool + idx, ok = fle.GetLocalIndex("~" + name) + if !ok { + panic("~name not added to fle atomically") + } + return // already exists + } + } + + // define ~name to fle. + _, ok := fle.GetLocalIndex("~" + name) + if ok { + panic("~name already defined in fle") + } + + tv := dbn.GetValueRef(nil, name, true) + fle.Define("~"+name, tv.Copy(nil)) + + // add name to fle.HeapCaptures. + vp := fle.GetPathForName(nil, name) + vp.Depth -= 1 // minus 1 for fle itself. + ne := NameExpr{ + Path: vp, + Name: name, + Type: NameExprTypeHeapClosure, + } + fle.HeapCaptures = append(fle.HeapCaptures, ne) + + // find index after define + for i, n := range fle.GetBlockNames() { + if n == "~"+name { + idx = uint16(i) + return + } + } + + panic("should not happen, idx not found") +} + +// finds the first FuncLitExpr in the stack at or after stop. +// returns the depth of first closure, 1 if stop itself is a closure, +// or 0 if not found. +func findFirstClosure(stack []BlockNode, stop BlockNode) (fle *FuncLitExpr, depth int, found bool) { + redundant := 0 // count faux block + for i := len(stack) - 1; i >= 0; i-- { + stbn := stack[i] + switch stbn := stbn.(type) { + case *FuncLitExpr: + if stbn == stop { // if fle is stopBn, does not count, use last fle + return + } + fle = stbn + depth = len(stack) - 1 - redundant - i + 1 // +1 since 1 is lowest. + found = true + // even if found, continue iteration in case + // an earlier *FuncLitExpr is found. + case *IfCaseStmt, *SwitchClauseStmt: + if stbn == stop { + return + } + redundant++ + default: + if stbn == stop { + return + } + } + } + panic("stop not found in stack") +} + +// Convert non-loop uses of loop names to NameExprTypeHeapUse. +// Also, NameExprTypeHeapDefine gets demoted to NameExprTypeDefine if no actual +// usage was found that warrants a NameExprTypeHeapDefine. +func findLoopUses2(ctx BlockNode, bn BlockNode) { + // create stack of BlockNodes. + var stack []BlockNode = make([]BlockNode, 0, 32) + var last BlockNode = ctx + stack = append(stack, last) + + // Iterate over all nodes recursively. + _ = Transcribe(bn, func(ns []Node, ftype TransField, index int, n Node, stage TransStage) (Node, TransCtrl) { + defer doRecover(stack, n) + + if debug { + debug.Printf("findLoopUses2 %s (%v) stage:%v\n", n.String(), reflect.TypeOf(n), stage) + } + + switch stage { + // ---------------------------------------- + case TRANS_BLOCK: + pushInitBlock(n.(BlockNode), &last, &stack) + + // ---------------------------------------- + case TRANS_ENTER: + switch n := n.(type) { + case *NameExpr: + // Ignore non-block type paths + if n.Path.Type != VPBlock { + return n, TRANS_CONTINUE + } + switch n.Type { + case NameExprTypeNormal: + // Find the block where name is defined + dbn := last.GetBlockNodeForPath(nil, n.Path) + // if the name is loop defined, + lds, _ := dbn.GetAttribute(ATTR_LOOP_DEFINES).([]Name) + if slices.Contains(lds, n.Name) { + // if the name is actually loop used, + lus, _ := dbn.GetAttribute(ATTR_LOOP_USES).([]Name) + if slices.Contains(lus, n.Name) { + // change type finally to HeapUse. + n.Type = NameExprTypeHeapUse + } else { + // else, will be demoted in later clause. + } + } + case NameExprTypeHeapDefine: + // Find the block where name is defined + dbn := last.GetBlockNodeForPath(nil, n.Path) + // if the name is loop defined + lds, _ := dbn.GetAttribute(ATTR_LOOP_DEFINES).([]Name) + if slices.Contains(lds, n.Name) { + // if the name is actually loop used + lus, _ := dbn.GetAttribute(ATTR_LOOP_USES).([]Name) + if !slices.Contains(lus, n.Name) { + // demote type finally to Define. + n.Type = NameExprTypeDefine + } + } + } + } + return n, TRANS_CONTINUE + + // ---------------------------------------- + case TRANS_LEAVE: + + // Defer pop block from stack. + // NOTE: DO NOT USE TRANS_SKIP WITHIN BLOCK + // NODES, AS TRANS_LEAVE WILL BE SKIPPED; OR + // POP BLOCK YOURSELF. + defer func() { + switch n.(type) { + case BlockNode: + stack = stack[:len(stack)-1] + last = stack[len(stack)-1] + } + }() + + switch n := n.(type) { + case BlockNode: + lds, _ := n.GetAttribute(ATTR_LOOP_DEFINES).([]Name) + lus, _ := n.GetAttribute(ATTR_LOOP_USES).([]Name) + if len(lds) < len(lus) { + panic("defines should be a superset of used-defines") + } + // no need anymore + n.DelAttribute(ATTR_LOOP_USES) + n.DelAttribute(ATTR_LOOP_DEFINES) + } + return n, TRANS_CONTINUE + } + return n, TRANS_CONTINUE + }) +} + func isSwitchLabel(ns []Node, label Name) bool { for { swch := lastSwitch(ns) @@ -2429,37 +2987,38 @@ func isSwitchLabel(ns []Node, label Name) bool { } // Idempotent. +// Also makes sure the stack doesn't reach MaxUint8 in length. func pushInitBlock(bn BlockNode, last *BlockNode, stack *[]BlockNode) { if !bn.IsInitialized() { - bn.InitStaticBlock(bn, *last) + switch bn.(type) { + case *IfCaseStmt, *SwitchClauseStmt: + // skip faux block + bn.InitStaticBlock(bn, (*last).GetParentNode(nil)) + default: + bn.InitStaticBlock(bn, *last) + } } if bn.GetStaticBlock().Source != bn { panic("expected the source of a block node to be itself") } *last = bn *stack = append(*stack, bn) -} - -// like pushInitBlock(), but when the last block is a faux block, -// namely after SwitchStmt and IfStmt. -// Idempotent. -func pushInitRealBlock(bn BlockNode, last *BlockNode, stack *[]BlockNode) { - if !bn.IsInitialized() { - bn.InitStaticBlock(bn, (*last).GetParentNode(nil)) - } - if bn.GetStaticBlock().Source != bn { - panic("expected the source of a block node to be itself") + if len(*stack) >= math.MaxUint8 { + panic("block node depth reached maximum MaxUint8") } - *last = bn - *stack = append(*stack, bn) } // like pushInitBlock(), but when the last block is a faux block, // namely after SwitchStmt and IfStmt. // Not idempotent, as it calls bn.Define with reference to last's TV value slot. -func pushInitRealBlockAndCopy(bn BlockNode, last *BlockNode, stack *[]BlockNode) { +func pushInitBlockAndCopy(bn BlockNode, last *BlockNode, stack *[]BlockNode) { + if _, ok := bn.(*IfCaseStmt); !ok { + if _, ok := bn.(*SwitchClauseStmt); !ok { + panic("should not happen") + } + } orig := *last - pushInitRealBlock(bn, last, stack) + pushInitBlock(bn, last, stack) copyFromFauxBlock(bn, orig) } @@ -2665,6 +3224,7 @@ func evalConst(store Store, last BlockNode, x Expr) *ConstExpr { Source: x, TypedValue: cv, } + cx.SetLine(x.GetLine()) cx.SetAttribute(ATTR_PREPROCESSED, true) setConstAttrs(cx) return cx @@ -2673,6 +3233,7 @@ func evalConst(store Store, last BlockNode, x Expr) *ConstExpr { func constType(source Expr, t Type) *constTypeExpr { cx := &constTypeExpr{Source: source} cx.Type = t + cx.SetLine(source.GetLine()) cx.SetAttribute(ATTR_PREPROCESSED, true) return cx } @@ -2708,6 +3269,26 @@ func funcOf(last BlockNode) (BlockNode, *FuncTypeExpr) { } } +func findBreakableNode(ns []Node) bool { + for _, n := range ns { + switch n.(type) { + case *ForStmt, *RangeStmt, *SwitchClauseStmt: + return true + } + } + return false +} + +func findContinuableNode(ns []Node) bool { + for _, n := range ns { + switch n.(type) { + case *ForStmt, *RangeStmt: + return true + } + } + return false +} + func findBranchLabel(last BlockNode, label Name) ( bn BlockNode, depth uint8, bodyIdx int, ) { @@ -2840,9 +3421,25 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative assertAssignableTo(cx.T, t, autoNative) } } else if bx, ok := (*x).(*BinaryExpr); ok && (bx.Op == SHL || bx.Op == SHR) { - // "push" expected type into shift binary's left operand. recursively. - checkOrConvertType(store, last, &bx.Left, t, autoNative) - } else if *x != nil { // XXX if x != nil && t != nil { + xt := evalStaticTypeOf(store, last, *x) + if debug { + debug.Printf("shift, xt: %v, Op: %v, t: %v \n", xt, bx.Op, t) + } + if isUntyped(xt) { + // check assignable first, see: types/shift_b6.gno + assertAssignableTo(xt, t, autoNative) + + if t == nil || t.Kind() == InterfaceKind { + t = defaultTypeOf(xt) + } + + bx.assertShiftExprCompatible2(t) + checkOrConvertType(store, last, &bx.Left, t, autoNative) + } else { + assertAssignableTo(xt, t, autoNative) + } + return + } else if *x != nil { xt := evalStaticTypeOf(store, last, *x) if t != nil { assertAssignableTo(xt, t, autoNative) @@ -2853,19 +3450,53 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative switch bx.Op { case ADD, SUB, MUL, QUO, REM, BAND, BOR, XOR, BAND_NOT, LAND, LOR: - // push t into bx.Left and bx.Right - checkOrConvertType(store, last, &bx.Left, t, autoNative) - checkOrConvertType(store, last, &bx.Right, t, autoNative) - return - case SHL, SHR: - // push t into bx.Left - checkOrConvertType(store, last, &bx.Left, t, autoNative) + lt := evalStaticTypeOf(store, last, bx.Left) + rt := evalStaticTypeOf(store, last, bx.Right) + if t != nil { + // push t into bx.Left and bx.Right + checkOrConvertType(store, last, &bx.Left, t, autoNative) + checkOrConvertType(store, last, &bx.Right, t, autoNative) + return + } else { + if shouldSwapOnSpecificity(lt, rt) { + // e.g. 1.0<gno type conversion must be registered. @@ -124,7 +119,6 @@ func NewStore(alloc *Allocator, baseStore, iavlStore store.Store) *defaultStore // store configuration pkgGetter: nil, cacheNativeTypes: make(map[reflect.Type]Type), - pkgInjector: nil, nativeStore: nil, go2gnoStrict: true, } @@ -154,7 +148,6 @@ func (ds *defaultStore) BeginTransaction(baseStore, iavlStore store.Store) Trans // store configuration pkgGetter: ds.pkgGetter, cacheNativeTypes: ds.cacheNativeTypes, - pkgInjector: ds.pkgInjector, nativeStore: ds.nativeStore, go2gnoStrict: ds.go2gnoStrict, @@ -190,10 +183,6 @@ func (transactionStore) ClearCache() { // panic("Go2GnoType may not be called in a transaction store") // } -func (transactionStore) SetPackageInjector(inj PackageInjector) { - panic("SetPackageInjector may not be called in a transaction store") -} - func (transactionStore) SetNativeStore(ns NativeStore) { panic("SetNativeStore may not be called in a transaction store") } @@ -263,26 +252,6 @@ func (ds *defaultStore) GetPackage(pkgPath string, isImport bool) *PackageValue rlm := ds.GetPackageRealm(pkgPath) pv.Realm = rlm } - // get package node. - pl := PackageNodeLocation(pkgPath) - pn, ok := ds.GetBlockNodeSafe(pl).(*PackageNode) - if !ok { - // Do not inject packages from packageGetter - // that don't have corresponding *PackageNodes. - } else { - // Inject natives after load. - if ds.pkgInjector != nil { - if pn.HasAttribute(ATTR_INJECTED) { - // e.g. in checktx or simulate or query. - pn.PrepareNewValues(pv) - } else { - // pv.GetBlock(ds) // preload pv.Block - ds.pkgInjector(ds, pn) - pn.SetAttribute(ATTR_INJECTED, true) - pn.PrepareNewValues(pv) - } - } - } // Rederive pv.fBlocksMap. pv.deriveFBlocksMap(ds) return pv @@ -303,18 +272,6 @@ func (ds *defaultStore) GetPackage(pkgPath string, isImport bool) *PackageValue // will get written elsewhere // later. ds.cacheObjects[oid] = pv - // inject natives after init. - if ds.pkgInjector != nil { - if pn.HasAttribute(ATTR_INJECTED) { - // not sure why this would happen. - panic("should not happen") - // pn.PrepareNewValues(pv) - } else { - ds.pkgInjector(ds, pn) - pn.SetAttribute(ATTR_INJECTED, true) - pn.PrepareNewValues(pv) - } - } // cache all types. usually preprocess() sets types, // but packages gotten from the pkgGetter may skip this step, // so fill in store.CacheTypes here. @@ -654,7 +611,7 @@ func (ds *defaultStore) incGetPackageIndexCounter() uint64 { } } -func (ds *defaultStore) AddMemPackage(memPkg *std.MemPackage) { +func (ds *defaultStore) AddMemPackage(memPkg *gnovm.MemPackage) { memPkg.Validate() // NOTE: duplicate validation. ctr := ds.incGetPackageIndexCounter() idxkey := []byte(backendPackageIndexKey(ctr)) @@ -666,11 +623,11 @@ func (ds *defaultStore) AddMemPackage(memPkg *std.MemPackage) { // GetMemPackage retrieves the MemPackage at the given path. // It returns nil if the package could not be found. -func (ds *defaultStore) GetMemPackage(path string) *std.MemPackage { +func (ds *defaultStore) GetMemPackage(path string) *gnovm.MemPackage { return ds.getMemPackage(path, false) } -func (ds *defaultStore) getMemPackage(path string, isRetry bool) *std.MemPackage { +func (ds *defaultStore) getMemPackage(path string, isRetry bool) *gnovm.MemPackage { pathkey := []byte(backendPackagePathKey(path)) bz := ds.iavlStore.Get(pathkey) if bz == nil { @@ -687,7 +644,7 @@ func (ds *defaultStore) getMemPackage(path string, isRetry bool) *std.MemPackage return nil } - var memPkg *std.MemPackage + var memPkg *gnovm.MemPackage amino.MustUnmarshal(bz, &memPkg) return memPkg } @@ -695,7 +652,7 @@ func (ds *defaultStore) getMemPackage(path string, isRetry bool) *std.MemPackage // GetMemFile retrieves the MemFile with the given name, contained in the // MemPackage at the given path. It returns nil if the file or the package // do not exist. -func (ds *defaultStore) GetMemFile(path string, name string) *std.MemFile { +func (ds *defaultStore) GetMemFile(path string, name string) *gnovm.MemFile { memPkg := ds.GetMemPackage(path) if memPkg == nil { return nil @@ -704,7 +661,7 @@ func (ds *defaultStore) GetMemFile(path string, name string) *std.MemFile { return memFile } -func (ds *defaultStore) IterMemPackage() <-chan *std.MemPackage { +func (ds *defaultStore) IterMemPackage() <-chan *gnovm.MemPackage { ctrkey := []byte(backendPackageIndexCtrKey()) ctrbz := ds.baseStore.Get(ctrkey) if ctrbz == nil { @@ -714,7 +671,7 @@ func (ds *defaultStore) IterMemPackage() <-chan *std.MemPackage { if err != nil { panic(err) } - ch := make(chan *std.MemPackage, 0) + ch := make(chan *gnovm.MemPackage, 0) go func() { for i := uint64(1); i <= uint64(ctr); i++ { idxkey := []byte(backendPackageIndexKey(i)) @@ -742,10 +699,6 @@ func (ds *defaultStore) ClearObjectCache() { ds.SetCachePackage(Uverse()) } -func (ds *defaultStore) SetPackageInjector(inj PackageInjector) { - ds.pkgInjector = inj -} - func (ds *defaultStore) SetNativeStore(ns NativeStore) { ds.nativeStore = ns } diff --git a/gnovm/pkg/gnolang/store_test.go b/gnovm/pkg/gnolang/store_test.go index 8114291d1b6..40f84b65375 100644 --- a/gnovm/pkg/gnolang/store_test.go +++ b/gnovm/pkg/gnolang/store_test.go @@ -4,8 +4,8 @@ import ( "io" "testing" + "github.com/gnolang/gno/gnovm" "github.com/gnolang/gno/tm2/pkg/db/memdb" - "github.com/gnolang/gno/tm2/pkg/std" "github.com/gnolang/gno/tm2/pkg/store/dbadapter" storetypes "github.com/gnolang/gno/tm2/pkg/store/types" "github.com/stretchr/testify/assert" @@ -23,10 +23,10 @@ func TestTransactionStore(t *testing.T) { Store: txSt, Output: io.Discard, }) - _, pv := m.RunMemPackage(&std.MemPackage{ + _, pv := m.RunMemPackage(&gnovm.MemPackage{ Name: "hello", Path: "hello", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ {Name: "hello.gno", Body: "package hello; func main() { println(A(11)); }; type A int"}, }, }, true) @@ -59,7 +59,6 @@ func TestTransactionStore_blockedMethods(t *testing.T) { // only be changed in the root store. assert.Panics(t, func() { transactionStore{}.SetPackageGetter(nil) }) assert.Panics(t, func() { transactionStore{}.ClearCache() }) - assert.Panics(t, func() { transactionStore{}.SetPackageInjector(nil) }) assert.Panics(t, func() { transactionStore{}.SetNativeStore(nil) }) assert.Panics(t, func() { transactionStore{}.SetStrictGo2GnoMapping(false) }) } @@ -76,10 +75,10 @@ func TestCopyFromCachedStore(t *testing.T) { Name: "Reader", Base: BoolType, }) - cachedStore.AddMemPackage(&std.MemPackage{ + cachedStore.AddMemPackage(&gnovm.MemPackage{ Name: "math", Path: "math", - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ {Name: "math.gno", Body: "package math"}, }, }) diff --git a/gnovm/pkg/gnolang/transcribe.go b/gnovm/pkg/gnolang/transcribe.go index 28e97ff2b5b..dab539a8707 100644 --- a/gnovm/pkg/gnolang/transcribe.go +++ b/gnovm/pkg/gnolang/transcribe.go @@ -47,6 +47,7 @@ const ( TRANS_COMPOSITE_KEY TRANS_COMPOSITE_VALUE TRANS_FUNCLIT_TYPE + TRANS_FUNCLIT_HEAP_CAPTURE TRANS_FUNCLIT_BODY TRANS_FIELDTYPE_TYPE TRANS_FIELDTYPE_TAG @@ -100,6 +101,7 @@ const ( TRANS_IMPORT_PATH TRANS_CONST_TYPE TRANS_CONST_VALUE + TRANS_VAR_NAME // XXX stringer TRANS_VAR_TYPE TRANS_VAR_VALUE TRANS_TYPE_TYPE @@ -112,6 +114,7 @@ const ( // ENTER,CHILDS1,[BLOCK,CHILDS2]?,LEAVE sequence for that node, // i.e. skipping (the rest of) it; // - TRANS_BREAK to break out of looping in CHILDS1 or CHILDS2, +// but still perform TRANS_LEAVE. // - TRANS_EXIT to stop traversing altogether. // // Do not mutate ns. @@ -264,6 +267,14 @@ func transcribe(t Transform, ns []Node, ftype TransField, index int, n Node, nc if isStopOrSkip(nc, c) { return } + for idx := range cnn.HeapCaptures { + cnn.HeapCaptures[idx] = *(transcribe(t, nns, TRANS_FUNCLIT_HEAP_CAPTURE, idx, &cnn.HeapCaptures[idx], &c).(*NameExpr)) + if isBreak(c) { + break + } else if isStopOrSkip(nc, c) { + return + } + } cnn2, c2 := t(ns, ftype, index, cnn, TRANS_BLOCK) if isStopOrSkip(nc, c2) { nn = cnn2 @@ -692,6 +703,10 @@ func transcribe(t Transform, ns []Node, ftype TransField, index int, n Node, nc return } } + // XXX consider RHS, LHS, RHS, LHS, ... order. + for idx := range cnn.NameExprs { + cnn.NameExprs[idx] = *(transcribe(t, nns, TRANS_VAR_NAME, idx, &cnn.NameExprs[idx], &c).(*NameExpr)) + } for idx := range cnn.Values { cnn.Values[idx] = transcribe(t, nns, TRANS_VAR_VALUE, idx, cnn.Values[idx], &c).(Expr) if isBreak(c) { diff --git a/gnovm/pkg/gnolang/transfield_string.go b/gnovm/pkg/gnolang/transfield_string.go index 587ca7a7654..31afcf2be0d 100644 --- a/gnovm/pkg/gnolang/transfield_string.go +++ b/gnovm/pkg/gnolang/transfield_string.go @@ -29,68 +29,70 @@ func _() { _ = x[TRANS_COMPOSITE_KEY-18] _ = x[TRANS_COMPOSITE_VALUE-19] _ = x[TRANS_FUNCLIT_TYPE-20] - _ = x[TRANS_FUNCLIT_BODY-21] - _ = x[TRANS_FIELDTYPE_TYPE-22] - _ = x[TRANS_FIELDTYPE_TAG-23] - _ = x[TRANS_ARRAYTYPE_LEN-24] - _ = x[TRANS_ARRAYTYPE_ELT-25] - _ = x[TRANS_SLICETYPE_ELT-26] - _ = x[TRANS_INTERFACETYPE_METHOD-27] - _ = x[TRANS_CHANTYPE_VALUE-28] - _ = x[TRANS_FUNCTYPE_PARAM-29] - _ = x[TRANS_FUNCTYPE_RESULT-30] - _ = x[TRANS_MAPTYPE_KEY-31] - _ = x[TRANS_MAPTYPE_VALUE-32] - _ = x[TRANS_STRUCTTYPE_FIELD-33] - _ = x[TRANS_MAYBENATIVETYPE_TYPE-34] - _ = x[TRANS_ASSIGN_LHS-35] - _ = x[TRANS_ASSIGN_RHS-36] - _ = x[TRANS_BLOCK_BODY-37] - _ = x[TRANS_DECL_BODY-38] - _ = x[TRANS_DEFER_CALL-39] - _ = x[TRANS_EXPR_X-40] - _ = x[TRANS_FOR_INIT-41] - _ = x[TRANS_FOR_COND-42] - _ = x[TRANS_FOR_POST-43] - _ = x[TRANS_FOR_BODY-44] - _ = x[TRANS_GO_CALL-45] - _ = x[TRANS_IF_INIT-46] - _ = x[TRANS_IF_COND-47] - _ = x[TRANS_IF_BODY-48] - _ = x[TRANS_IF_ELSE-49] - _ = x[TRANS_IF_CASE_BODY-50] - _ = x[TRANS_INCDEC_X-51] - _ = x[TRANS_RANGE_X-52] - _ = x[TRANS_RANGE_KEY-53] - _ = x[TRANS_RANGE_VALUE-54] - _ = x[TRANS_RANGE_BODY-55] - _ = x[TRANS_RETURN_RESULT-56] - _ = x[TRANS_PANIC_EXCEPTION-57] - _ = x[TRANS_SELECT_CASE-58] - _ = x[TRANS_SELECTCASE_COMM-59] - _ = x[TRANS_SELECTCASE_BODY-60] - _ = x[TRANS_SEND_CHAN-61] - _ = x[TRANS_SEND_VALUE-62] - _ = x[TRANS_SWITCH_INIT-63] - _ = x[TRANS_SWITCH_X-64] - _ = x[TRANS_SWITCH_CASE-65] - _ = x[TRANS_SWITCHCASE_CASE-66] - _ = x[TRANS_SWITCHCASE_BODY-67] - _ = x[TRANS_FUNC_RECV-68] - _ = x[TRANS_FUNC_TYPE-69] - _ = x[TRANS_FUNC_BODY-70] - _ = x[TRANS_IMPORT_PATH-71] - _ = x[TRANS_CONST_TYPE-72] - _ = x[TRANS_CONST_VALUE-73] - _ = x[TRANS_VAR_TYPE-74] - _ = x[TRANS_VAR_VALUE-75] - _ = x[TRANS_TYPE_TYPE-76] - _ = x[TRANS_FILE_BODY-77] + _ = x[TRANS_FUNCLIT_HEAP_CAPTURE-21] + _ = x[TRANS_FUNCLIT_BODY-22] + _ = x[TRANS_FIELDTYPE_TYPE-23] + _ = x[TRANS_FIELDTYPE_TAG-24] + _ = x[TRANS_ARRAYTYPE_LEN-25] + _ = x[TRANS_ARRAYTYPE_ELT-26] + _ = x[TRANS_SLICETYPE_ELT-27] + _ = x[TRANS_INTERFACETYPE_METHOD-28] + _ = x[TRANS_CHANTYPE_VALUE-29] + _ = x[TRANS_FUNCTYPE_PARAM-30] + _ = x[TRANS_FUNCTYPE_RESULT-31] + _ = x[TRANS_MAPTYPE_KEY-32] + _ = x[TRANS_MAPTYPE_VALUE-33] + _ = x[TRANS_STRUCTTYPE_FIELD-34] + _ = x[TRANS_MAYBENATIVETYPE_TYPE-35] + _ = x[TRANS_ASSIGN_LHS-36] + _ = x[TRANS_ASSIGN_RHS-37] + _ = x[TRANS_BLOCK_BODY-38] + _ = x[TRANS_DECL_BODY-39] + _ = x[TRANS_DEFER_CALL-40] + _ = x[TRANS_EXPR_X-41] + _ = x[TRANS_FOR_INIT-42] + _ = x[TRANS_FOR_COND-43] + _ = x[TRANS_FOR_POST-44] + _ = x[TRANS_FOR_BODY-45] + _ = x[TRANS_GO_CALL-46] + _ = x[TRANS_IF_INIT-47] + _ = x[TRANS_IF_COND-48] + _ = x[TRANS_IF_BODY-49] + _ = x[TRANS_IF_ELSE-50] + _ = x[TRANS_IF_CASE_BODY-51] + _ = x[TRANS_INCDEC_X-52] + _ = x[TRANS_RANGE_X-53] + _ = x[TRANS_RANGE_KEY-54] + _ = x[TRANS_RANGE_VALUE-55] + _ = x[TRANS_RANGE_BODY-56] + _ = x[TRANS_RETURN_RESULT-57] + _ = x[TRANS_PANIC_EXCEPTION-58] + _ = x[TRANS_SELECT_CASE-59] + _ = x[TRANS_SELECTCASE_COMM-60] + _ = x[TRANS_SELECTCASE_BODY-61] + _ = x[TRANS_SEND_CHAN-62] + _ = x[TRANS_SEND_VALUE-63] + _ = x[TRANS_SWITCH_INIT-64] + _ = x[TRANS_SWITCH_X-65] + _ = x[TRANS_SWITCH_CASE-66] + _ = x[TRANS_SWITCHCASE_CASE-67] + _ = x[TRANS_SWITCHCASE_BODY-68] + _ = x[TRANS_FUNC_RECV-69] + _ = x[TRANS_FUNC_TYPE-70] + _ = x[TRANS_FUNC_BODY-71] + _ = x[TRANS_IMPORT_PATH-72] + _ = x[TRANS_CONST_TYPE-73] + _ = x[TRANS_CONST_VALUE-74] + _ = x[TRANS_VAR_NAME-75] + _ = x[TRANS_VAR_TYPE-76] + _ = x[TRANS_VAR_VALUE-77] + _ = x[TRANS_TYPE_TYPE-78] + _ = x[TRANS_FILE_BODY-79] } -const _TransField_name = "TRANS_ROOTTRANS_BINARY_LEFTTRANS_BINARY_RIGHTTRANS_CALL_FUNCTRANS_CALL_ARGTRANS_INDEX_XTRANS_INDEX_INDEXTRANS_SELECTOR_XTRANS_SLICE_XTRANS_SLICE_LOWTRANS_SLICE_HIGHTRANS_SLICE_MAXTRANS_STAR_XTRANS_REF_XTRANS_TYPEASSERT_XTRANS_TYPEASSERT_TYPETRANS_UNARY_XTRANS_COMPOSITE_TYPETRANS_COMPOSITE_KEYTRANS_COMPOSITE_VALUETRANS_FUNCLIT_TYPETRANS_FUNCLIT_BODYTRANS_FIELDTYPE_TYPETRANS_FIELDTYPE_TAGTRANS_ARRAYTYPE_LENTRANS_ARRAYTYPE_ELTTRANS_SLICETYPE_ELTTRANS_INTERFACETYPE_METHODTRANS_CHANTYPE_VALUETRANS_FUNCTYPE_PARAMTRANS_FUNCTYPE_RESULTTRANS_MAPTYPE_KEYTRANS_MAPTYPE_VALUETRANS_STRUCTTYPE_FIELDTRANS_MAYBENATIVETYPE_TYPETRANS_ASSIGN_LHSTRANS_ASSIGN_RHSTRANS_BLOCK_BODYTRANS_DECL_BODYTRANS_DEFER_CALLTRANS_EXPR_XTRANS_FOR_INITTRANS_FOR_CONDTRANS_FOR_POSTTRANS_FOR_BODYTRANS_GO_CALLTRANS_IF_INITTRANS_IF_CONDTRANS_IF_BODYTRANS_IF_ELSETRANS_IF_CASE_BODYTRANS_INCDEC_XTRANS_RANGE_XTRANS_RANGE_KEYTRANS_RANGE_VALUETRANS_RANGE_BODYTRANS_RETURN_RESULTTRANS_PANIC_EXCEPTIONTRANS_SELECT_CASETRANS_SELECTCASE_COMMTRANS_SELECTCASE_BODYTRANS_SEND_CHANTRANS_SEND_VALUETRANS_SWITCH_INITTRANS_SWITCH_XTRANS_SWITCH_CASETRANS_SWITCHCASE_CASETRANS_SWITCHCASE_BODYTRANS_FUNC_RECVTRANS_FUNC_TYPETRANS_FUNC_BODYTRANS_IMPORT_PATHTRANS_CONST_TYPETRANS_CONST_VALUETRANS_VAR_TYPETRANS_VAR_VALUETRANS_TYPE_TYPETRANS_FILE_BODY" +const _TransField_name = "TRANS_ROOTTRANS_BINARY_LEFTTRANS_BINARY_RIGHTTRANS_CALL_FUNCTRANS_CALL_ARGTRANS_INDEX_XTRANS_INDEX_INDEXTRANS_SELECTOR_XTRANS_SLICE_XTRANS_SLICE_LOWTRANS_SLICE_HIGHTRANS_SLICE_MAXTRANS_STAR_XTRANS_REF_XTRANS_TYPEASSERT_XTRANS_TYPEASSERT_TYPETRANS_UNARY_XTRANS_COMPOSITE_TYPETRANS_COMPOSITE_KEYTRANS_COMPOSITE_VALUETRANS_FUNCLIT_TYPETRANS_FUNCLIT_HEAP_CAPTURETRANS_FUNCLIT_BODYTRANS_FIELDTYPE_TYPETRANS_FIELDTYPE_TAGTRANS_ARRAYTYPE_LENTRANS_ARRAYTYPE_ELTTRANS_SLICETYPE_ELTTRANS_INTERFACETYPE_METHODTRANS_CHANTYPE_VALUETRANS_FUNCTYPE_PARAMTRANS_FUNCTYPE_RESULTTRANS_MAPTYPE_KEYTRANS_MAPTYPE_VALUETRANS_STRUCTTYPE_FIELDTRANS_MAYBENATIVETYPE_TYPETRANS_ASSIGN_LHSTRANS_ASSIGN_RHSTRANS_BLOCK_BODYTRANS_DECL_BODYTRANS_DEFER_CALLTRANS_EXPR_XTRANS_FOR_INITTRANS_FOR_CONDTRANS_FOR_POSTTRANS_FOR_BODYTRANS_GO_CALLTRANS_IF_INITTRANS_IF_CONDTRANS_IF_BODYTRANS_IF_ELSETRANS_IF_CASE_BODYTRANS_INCDEC_XTRANS_RANGE_XTRANS_RANGE_KEYTRANS_RANGE_VALUETRANS_RANGE_BODYTRANS_RETURN_RESULTTRANS_PANIC_EXCEPTIONTRANS_SELECT_CASETRANS_SELECTCASE_COMMTRANS_SELECTCASE_BODYTRANS_SEND_CHANTRANS_SEND_VALUETRANS_SWITCH_INITTRANS_SWITCH_XTRANS_SWITCH_CASETRANS_SWITCHCASE_CASETRANS_SWITCHCASE_BODYTRANS_FUNC_RECVTRANS_FUNC_TYPETRANS_FUNC_BODYTRANS_IMPORT_PATHTRANS_CONST_TYPETRANS_CONST_VALUETRANS_VAR_NAMETRANS_VAR_TYPETRANS_VAR_VALUETRANS_TYPE_TYPETRANS_FILE_BODY" -var _TransField_index = [...]uint16{0, 10, 27, 45, 60, 74, 87, 104, 120, 133, 148, 164, 179, 191, 202, 220, 241, 254, 274, 293, 314, 332, 350, 370, 389, 408, 427, 446, 472, 492, 512, 533, 550, 569, 591, 617, 633, 649, 665, 680, 696, 708, 722, 736, 750, 764, 777, 790, 803, 816, 829, 847, 861, 874, 889, 906, 922, 941, 962, 979, 1000, 1021, 1036, 1052, 1069, 1083, 1100, 1121, 1142, 1157, 1172, 1187, 1204, 1220, 1237, 1251, 1266, 1281, 1296} +var _TransField_index = [...]uint16{0, 10, 27, 45, 60, 74, 87, 104, 120, 133, 148, 164, 179, 191, 202, 220, 241, 254, 274, 293, 314, 332, 358, 376, 396, 415, 434, 453, 472, 498, 518, 538, 559, 576, 595, 617, 643, 659, 675, 691, 706, 722, 734, 748, 762, 776, 790, 803, 816, 829, 842, 855, 873, 887, 900, 915, 932, 948, 967, 988, 1005, 1026, 1047, 1062, 1078, 1095, 1109, 1126, 1147, 1168, 1183, 1198, 1213, 1230, 1246, 1263, 1277, 1291, 1306, 1321, 1336} func (i TransField) String() string { if i >= TransField(len(_TransField_index)-1) { diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index 31025fef152..f86c44e7921 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -47,8 +47,8 @@ var ( MUL_ASSIGN: isNumeric, QUO_ASSIGN: isNumeric, REM_ASSIGN: isIntNum, - SHL_ASSIGN: isNumeric, - SHR_ASSIGN: isNumeric, + SHL_ASSIGN: isIntNum, + SHR_ASSIGN: isIntNum, BAND_ASSIGN: isIntNum, XOR_ASSIGN: isIntNum, BOR_ASSIGN: isIntNum, @@ -583,10 +583,73 @@ func checkAssignableTo(xt, dt Type, autoNative bool) error { } // =========================================================== -func (x *BinaryExpr) checkShiftLhs(dt Type) { +// this check happens while trans_leave binary expression. +// it checks if type of RHS is valid. +// Check part of the LHS to ensure it is of a numeric type. +// More stringent checks will be performed in the subsequent stage in +// assertShiftExprCompatible2. +func (x *BinaryExpr) assertShiftExprCompatible1(store Store, last BlockNode, lt, rt Type) { + // check rhs type + if rt == nil { + panic(fmt.Sprintf("cannot convert %v to type uint", x.Right)) + } + + lcx, lic := x.Left.(*ConstExpr) + _, ric := x.Right.(*ConstExpr) + // step1, check RHS type + // special case when rhs is not integer + if !isNumeric(rt) { + panic(fmt.Sprintf("cannot convert %v to type uint", x.Right)) + } + if !isIntNum(rt) { + var isIntValue bool + // special case for num like 1.0, it will be converted to uint later + if ric { + rv := evalConst(store, last, x.Right) + if bd, ok := rv.V.(BigdecValue); ok { + if isInteger(bd.V) { + isIntValue = true + } + } + } + if !isIntValue { + panic(fmt.Sprintf("invalid operation: invalid shift count: %v", x.Right)) + } + } else if ric { // is integer, check negative + rv := evalConst(store, last, x.Right) + if rv.Sign() < 0 { + panic(fmt.Sprintf("invalid operation: negative shift count: %v", x.Right)) + } + } + + // step2, check lhs type if checker, ok := binaryChecker[x.Op]; ok { - if !checker(dt) { - panic(fmt.Sprintf("operator %s not defined on: %v", x.Op.TokenString(), kindString(dt))) + if checker(lt) { // check pass + return + } + // special case for 1.0 + if lt == UntypedBigdecType { + // 1.0 << 1 + if lic && ric { + convertConst(store, last, lcx, UntypedBigintType) + return + } + } + // not const, e.g. 1.0 << x, see types/shift_d5.gno + if isNumeric(lt) { + return + } + panic(fmt.Sprintf("operator %s not defined on: %v", x.Op.TokenString(), kindString(lt))) + } + panic(fmt.Sprintf("checker for %s does not exist", x.Op)) +} + +// used in checkOrConvertType, only check lhs type +func (x *BinaryExpr) assertShiftExprCompatible2(t Type) { + // check lhs type + if checker, ok := binaryChecker[x.Op]; ok { + if !checker(t) { + panic(fmt.Sprintf("operator %s not defined on: %v", x.Op.TokenString(), kindString(t))) } } else { panic(fmt.Sprintf("checker for %s does not exist", x.Op)) @@ -654,7 +717,7 @@ func (x *BinaryExpr) AssertCompatible(lt, rt Type) { // special case of zero divisor if isQuoOrRem(x.Op) { if rcx, ok := x.Right.(*ConstExpr); ok { - if rcx.TypedValue.isZero() { + if rcx.TypedValue.Sign() == 0 { panic("invalid operation: division by zero") } } @@ -792,8 +855,8 @@ func (x *AssignStmt) AssertCompatible(store Store, last BlockNode) { if x.Op == ASSIGN { // check assignable for i, lx := range x.Lhs { + assertValidAssignLhs(store, last, lx) if !isBlankIdentifier(lx) { - assertValidAssignLhs(store, last, lx) lxt := evalStaticTypeOf(store, last, lx) assertAssignableTo(cft.Results[i].Type, lxt, false) } @@ -805,15 +868,16 @@ func (x *AssignStmt) AssertCompatible(store Store, last BlockNode) { panic("should not happen") } if x.Op == ASSIGN { - // check assignable to first value + // check first value + assertValidAssignLhs(store, last, x.Lhs[0]) if !isBlankIdentifier(x.Lhs[0]) { // see composite3.gno - assertValidAssignLhs(store, last, x.Lhs[0]) dt := evalStaticTypeOf(store, last, x.Lhs[0]) ift := evalStaticTypeOf(store, last, cx) assertAssignableTo(ift, dt, false) } + // check second value + assertValidAssignLhs(store, last, x.Lhs[1]) if !isBlankIdentifier(x.Lhs[1]) { // see composite3.gno - assertValidAssignLhs(store, last, x.Lhs[1]) dt := evalStaticTypeOf(store, last, x.Lhs[1]) if dt.Kind() != BoolKind { // typed, not bool panic(fmt.Sprintf("want bool type got %v", dt)) @@ -826,8 +890,8 @@ func (x *AssignStmt) AssertCompatible(store Store, last BlockNode) { panic("should not happen") } if x.Op == ASSIGN { + assertValidAssignLhs(store, last, x.Lhs[0]) if !isBlankIdentifier(x.Lhs[0]) { - assertValidAssignLhs(store, last, x.Lhs[0]) lt := evalStaticTypeOf(store, last, x.Lhs[0]) if _, ok := cx.X.(*NameExpr); ok { rt := evalStaticTypeOf(store, last, cx.X) @@ -843,8 +907,9 @@ func (x *AssignStmt) AssertCompatible(store Store, last BlockNode) { } } } + + assertValidAssignLhs(store, last, x.Lhs[1]) if !isBlankIdentifier(x.Lhs[1]) { - assertValidAssignLhs(store, last, x.Lhs[1]) dt := evalStaticTypeOf(store, last, x.Lhs[1]) if dt != nil && dt.Kind() != BoolKind { // typed, not bool panic(fmt.Sprintf("want bool type got %v", dt)) @@ -870,30 +935,38 @@ func (x *AssignStmt) AssertCompatible(store Store, last BlockNode) { panic("assignment operator " + x.Op.TokenString() + " requires only one expression on lhs and rhs") } - for i, lx := range x.Lhs { - lt := evalStaticTypeOf(store, last, lx) - rt := evalStaticTypeOf(store, last, x.Rhs[i]) + lt := evalStaticTypeOf(store, last, x.Lhs[0]) + rt := evalStaticTypeOf(store, last, x.Rhs[0]) - if checker, ok := AssignStmtChecker[x.Op]; ok { - if !checker(lt) { - panic(fmt.Sprintf("operator %s not defined on: %v", x.Op.TokenString(), kindString(lt))) - } - switch x.Op { - case ADD_ASSIGN, SUB_ASSIGN, MUL_ASSIGN, QUO_ASSIGN, REM_ASSIGN, BAND_ASSIGN, BOR_ASSIGN, BAND_NOT_ASSIGN, XOR_ASSIGN: - // check when both typed - if !isUntyped(lt) && !isUntyped(rt) { // in this stage, lt or rt maybe untyped, not converted yet - if lt != nil && rt != nil { - if lt.TypeID() != rt.TypeID() { - panic(fmt.Sprintf("invalid operation: mismatched types %v and %v", lt, rt)) - } + if checker, ok := AssignStmtChecker[x.Op]; ok { + if !checker(lt) { + panic(fmt.Sprintf("operator %s not defined on: %v", x.Op.TokenString(), kindString(lt))) + } + switch x.Op { + case ADD_ASSIGN, SUB_ASSIGN, MUL_ASSIGN, QUO_ASSIGN, REM_ASSIGN, BAND_ASSIGN, BOR_ASSIGN, BAND_NOT_ASSIGN, XOR_ASSIGN: + // check when both typed + if !isUntyped(lt) && !isUntyped(rt) { // in this stage, lt or rt maybe untyped, not converted yet + if lt != nil && rt != nil { + if lt.TypeID() != rt.TypeID() { + panic(fmt.Sprintf("invalid operation: mismatched types %v and %v", lt, rt)) } } - default: - // do nothing } - } else { - panic(fmt.Sprintf("checker for %s does not exist", x.Op)) + case SHL_ASSIGN, SHR_ASSIGN: + if !isIntNum(rt) { + panic(fmt.Sprintf("invalid operation: invalid shift count: %v", x.Rhs[0])) + } + _, ric := x.Rhs[0].(*ConstExpr) + // check negative + if ric { + rv := evalConst(store, last, x.Rhs[0]) + rv.AssertNonNegative("invalid operation: negative shift count") + } + default: + // do nothing } + } else { + panic(fmt.Sprintf("checker for %s does not exist", x.Op)) } } } @@ -902,7 +975,17 @@ func (x *AssignStmt) AssertCompatible(store Store, last BlockNode) { func assertValidAssignLhs(store Store, last BlockNode, lx Expr) { shouldPanic := true switch clx := lx.(type) { - case *NameExpr, *StarExpr, *SelectorExpr: + case *NameExpr: + if clx.Name == blankIdentifier { + shouldPanic = false + } else if clx.Path.Type == VPUverse { + panic(fmt.Sprintf("cannot assign to uverse %v", clx.Name)) + } else if last.GetIsConst(store, clx.Name) { + panic(fmt.Sprintf("cannot assign to const %v", clx.Name)) + } else { + shouldPanic = false + } + case *StarExpr, *SelectorExpr: shouldPanic = false case *IndexExpr: xt := evalStaticTypeOf(store, last, clx.X) @@ -946,7 +1029,7 @@ func isComparison(op Word) bool { // it returns true, indicating a swap is needed. func shouldSwapOnSpecificity(t1, t2 Type) bool { // check nil - if t1 == nil { // see test file 0f46 + if t1 == nil { return false // also with both nil } else if t2 == nil { return true @@ -985,7 +1068,7 @@ func shouldSwapOnSpecificity(t1, t2 Type) bool { func isBlankIdentifier(x Expr) bool { if nx, ok := x.(*NameExpr); ok { - return nx.Name == "_" + return nx.Name == blankIdentifier } return false } diff --git a/gnovm/pkg/gnolang/types.go b/gnovm/pkg/gnolang/types.go index b43f623ea99..eedb71ffa73 100644 --- a/gnovm/pkg/gnolang/types.go +++ b/gnovm/pkg/gnolang/types.go @@ -69,6 +69,7 @@ func (*PackageType) assertType() {} func (*ChanType) assertType() {} func (*NativeType) assertType() {} func (blockType) assertType() {} +func (heapItemType) assertType() {} func (*tupleType) assertType() {} func (RefType) assertType() {} func (MaybeNativeType) assertType() {} @@ -1964,6 +1965,35 @@ func (bt blockType) IsNamed() bool { panic("blockType has no property called named") } +// ---------------------------------------- +// heapItemType + +type heapItemType struct{} // no data + +func (bt heapItemType) Kind() Kind { + return HeapItemKind +} + +func (bt heapItemType) TypeID() TypeID { + return typeid("heapitem") +} + +func (bt heapItemType) String() string { + return "heapitem" +} + +func (bt heapItemType) Elem() Type { + panic("heapItemType has no elem type") +} + +func (bt heapItemType) GetPkgPath() string { + panic("heapItemType has no package path") +} + +func (bt heapItemType) IsNamed() bool { + panic("heapItemType has no property called named") +} + // ---------------------------------------- // tupleType @@ -2118,9 +2148,10 @@ const ( MapKind TypeKind // not in go. // UnsafePointerKind - BlockKind // not in go. - TupleKind // not in go. - RefTypeKind // not in go. + BlockKind // not in go. + HeapItemKind // not in go. + TupleKind // not in go. + RefTypeKind // not in go. ) // This is generally slower than switching on baseOf(t). @@ -2193,6 +2224,8 @@ func KindOf(t Type) Kind { return t.Kind() case blockType: return BlockKind + case heapItemType: + return HeapItemKind case *tupleType: return TupleKind case RefType: diff --git a/gnovm/pkg/gnolang/uverse.go b/gnovm/pkg/gnolang/uverse.go index d62d4228d68..ba66b27499f 100644 --- a/gnovm/pkg/gnolang/uverse.go +++ b/gnovm/pkg/gnolang/uverse.go @@ -61,26 +61,55 @@ var gStringerType = &DeclaredType{ var ( uverseNode *PackageNode uverseValue *PackageValue + uverseInit = uverseUninitialized ) +const ( + uverseUninitialized = iota + uverseInitializing + uverseInitialized +) + +func init() { + // Call Uverse() so we initialize the Uverse node ahead of any calls to the package. + Uverse() +} + const uversePkgPath = ".uverse" -// Always returns a new copy from the latest state of source. +// UverseNode returns the uverse PackageValue. +// If called while initializing the UverseNode itself, it will return an empty +// PackageValue. func Uverse() *PackageValue { - if uverseValue == nil { - pn := UverseNode() - uverseValue = pn.NewPackage() + switch uverseInit { + case uverseUninitialized: + uverseInit = uverseInitializing + makeUverseNode() + uverseInit = uverseInitialized + case uverseInitializing: + return &PackageValue{} } + return uverseValue } -// Always returns the same instance with possibly differing completeness. +// UverseNode returns the uverse PackageNode. +// If called while initializing the UverseNode itself, it will return an empty +// PackageNode. func UverseNode() *PackageNode { - // Global is singleton. - if uverseNode != nil { - return uverseNode + switch uverseInit { + case uverseUninitialized: + uverseInit = uverseInitializing + makeUverseNode() + uverseInit = uverseInitialized + case uverseInitializing: + return &PackageNode{} } + return uverseNode +} + +func makeUverseNode() { // NOTE: uverse node is hidden, thus the leading dot in pkgPath=".uverse". uverseNode = NewPackageNode("uverse", uversePkgPath, nil) @@ -1017,7 +1046,7 @@ func UverseNode() *PackageNode { m.Exceptions = nil }, ) - return uverseNode + uverseValue = uverseNode.NewPackage() } func copyDataToList(dst []TypedValue, data []byte, et Type) { diff --git a/gnovm/pkg/gnolang/values.go b/gnovm/pkg/gnolang/values.go index bbf77bf19c7..68c2967811f 100644 --- a/gnovm/pkg/gnolang/values.go +++ b/gnovm/pkg/gnolang/values.go @@ -534,12 +534,13 @@ func (sv *StructValue) Copy(alloc *Allocator) *StructValue { // makes construction TypedValue{T:*FuncType{},V:*FuncValue{}} // faster. type FuncValue struct { - Type Type // includes unbound receiver(s) - IsMethod bool // is an (unbound) method - Source BlockNode // for block mem allocation - Name Name // name of function/method - Closure Value // *Block or RefValue to closure (may be nil for file blocks; lazy) - FileName Name // file name where declared + Type Type // includes unbound receiver(s) + IsMethod bool // is an (unbound) method + Source BlockNode // for block mem allocation + Name Name // name of function/method + Closure Value // *Block or RefValue to closure (may be nil for file blocks; lazy) + Captures []TypedValue `json:",omitempty"` // HeapItemValues captured from closure. + FileName Name // file name where declared PkgPath string NativePkg string // for native bindings through NativeStore NativeName Name // not redundant with Name; this cannot be changed in userspace @@ -1509,86 +1510,31 @@ func (tv *TypedValue) GetBigDec() *apd.Decimal { return tv.V.(BigdecValue).V } -// returns true if tv is zero -func (tv *TypedValue) isZero() bool { +func (tv *TypedValue) Sign() int { if tv.T == nil { panic("type should not be nil") } + switch tv.T.Kind() { - case IntKind: - v := tv.GetInt() - if v == 0 { - return true - } - case Int8Kind: - v := tv.GetInt8() - if v == 0 { - return true - } - case Int16Kind: - v := tv.GetInt16() - if v == 0 { - return true - } - case Int32Kind: - v := tv.GetInt32() - if v == 0 { - return true - } - case Int64Kind: - v := tv.GetInt64() - if v == 0 { - return true - } - case UintKind: - v := tv.GetUint() - if v == 0 { - return true - } - case Uint8Kind: - v := tv.GetUint8() - if v == 0 { - return true - } - case Uint16Kind: - v := tv.GetUint16() - if v == 0 { - return true - } - case Uint32Kind: - v := tv.GetUint32() - if v == 0 { - return true - } - case Uint64Kind: - v := tv.GetUint64() - if v == 0 { - return true - } - case Float32Kind: - v := tv.GetFloat32() - if v == 0 { - return true - } - case Float64Kind: - v := tv.GetFloat64() - if v == 0 { - return true - } + case UintKind, Uint8Kind, Uint16Kind, Uint32Kind, Uint64Kind: + return signOfUnsignedBytes(tv.N) + case IntKind, Int8Kind, Int16Kind, Int32Kind, Int64Kind, Float32Kind, Float64Kind: + return signOfSignedBytes(tv.N) case BigintKind: v := tv.GetBigInt() - if v.Sign() == 0 { - return true - } + return v.Sign() case BigdecKind: v := tv.GetBigDec() - if v.Sign() == 0 { - return true - } + return v.Sign() default: - panic("not numeric") + panic("type should be numeric") + } +} + +func (tv *TypedValue) AssertNonNegative(msg string) { + if tv.Sign() < 0 { + panic(fmt.Sprintf("%s: %v", msg, tv)) } - return false } func (tv *TypedValue) ComputeMapKey(store Store, omitType bool) MapKey { @@ -1700,10 +1646,10 @@ func (tv *TypedValue) Assign(alloc *Allocator, tv2 TypedValue, cu bool) { // or binary operations. When a pointer is to be // allocated, *Allocator.AllocatePointer() is called separately, // as in OpRef. -func (tv *TypedValue) GetPointerTo(alloc *Allocator, store Store, path ValuePath) PointerValue { +func (tv *TypedValue) GetPointerToFromTV(alloc *Allocator, store Store, path ValuePath) PointerValue { if debug { if tv.IsUndefined() { - panic("GetPointerTo() on undefined value") + panic("GetPointerToFromTV() on undefined value") } } @@ -1922,7 +1868,7 @@ func (tv *TypedValue) GetPointerTo(alloc *Allocator, store Store, path ValuePath } bv := *dtv for i, path := range tr { - ptr := bv.GetPointerTo(alloc, store, path) + ptr := bv.GetPointerToFromTV(alloc, store, path) if i == len(tr)-1 { return ptr // done } @@ -2491,6 +2437,70 @@ func (b *Block) GetPointerTo(store Store, path ValuePath) PointerValue { return b.GetPointerToInt(store, int(path.Index)) } +// Convenience +func (b *Block) GetPointerToMaybeHeapUse(store Store, nx *NameExpr) PointerValue { + switch nx.Type { + case NameExprTypeNormal: + return b.GetPointerTo(store, nx.Path) + case NameExprTypeHeapUse: + return b.GetPointerToHeapUse(store, nx.Path) + case NameExprTypeHeapClosure: + panic("should not happen with type heap closure") + default: + panic("unexpected NameExpr type for GetPointerToMaybeHeapUse") + } +} + +// Convenience +func (b *Block) GetPointerToMaybeHeapDefine(store Store, nx *NameExpr) PointerValue { + switch nx.Type { + case NameExprTypeNormal: + return b.GetPointerTo(store, nx.Path) + case NameExprTypeDefine: + return b.GetPointerTo(store, nx.Path) + case NameExprTypeHeapDefine: + return b.GetPointerToHeapDefine(store, nx.Path) + default: + panic("unexpected NameExpr type for GetPointerToMaybeHeapDefine") + } +} + +// First defines a new HeapItemValue. +// This gets called from NameExprTypeHeapDefine name expressions. +func (b *Block) GetPointerToHeapDefine(store Store, path ValuePath) PointerValue { + ptr := b.GetPointerTo(store, path) + hiv := &HeapItemValue{} + // point to a heapItem + *ptr.TV = TypedValue{ + T: heapItemType{}, + V: hiv, + } + + return PointerValue{ + TV: &hiv.Value, + Base: hiv, + Index: 0, + } +} + +// Assumes a HeapItemValue, and gets inner pointer. +// This gets called from NameExprTypeHeapUse name expressions. +func (b *Block) GetPointerToHeapUse(store Store, path ValuePath) PointerValue { + ptr := b.GetPointerTo(store, path) + if _, ok := ptr.TV.T.(heapItemType); !ok { + panic("should not happen, should be heapItemType") + } + if _, ok := ptr.TV.V.(*HeapItemValue); !ok { + panic("should not happen, should be HeapItemValue") + } + + return PointerValue{ + TV: &ptr.TV.V.(*HeapItemValue).Value, + Base: ptr.TV.V, + Index: 0, + } +} + // Result is used has lhs for any assignments to "_". func (b *Block) GetBlankRef() *TypedValue { return &b.Blank @@ -2693,3 +2703,24 @@ func fillValueTV(store Store, tv *TypedValue) *TypedValue { } return tv } + +// ---------------------------------------- +// Utility +func signOfSignedBytes(n [8]byte) int { + si := *(*int64)(unsafe.Pointer(&n[0])) + switch { + case si == 0: + return 0 + case si < 0: + return -1 + default: + return 1 + } +} + +func signOfUnsignedBytes(n [8]byte) int { + if *(*uint64)(unsafe.Pointer(&n[0])) == 0 { + return 0 + } + return 1 +} diff --git a/gnovm/pkg/gnolang/values_conversions.go b/gnovm/pkg/gnolang/values_conversions.go index c5ddc232fcb..9ec3427ed8f 100644 --- a/gnovm/pkg/gnolang/values_conversions.go +++ b/gnovm/pkg/gnolang/values_conversions.go @@ -44,6 +44,7 @@ func ConvertTo(alloc *Allocator, store Store, tv *TypedValue, t Type) { tv.T = t return } else { + // both NativeType, use reflect to assert. // convert go-native to gno type (shallow). *tv = go2GnoValue2(alloc, store, tv.V.(*NativeValue).Value, false) ConvertTo(alloc, store, tv, t) diff --git a/gnovm/pkg/gnomod/gnomod.go b/gnovm/pkg/gnomod/gnomod.go index 0effa532107..553bb32f4b5 100644 --- a/gnovm/pkg/gnomod/gnomod.go +++ b/gnovm/pkg/gnomod/gnomod.go @@ -9,10 +9,10 @@ import ( "path/filepath" "strings" + "github.com/gnolang/gno/gnovm" "github.com/gnolang/gno/gnovm/pkg/gnoenv" "github.com/gnolang/gno/gnovm/pkg/gnolang" "github.com/gnolang/gno/gnovm/pkg/transpiler" - "github.com/gnolang/gno/tm2/pkg/std" "golang.org/x/mod/modfile" "golang.org/x/mod/module" ) @@ -43,7 +43,7 @@ func writePackage(remote, basePath, pkgPath string) (requirements []string, err return nil, fmt.Errorf("querychain (%s): %w", pkgPath, err) } - dirPath, fileName := std.SplitFilepath(pkgPath) + dirPath, fileName := gnovm.SplitFilepath(pkgPath) if fileName == "" { // Is Dir // Create Dir if not exists diff --git a/gnovm/pkg/gnomod/read.go b/gnovm/pkg/gnomod/read.go index a7a600f8826..d6d771429d3 100644 --- a/gnovm/pkg/gnomod/read.go +++ b/gnovm/pkg/gnomod/read.go @@ -249,7 +249,7 @@ func (in *input) readToken() { // Otherwise, save comment for later attachment to syntax tree. in.endToken(_EOLCOMMENT) - in.comments = append(in.comments, modfile.Comment{in.token.pos, in.token.text, suffix}) + in.comments = append(in.comments, modfile.Comment{Start: in.token.pos, Token: in.token.text, Suffix: suffix}) return } diff --git a/gnovm/stdlibs/generated.go b/gnovm/stdlibs/generated.go index 4c460e220b7..a2d82b0bc60 100644 --- a/gnovm/stdlibs/generated.go +++ b/gnovm/stdlibs/generated.go @@ -11,7 +11,6 @@ import ( libs_crypto_sha256 "github.com/gnolang/gno/gnovm/stdlibs/crypto/sha256" libs_math "github.com/gnolang/gno/gnovm/stdlibs/math" libs_std "github.com/gnolang/gno/gnovm/stdlibs/std" - libs_strconv "github.com/gnolang/gno/gnovm/stdlibs/strconv" libs_testing "github.com/gnolang/gno/gnovm/stdlibs/testing" libs_time "github.com/gnolang/gno/gnovm/stdlibs/time" ) @@ -722,249 +721,145 @@ var nativeFuncs = [...]NativeFunc{ }, }, { - "strconv", - "Itoa", - []gno.FieldTypeExpr{ - {Name: gno.N("p0"), Type: gno.X("int")}, - }, - []gno.FieldTypeExpr{ - {Name: gno.N("r0"), Type: gno.X("string")}, - }, - false, - func(m *gno.Machine) { - b := m.LastBlock() - var ( - p0 int - rp0 = reflect.ValueOf(&p0).Elem() - ) - - gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 0, "")).TV, rp0) - - r0 := libs_strconv.Itoa(p0) - - m.PushValue(gno.Go2GnoValue( - m.Alloc, - m.Store, - reflect.ValueOf(&r0).Elem(), - )) - }, - }, - { - "strconv", - "AppendUint", - []gno.FieldTypeExpr{ - {Name: gno.N("p0"), Type: gno.X("[]byte")}, - {Name: gno.N("p1"), Type: gno.X("uint64")}, - {Name: gno.N("p2"), Type: gno.X("int")}, - }, - []gno.FieldTypeExpr{ - {Name: gno.N("r0"), Type: gno.X("[]byte")}, - }, - false, + "std", + "assertCallerIsRealm", + []gno.FieldTypeExpr{}, + []gno.FieldTypeExpr{}, + true, func(m *gno.Machine) { - b := m.LastBlock() - var ( - p0 []byte - rp0 = reflect.ValueOf(&p0).Elem() - p1 uint64 - rp1 = reflect.ValueOf(&p1).Elem() - p2 int - rp2 = reflect.ValueOf(&p2).Elem() + libs_std.X_assertCallerIsRealm( + m, ) - - gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 0, "")).TV, rp0) - gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 1, "")).TV, rp1) - gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 2, "")).TV, rp2) - - r0 := libs_strconv.AppendUint(p0, p1, p2) - - m.PushValue(gno.Go2GnoValue( - m.Alloc, - m.Store, - reflect.ValueOf(&r0).Elem(), - )) }, }, { - "strconv", - "Atoi", + "std", + "setParamString", []gno.FieldTypeExpr{ {Name: gno.N("p0"), Type: gno.X("string")}, + {Name: gno.N("p1"), Type: gno.X("string")}, }, - []gno.FieldTypeExpr{ - {Name: gno.N("r0"), Type: gno.X("int")}, - {Name: gno.N("r1"), Type: gno.X("error")}, - }, - false, + []gno.FieldTypeExpr{}, + true, func(m *gno.Machine) { b := m.LastBlock() var ( p0 string rp0 = reflect.ValueOf(&p0).Elem() + p1 string + rp1 = reflect.ValueOf(&p1).Elem() ) gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 0, "")).TV, rp0) + gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 1, "")).TV, rp1) - r0, r1 := libs_strconv.Atoi(p0) - - m.PushValue(gno.Go2GnoValue( - m.Alloc, - m.Store, - reflect.ValueOf(&r0).Elem(), - )) - m.PushValue(gno.Go2GnoValue( - m.Alloc, - m.Store, - reflect.ValueOf(&r1).Elem(), - )) + libs_std.X_setParamString( + m, + p0, p1) }, }, { - "strconv", - "CanBackquote", + "std", + "setParamBool", []gno.FieldTypeExpr{ {Name: gno.N("p0"), Type: gno.X("string")}, + {Name: gno.N("p1"), Type: gno.X("bool")}, }, - []gno.FieldTypeExpr{ - {Name: gno.N("r0"), Type: gno.X("bool")}, - }, - false, + []gno.FieldTypeExpr{}, + true, func(m *gno.Machine) { b := m.LastBlock() var ( p0 string rp0 = reflect.ValueOf(&p0).Elem() - ) - - gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 0, "")).TV, rp0) - - r0 := libs_strconv.CanBackquote(p0) - - m.PushValue(gno.Go2GnoValue( - m.Alloc, - m.Store, - reflect.ValueOf(&r0).Elem(), - )) - }, - }, - { - "strconv", - "FormatInt", - []gno.FieldTypeExpr{ - {Name: gno.N("p0"), Type: gno.X("int64")}, - {Name: gno.N("p1"), Type: gno.X("int")}, - }, - []gno.FieldTypeExpr{ - {Name: gno.N("r0"), Type: gno.X("string")}, - }, - false, - func(m *gno.Machine) { - b := m.LastBlock() - var ( - p0 int64 - rp0 = reflect.ValueOf(&p0).Elem() - p1 int + p1 bool rp1 = reflect.ValueOf(&p1).Elem() ) gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 0, "")).TV, rp0) gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 1, "")).TV, rp1) - r0 := libs_strconv.FormatInt(p0, p1) - - m.PushValue(gno.Go2GnoValue( - m.Alloc, - m.Store, - reflect.ValueOf(&r0).Elem(), - )) + libs_std.X_setParamBool( + m, + p0, p1) }, }, { - "strconv", - "FormatUint", - []gno.FieldTypeExpr{ - {Name: gno.N("p0"), Type: gno.X("uint64")}, - {Name: gno.N("p1"), Type: gno.X("int")}, - }, + "std", + "setParamInt64", []gno.FieldTypeExpr{ - {Name: gno.N("r0"), Type: gno.X("string")}, + {Name: gno.N("p0"), Type: gno.X("string")}, + {Name: gno.N("p1"), Type: gno.X("int64")}, }, - false, + []gno.FieldTypeExpr{}, + true, func(m *gno.Machine) { b := m.LastBlock() var ( - p0 uint64 + p0 string rp0 = reflect.ValueOf(&p0).Elem() - p1 int + p1 int64 rp1 = reflect.ValueOf(&p1).Elem() ) gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 0, "")).TV, rp0) gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 1, "")).TV, rp1) - r0 := libs_strconv.FormatUint(p0, p1) - - m.PushValue(gno.Go2GnoValue( - m.Alloc, - m.Store, - reflect.ValueOf(&r0).Elem(), - )) + libs_std.X_setParamInt64( + m, + p0, p1) }, }, { - "strconv", - "Quote", + "std", + "setParamUint64", []gno.FieldTypeExpr{ {Name: gno.N("p0"), Type: gno.X("string")}, + {Name: gno.N("p1"), Type: gno.X("uint64")}, }, - []gno.FieldTypeExpr{ - {Name: gno.N("r0"), Type: gno.X("string")}, - }, - false, + []gno.FieldTypeExpr{}, + true, func(m *gno.Machine) { b := m.LastBlock() var ( p0 string rp0 = reflect.ValueOf(&p0).Elem() + p1 uint64 + rp1 = reflect.ValueOf(&p1).Elem() ) gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 0, "")).TV, rp0) + gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 1, "")).TV, rp1) - r0 := libs_strconv.Quote(p0) - - m.PushValue(gno.Go2GnoValue( - m.Alloc, - m.Store, - reflect.ValueOf(&r0).Elem(), - )) + libs_std.X_setParamUint64( + m, + p0, p1) }, }, { - "strconv", - "QuoteToASCII", + "std", + "setParamBytes", []gno.FieldTypeExpr{ {Name: gno.N("p0"), Type: gno.X("string")}, + {Name: gno.N("p1"), Type: gno.X("[]byte")}, }, - []gno.FieldTypeExpr{ - {Name: gno.N("r0"), Type: gno.X("string")}, - }, - false, + []gno.FieldTypeExpr{}, + true, func(m *gno.Machine) { b := m.LastBlock() var ( p0 string rp0 = reflect.ValueOf(&p0).Elem() + p1 []byte + rp1 = reflect.ValueOf(&p1).Elem() ) gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 0, "")).TV, rp0) + gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 1, "")).TV, rp1) - r0 := libs_strconv.QuoteToASCII(p0) - - m.PushValue(gno.Go2GnoValue( - m.Alloc, - m.Store, - reflect.ValueOf(&r0).Elem(), - )) + libs_std.X_setParamBytes( + m, + p0, p1) }, }, { diff --git a/gnovm/stdlibs/io/export_test.gno b/gnovm/stdlibs/io/export_test.gno deleted file mode 100644 index 6204ffc4591..00000000000 --- a/gnovm/stdlibs/io/export_test.gno +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package io - -// exported for test -var ( - ErrInvalidWrite = errInvalidWrite - ErrWhence = errWhence - ErrOffset = errOffset -) diff --git a/gnovm/stdlibs/io/io_test.gno b/gnovm/stdlibs/io/io_test.gno index a7533a87799..4915982057b 100644 --- a/gnovm/stdlibs/io/io_test.gno +++ b/gnovm/stdlibs/io/io_test.gno @@ -1,4 +1,4 @@ -package io_test +package io // Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style @@ -8,7 +8,6 @@ import ( "bytes" "errors" "fmt" - "io" "strings" "testing" ) @@ -16,8 +15,8 @@ import ( // A version of bytes.Buffer without ReadFrom and WriteTo type Buffer struct { bytes.Buffer - io.ReaderFrom // conflicts with and hides bytes.Buffer's ReaderFrom. - io.WriterTo // conflicts with and hides bytes.Buffer's WriterTo. + ReaderFrom // conflicts with and hides bytes.Buffer's ReaderFrom. + WriterTo // conflicts with and hides bytes.Buffer's WriterTo. } // Simple tests, primarily to verify the ReadFrom and WriteTo callouts inside Copy, CopyBuffer and CopyN. @@ -26,7 +25,7 @@ func TestCopy(t *testing.T) { rb := new(Buffer) wb := new(Buffer) rb.WriteString("hello, world.") - io.Copy(wb, rb) + Copy(wb, rb) if wb.String() != "hello, world." { t.Errorf("Copy did not work properly") } @@ -36,12 +35,12 @@ func TestCopyNegative(t *testing.T) { rb := new(Buffer) wb := new(Buffer) rb.WriteString("hello") - io.Copy(wb, &io.LimitedReader{R: rb, N: -1}) + Copy(wb, &LimitedReader{R: rb, N: -1}) if wb.String() != "" { t.Errorf("Copy on LimitedReader with N<0 copied data") } - io.CopyN(wb, rb, -1) + CopyN(wb, rb, -1) if wb.String() != "" { t.Errorf("CopyN with N<0 copied data") } @@ -51,7 +50,7 @@ func TestCopyBuffer(t *testing.T) { rb := new(Buffer) wb := new(Buffer) rb.WriteString("hello, world.") - io.CopyBuffer(wb, rb, make([]byte, 1)) // Tiny buffer to keep it honest. + CopyBuffer(wb, rb, make([]byte, 1)) // Tiny buffer to keep it honest. if wb.String() != "hello, world." { t.Errorf("CopyBuffer did not work properly") } @@ -61,7 +60,7 @@ func TestCopyBufferNil(t *testing.T) { rb := new(Buffer) wb := new(Buffer) rb.WriteString("hello, world.") - io.CopyBuffer(wb, rb, nil) // Should allocate a buffer. + CopyBuffer(wb, rb, nil) // Should allocate a buffer. if wb.String() != "hello, world." { t.Errorf("CopyBuffer did not work properly") } @@ -71,7 +70,7 @@ func TestCopyReadFrom(t *testing.T) { rb := new(Buffer) wb := new(bytes.Buffer) // implements ReadFrom. rb.WriteString("hello, world.") - io.Copy(wb, rb) + Copy(wb, rb) if wb.String() != "hello, world." { t.Errorf("Copy did not work properly") } @@ -81,7 +80,7 @@ func TestCopyWriteTo(t *testing.T) { rb := new(bytes.Buffer) // implements WriteTo. wb := new(Buffer) rb.WriteString("hello, world.") - io.Copy(wb, rb) + Copy(wb, rb) if wb.String() != "hello, world." { t.Errorf("Copy did not work properly") } @@ -93,7 +92,7 @@ type writeToChecker struct { writeToCalled bool } -func (wt *writeToChecker) WriteTo(w io.Writer) (int64, error) { +func (wt *writeToChecker) WriteTo(w Writer) (int64, error) { wt.writeToCalled = true return wt.Buffer.WriteTo(w) } @@ -105,7 +104,7 @@ func TestCopyPriority(t *testing.T) { rb := new(writeToChecker) wb := new(bytes.Buffer) rb.WriteString("hello, world.") - io.Copy(wb, rb) + Copy(wb, rb) if wb.String() != "hello, world." { t.Errorf("Copy did not work properly") } else if !rb.writeToCalled { @@ -135,7 +134,7 @@ func (w errWriter) Write([]byte) (int, error) { func TestCopyReadErrWriteErr(t *testing.T) { er, ew := errors.New("readError"), errors.New("writeError") r, w := zeroErrReader{err: er}, errWriter{err: ew} - n, err := io.Copy(w, r) + n, err := Copy(w, r) if n != 0 || err != ew { t.Errorf("Copy(zeroErrReader, errWriter) = %d, %v; want 0, writeError", n, err) } @@ -145,7 +144,7 @@ func TestCopyN(t *testing.T) { rb := new(Buffer) wb := new(Buffer) rb.WriteString("hello, world.") - io.CopyN(wb, rb, 5) + CopyN(wb, rb, 5) if wb.String() != "hello" { t.Errorf("CopyN did not work properly") } @@ -155,7 +154,7 @@ func TestCopyNReadFrom(t *testing.T) { rb := new(Buffer) wb := new(bytes.Buffer) // implements ReadFrom. rb.WriteString("hello") - io.CopyN(wb, rb, 5) + CopyN(wb, rb, 5) if wb.String() != "hello" { t.Errorf("CopyN did not work properly") } @@ -165,7 +164,7 @@ func TestCopyNWriteTo(t *testing.T) { rb := new(bytes.Buffer) // implements WriteTo. wb := new(Buffer) rb.WriteString("hello, world.") - io.CopyN(wb, rb, 5) + CopyN(wb, rb, 5) if wb.String() != "hello" { t.Errorf("CopyN did not work properly") } @@ -178,7 +177,7 @@ func BenchmarkCopyNSmall(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { - io.CopyN(buf, rd, 512) + CopyN(buf, rd, 512) rd.Reset(bs) } } @@ -190,13 +189,13 @@ func BenchmarkCopyNLarge(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { - io.CopyN(buf, rd, 32*1024) + CopyN(buf, rd, 32*1024) rd.Reset(bs) } } type noReadFrom struct { - w io.Writer + w Writer } func (w *noReadFrom) Write(p []byte) (n int, err error) { @@ -215,32 +214,32 @@ func TestCopyNEOF(t *testing.T) { b := new(bytes.Buffer) - n, err := io.CopyN(&noReadFrom{b}, strings.NewReader("foo"), 3) + n, err := CopyN(&noReadFrom{b}, strings.NewReader("foo"), 3) if n != 3 || err != nil { t.Errorf("CopyN(noReadFrom, foo, 3) = %d, %v; want 3, nil", n, err) } - n, err = io.CopyN(&noReadFrom{b}, strings.NewReader("foo"), 4) - if n != 3 || err != io.EOF { + n, err = CopyN(&noReadFrom{b}, strings.NewReader("foo"), 4) + if n != 3 || err != EOF { t.Errorf("CopyN(noReadFrom, foo, 4) = %d, %v; want 3, EOF", n, err) } - n, err = io.CopyN(b, strings.NewReader("foo"), 3) // b has read from + n, err = CopyN(b, strings.NewReader("foo"), 3) // b has read from if n != 3 || err != nil { t.Errorf("CopyN(bytes.Buffer, foo, 3) = %d, %v; want 3, nil", n, err) } - n, err = io.CopyN(b, strings.NewReader("foo"), 4) // b has read from - if n != 3 || err != io.EOF { + n, err = CopyN(b, strings.NewReader("foo"), 4) // b has read from + if n != 3 || err != EOF { t.Errorf("CopyN(bytes.Buffer, foo, 4) = %d, %v; want 3, EOF", n, err) } - n, err = io.CopyN(b, wantedAndErrReader{}, 5) + n, err = CopyN(b, wantedAndErrReader{}, 5) if n != 5 || err != nil { t.Errorf("CopyN(bytes.Buffer, wantedAndErrReader, 5) = %d, %v; want 5, nil", n, err) } - n, err = io.CopyN(&noReadFrom{b}, wantedAndErrReader{}, 5) + n, err = CopyN(&noReadFrom{b}, wantedAndErrReader{}, 5) if n != 5 || err != nil { t.Errorf("CopyN(noReadFrom, wantedAndErrReader, 5) = %d, %v; want 5, nil", n, err) } @@ -268,7 +267,7 @@ func (r *dataAndErrorBuffer) Read(p []byte) (n int, err error) { func TestReadAtLeastWithDataAndEOF(t *testing.T) { var rb dataAndErrorBuffer - rb.err = io.EOF + rb.err = EOF testReadAtLeast(t, &rb) } @@ -278,41 +277,41 @@ func TestReadAtLeastWithDataAndError(t *testing.T) { testReadAtLeast(t, &rb) } -func testReadAtLeast(t *testing.T, rb io.ReadWriter) { +func testReadAtLeast(t *testing.T, rb ReadWriter) { rb.Write([]byte("0123")) buf := make([]byte, 2) - n, err := io.ReadAtLeast(rb, buf, 2) + n, err := ReadAtLeast(rb, buf, 2) if err != nil { t.Error(err) } if n != 2 { t.Errorf("expected to have read 2 bytes, got %v", n) } - n, err = io.ReadAtLeast(rb, buf, 4) - if err != io.ErrShortBuffer { - t.Errorf("expected ErrShortBuffer got %v", err) + n, err = ReadAtLeast(rb, buf, 4) + if err != ErrShortBuffer { + t.Errorf("expected `ErrShortBuffer` got %v", err) } if n != 0 { t.Errorf("expected to have read 0 bytes, got %v", n) } - n, err = io.ReadAtLeast(rb, buf, 1) + n, err = ReadAtLeast(rb, buf, 1) if err != nil { t.Error(err) } if n != 2 { t.Errorf("expected to have read 2 bytes, got %v", n) } - n, err = io.ReadAtLeast(rb, buf, 2) - if err != io.EOF { + n, err = ReadAtLeast(rb, buf, 2) + if err != EOF { t.Errorf("expected EOF, got %v", err) } if n != 0 { t.Errorf("expected to have read 0 bytes, got %v", n) } rb.Write([]byte("4")) - n, err = io.ReadAtLeast(rb, buf, 2) - want := io.ErrUnexpectedEOF - if rb, ok := rb.(*dataAndErrorBuffer); ok && rb.err != io.EOF { + n, err = ReadAtLeast(rb, buf, 2) + want := ErrUnexpectedEOF + if rb, ok := rb.(*dataAndErrorBuffer); ok && rb.err != EOF { want = rb.err } if err != want { @@ -323,14 +322,14 @@ func testReadAtLeast(t *testing.T, rb io.ReadWriter) { } } -/* XXX no io.Pipe() no chan +/* XXX no Pipe() no chan func TestTeeReader(t *testing.T) { src := []byte("hello, world") dst := make([]byte, len(src)) rb := bytes.NewBuffer(src) wb := new(bytes.Buffer) - r := io.TeeReader(rb, wb) - if n, err := io.ReadFull(r, dst); err != nil || n != len(src) { + r := TeeReader(rb, wb) + if n, err := ReadFull(r, dst); err != nil || n != len(src) { t.Fatalf("ReadFull(r, dst) = %d, %v; want %d, nil", n, err, len(src)) } if !bytes.Equal(dst, src) { @@ -339,14 +338,14 @@ func TestTeeReader(t *testing.T) { if !bytes.Equal(wb.Bytes(), src) { t.Errorf("bytes written = %q want %q", wb.Bytes(), src) } - if n, err := r.Read(dst); n != 0 || err != io.EOF { + if n, err := r.Read(dst); n != 0 || err != EOF { t.Errorf("r.Read at EOF = %d, %v want 0, EOF", n, err) } rb = bytes.NewBuffer(src) - pr, pw := io.Pipe() + pr, pw := Pipe() pr.Close() - r = io.TeeReader(rb, pw) - if n, err := io.ReadFull(r, dst); n != 0 || err != io.ErrClosedPipe { + r = TeeReader(rb, pw) + if n, err := ReadFull(r, dst); n != 0 || err != ErrClosedPipe { t.Errorf("closed tee: ReadFull(r, dst) = %d, %v; want 0, EPIPE", n, err) } } @@ -363,22 +362,22 @@ func TestSectionReader_ReadAt(t *testing.T) { exp string err error }{ - {data: "", off: 0, n: 10, bufLen: 2, at: 0, exp: "", err: io.EOF}, + {data: "", off: 0, n: 10, bufLen: 2, at: 0, exp: "", err: EOF}, {data: dat, off: 0, n: len(dat), bufLen: 0, at: 0, exp: "", err: nil}, - {data: dat, off: len(dat), n: 1, bufLen: 1, at: 0, exp: "", err: io.EOF}, + {data: dat, off: len(dat), n: 1, bufLen: 1, at: 0, exp: "", err: EOF}, {data: dat, off: 0, n: len(dat) + 2, bufLen: len(dat), at: 0, exp: dat, err: nil}, {data: dat, off: 0, n: len(dat), bufLen: len(dat) / 2, at: 0, exp: dat[:len(dat)/2], err: nil}, {data: dat, off: 0, n: len(dat), bufLen: len(dat), at: 0, exp: dat, err: nil}, {data: dat, off: 0, n: len(dat), bufLen: len(dat) / 2, at: 2, exp: dat[2 : 2+len(dat)/2], err: nil}, {data: dat, off: 3, n: len(dat), bufLen: len(dat) / 2, at: 2, exp: dat[5 : 5+len(dat)/2], err: nil}, {data: dat, off: 3, n: len(dat) / 2, bufLen: len(dat)/2 - 2, at: 2, exp: dat[5 : 5+len(dat)/2-2], err: nil}, - {data: dat, off: 3, n: len(dat) / 2, bufLen: len(dat)/2 + 2, at: 2, exp: dat[5 : 5+len(dat)/2-2], err: io.EOF}, - {data: dat, off: 0, n: 0, bufLen: 0, at: -1, exp: "", err: io.EOF}, - {data: dat, off: 0, n: 0, bufLen: 0, at: 1, exp: "", err: io.EOF}, + {data: dat, off: 3, n: len(dat) / 2, bufLen: len(dat)/2 + 2, at: 2, exp: dat[5 : 5+len(dat)/2-2], err: EOF}, + {data: dat, off: 0, n: 0, bufLen: 0, at: -1, exp: "", err: EOF}, + {data: dat, off: 0, n: 0, bufLen: 0, at: 1, exp: "", err: EOF}, } for i, tt := range tests { r := strings.NewReader(tt.data) - s := io.NewSectionReader(r, int64(tt.off), int64(tt.n)) + s := NewSectionReader(r, int64(tt.off), int64(tt.n)) buf := make([]byte, tt.bufLen) if n, err := s.ReadAt(buf, int64(tt.at)); n != len(tt.exp) || string(buf[:n]) != tt.exp || err != tt.err { t.Fatalf("%d: ReadAt(%d) = %q, %v; expected %q, %v", i, tt.at, buf[:n], err, tt.exp, tt.err) @@ -389,9 +388,9 @@ func TestSectionReader_ReadAt(t *testing.T) { func TestSectionReader_Seek(t *testing.T) { // Verifies that NewSectionReader's Seeker behaves like bytes.NewReader (which is like strings.NewReader) br := bytes.NewReader([]byte("foo")) - sr := io.NewSectionReader(br, 0, int64(len("foo"))) + sr := NewSectionReader(br, 0, int64(len("foo"))) - for _, whence := range []int{io.SeekStart, io.SeekCurrent, io.SeekEnd} { + for _, whence := range []int{SeekStart, SeekCurrent, SeekEnd} { for offset := int64(-3); offset <= 4; offset++ { brOff, brErr := br.Seek(offset, whence) srOff, srErr := sr.Seek(offset, whence) @@ -403,13 +402,13 @@ func TestSectionReader_Seek(t *testing.T) { } // And verify we can just seek past the end and get an EOF - got, err := sr.Seek(100, io.SeekStart) + got, err := sr.Seek(100, SeekStart) if err != nil || got != 100 { t.Errorf("Seek = %v, %v; want 100, nil", got, err) } n, err := sr.Read(make([]byte, 10)) - if n != 0 || err != io.EOF { + if n != 0 || err != EOF { t.Errorf("Read = %v, %v; want 0, EOF", n, err) } } @@ -425,7 +424,7 @@ func TestSectionReader_Size(t *testing.T) { for _, tt := range tests { r := strings.NewReader(tt.data) - sr := io.NewSectionReader(r, 0, int64(len(tt.data))) + sr := NewSectionReader(r, 0, int64(len(tt.data))) if got := sr.Size(); got != tt.want { t.Errorf("Size = %v; want %v", got, tt.want) } @@ -443,11 +442,11 @@ func (w largeWriter) Write(p []byte) (int, error) { } func TestCopyLargeWriter(t *testing.T) { - want := io.ErrInvalidWrite + want := errInvalidWrite rb := new(Buffer) wb := largeWriter{} rb.WriteString("hello, world.") - if _, err := io.Copy(wb, rb); err != want { + if _, err := Copy(wb, rb); err != want { t.Errorf("Copy error: got %v, want %v", err, want) } @@ -455,7 +454,7 @@ func TestCopyLargeWriter(t *testing.T) { rb = new(Buffer) wb = largeWriter{err: want} rb.WriteString("hello, world.") - if _, err := io.Copy(wb, rb); err != want { + if _, err := Copy(wb, rb); err != want { t.Errorf("Copy error: got %v, want %v", err, want) } } @@ -463,18 +462,18 @@ func TestCopyLargeWriter(t *testing.T) { func TestNopCloserWriterToForwarding(t *testing.T) { for _, tc := range [...]struct { Name string - r io.Reader + r Reader }{ - {"not a WriterTo", io.Reader(nil)}, + {"not a WriterTo", Reader(nil)}, {"a WriterTo", struct { - io.Reader - io.WriterTo + Reader + WriterTo }{}}, } { - nc := io.NopCloser(tc.r) + nc := NopCloser(tc.r) - _, expected := tc.r.(io.WriterTo) - _, got := nc.(io.WriterTo) + _, expected := tc.r.(WriterTo) + _, got := nc.(WriterTo) if expected != got { t.Errorf("NopCloser incorrectly forwards WriterTo for %s, got %t want %t", tc.Name, got, expected) } @@ -496,9 +495,9 @@ func TestNopCloserWriterToForwarding(t *testing.T) { // for _, whence := range []int{-3, -2, -1, 3, 4, 5} { // var offset int64 = 0 // gotOff, gotErr := w.Seek(offset, whence) -// if gotOff != 0 || gotErr != ErrWhence { +// if gotOff != 0 || gotErr != errWhence { // t.Errorf("For whence %d, offset %d, OffsetWriter.Seek got: (%d, %v), want: (%d, %v)", -// whence, offset, gotOff, gotErr, 0, ErrWhence) +// whence, offset, gotOff, gotErr, 0, errWhence) // } // } // }) @@ -508,7 +507,7 @@ func TestNopCloserWriterToForwarding(t *testing.T) { // for _, whence := range []int{SeekStart, SeekCurrent} { // for offset := int64(-3); offset < 0; offset++ { // gotOff, gotErr := w.Seek(offset, whence) -// if gotOff != 0 || gotErr != ErrOffset { +// if gotOff != 0 || gotErr != errOffset { // t.Errorf("For whence %d, offset %d, OffsetWriter.Seek got: (%d, %v), want: (%d, %v)", // whence, offset, gotOff, gotErr, 0, ErrOffset) // } @@ -540,3 +539,70 @@ func TestNopCloserWriterToForwarding(t *testing.T) { // } // }) // } + +// TODO: The original test uses `os.CreateTemp`, but here +// to work around it by using `bytes.Buffer`. +// When `os.CreateTemp` is available in the future, we should change the test +// to use the original approach instead of this method. (just un-comment the test above) +func TestOffsetWriter_Seek(t *testing.T) { + buf := new(bytes.Buffer) + w := NewOffsetWriter(testWriterAt{buf}, 0) + + // Should throw error errWhence if whence is not valid + t.Run("errWhence", func(t *testing.T) { + for _, whence := range []int{-3, -2, -1, 3, 4, 5} { + var offset int64 = 0 + gotOff, gotErr := w.Seek(offset, whence) + if gotOff != 0 || gotErr != errWhence { + t.Errorf("For whence %d, offset %d, OffsetWriter.Seek got: (%d, %v), want: (%d, %v)", + whence, offset, gotOff, gotErr, 0, errWhence) + } + } + }) + + // Should throw error errOffset if offset is negative + t.Run("errOffset", func(t *testing.T) { + for _, whence := range []int{SeekStart, SeekCurrent} { + for offset := int64(-3); offset < 0; offset++ { + gotOff, gotErr := w.Seek(offset, whence) + if gotOff != 0 || gotErr != errOffset { + t.Errorf("For whence %d, offset %d, OffsetWriter.Seek got: (%d, %v), want: (%d, %v)", + whence, offset, gotOff, gotErr, 0, errOffset) + } + } + } + }) + + t.Run("normal", func(t *testing.T) { + tests := []struct { + offset int64 + whence int + returnOff int64 + }{ + {whence: SeekStart, offset: 1, returnOff: 1}, + {whence: SeekStart, offset: 2, returnOff: 2}, + {whence: SeekStart, offset: 3, returnOff: 3}, + {whence: SeekCurrent, offset: 1, returnOff: 4}, + {whence: SeekCurrent, offset: 2, returnOff: 6}, + {whence: SeekCurrent, offset: 3, returnOff: 9}, + } + for idx, tt := range tests { + gotOff, gotErr := w.Seek(tt.offset, tt.whence) + if gotOff != tt.returnOff || gotErr != nil { + t.Errorf("%d:: For whence %d, offset %d, OffsetWriter.Seek got: (%d, %v), want: (%d, )", + idx+1, tt.whence, tt.offset, gotOff, gotErr, tt.returnOff) + } + } + }) +} + +type testWriterAt struct { + buf *bytes.Buffer +} + +func (w testWriterAt) WriteAt(p []byte, off int64) (n int, err error) { + if int64(w.buf.Len()) < off+int64(len(p)) { + w.buf.Grow(int(off + int64(len(p)) - int64(w.buf.Len()))) + } + return copy(w.buf.Bytes()[off:], p), nil +} diff --git a/gnovm/stdlibs/io/multi_test.gno b/gnovm/stdlibs/io/multi_test.gno index 31345279318..8932ace2e59 100644 --- a/gnovm/stdlibs/io/multi_test.gno +++ b/gnovm/stdlibs/io/multi_test.gno @@ -1,4 +1,4 @@ -package io_test +package io // Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style @@ -8,7 +8,6 @@ import ( "bytes" "crypto/sha1" "fmt" - "io" "strings" "testing" ) @@ -18,14 +17,14 @@ type Stringer interface { } func TestMultiReader(t *testing.T) { - var mr io.Reader + var mr Reader var buf []byte nread := 0 withFooBar := func(tests func()) { r1 := strings.NewReader("foo ") r2 := strings.NewReader("") r3 := strings.NewReader("bar") - mr = io.MultiReader(r1, r2, r3) + mr = MultiReader(r1, r2, r3) buf = make([]byte, 20) tests() } @@ -51,13 +50,13 @@ func TestMultiReader(t *testing.T) { expectRead(2, "fo", nil) expectRead(5, "o ", nil) expectRead(5, "bar", nil) - expectRead(5, "", io.EOF) + expectRead(5, "", EOF) }) withFooBar(func() { expectRead(4, "foo ", nil) expectRead(1, "b", nil) expectRead(3, "ar", nil) - expectRead(1, "", io.EOF) + expectRead(1, "", EOF) }) withFooBar(func() { expectRead(5, "foo ", nil) @@ -68,7 +67,7 @@ func TestMultiWriter(t *testing.T) { sink := new(bytes.Buffer) // Hide bytes.Buffer's WriteString method: testMultiWriter(t, struct { - io.Writer + Writer Stringer }{sink, sink}) } @@ -83,11 +82,11 @@ func TestMultiWriter_String(t *testing.T) { func TestMultiWriter_WriteStringSingleAlloc(t *testing.T) { var sink1, sink2 bytes.Buffer type simpleWriter struct { // hide bytes.Buffer's WriteString - io.Writer + Writer } - mw := io.MultiWriter(simpleWriter{&sink1}, simpleWriter{&sink2}) + mw := MultiWriter(simpleWriter{&sink1}, simpleWriter{&sink2}) allocs := int(testing.AllocsPerRun2(1000, func() { - io.WriteString(mw, "foo") + WriteString(mw, "foo") })) if allocs != 1 { t.Errorf("num allocations = %d; want 1", allocs) @@ -108,24 +107,24 @@ func (c *writeStringChecker) Write(p []byte) (n int, err error) { func TestMultiWriter_StringCheckCall(t *testing.T) { var c writeStringChecker - mw := io.MultiWriter(&c) - io.WriteString(mw, "foo") + mw := MultiWriter(&c) + WriteString(mw, "foo") if !c.called { t.Error("did not see WriteString call to writeStringChecker") } } func testMultiWriter(t *testing.T, sink interface { - io.Writer + Writer Stringer }, ) { sha1 := sha1.New() - mw := io.MultiWriter(sha1, sink) + mw := MultiWriter(sha1, sink) sourceString := "My input text." source := strings.NewReader(sourceString) - written, err := io.Copy(mw, source) + written, err := Copy(mw, source) if written != int64(len(sourceString)) { t.Errorf("short write of %d, not %d", written, len(sourceString)) @@ -183,25 +182,25 @@ func TestMultiWriterSingleChainFlatten(t *testing.T) { func TestMultiWriterError(t *testing.T) { f1 := writerFunc(func(p []byte) (int, error) { - return len(p) / 2, io.ErrShortWrite + return len(p) / 2, ErrShortWrite }) f2 := writerFunc(func(p []byte) (int, error) { t.Errorf("MultiWriter called f2.Write") return len(p), nil }) - w := io.MultiWriter(f1, f2) + w := MultiWriter(f1, f2) n, err := w.Write(make([]byte, 100)) - if n != 50 || err != io.ErrShortWrite { + if n != 50 || err != ErrShortWrite { t.Errorf("Write = %d, %v, want 50, ErrShortWrite", n, err) } } // Test that MultiReader copies the input slice and is insulated from future modification. func TestMultiReaderCopy(t *testing.T) { - slice := []io.Reader{strings.NewReader("hello world")} - r := io.MultiReader(slice...) + slice := []Reader{strings.NewReader("hello world")} + r := MultiReader(slice...) slice[0] = nil - data, err := io.ReadAll(r) + data, err := ReadAll(r) if err != nil || string(data) != "hello world" { t.Errorf("ReadAll() = %q, %v, want %q, nil", data, err, "hello world") } @@ -210,8 +209,8 @@ func TestMultiReaderCopy(t *testing.T) { // Test that MultiWriter copies the input slice and is insulated from future modification. func TestMultiWriterCopy(t *testing.T) { var buf bytes.Buffer - slice := []io.Writer{&buf} - w := io.MultiWriter(slice...) + slice := []Writer{&buf} + w := MultiWriter(slice...) slice[0] = nil n, err := w.Write([]byte("hello world")) if err != nil || n != 11 { @@ -278,12 +277,12 @@ func (b byteAndEOFReader) Read(p []byte) (n int, err error) { panic("unexpected call") } p[0] = byte(b) - return 1, io.EOF + return 1, EOF } // This used to yield bytes forever; issue 16795. func TestMultiReaderSingleByteWithEOF(t *testing.T) { - got, err := io.ReadAll(io.LimitReader(io.MultiReader(byteAndEOFReader('a'), byteAndEOFReader('b')), 10)) + got, err := ReadAll(LimitReader(MultiReader(byteAndEOFReader('a'), byteAndEOFReader('b')), 10)) if err != nil { t.Fatal(err) } @@ -297,10 +296,10 @@ func TestMultiReaderSingleByteWithEOF(t *testing.T) { // chain continues to return EOF on its final read, rather than // yielding a (0, EOF). func TestMultiReaderFinalEOF(t *testing.T) { - r := io.MultiReader(bytes.NewReader(nil), byteAndEOFReader('a')) + r := MultiReader(bytes.NewReader(nil), byteAndEOFReader('a')) buf := make([]byte, 2) n, err := r.Read(buf) - if n != 1 || err != io.EOF { + if n != 1 || err != EOF { t.Errorf("got %v, %v; want 1, EOF", n, err) } } @@ -343,21 +342,21 @@ func TestInterleavedMultiReader(t *testing.T) { r1 := strings.NewReader("123") r2 := strings.NewReader("45678") - mr1 := io.MultiReader(r1, r2) - mr2 := io.MultiReader(mr1) + mr1 := MultiReader(r1, r2) + mr2 := MultiReader(mr1) buf := make([]byte, 4) // Have mr2 use mr1's []Readers. // Consume r1 (and clear it for GC to handle) and consume part of r2. - n, err := io.ReadFull(mr2, buf) + n, err := ReadFull(mr2, buf) if got := string(buf[:n]); got != "1234" || err != nil { t.Errorf(`ReadFull(mr2) = (%q, %v), want ("1234", nil)`, got, err) } // Consume the rest of r2 via mr1. // This should not panic even though mr2 cleared r1. - n, err = io.ReadFull(mr1, buf) + n, err = ReadFull(mr1, buf) if got := string(buf[:n]); got != "5678" || err != nil { t.Errorf(`ReadFull(mr1) = (%q, %v), want ("5678", nil)`, got, err) } diff --git a/gnovm/stdlibs/std/banker.gno b/gnovm/stdlibs/std/banker.gno index 2b94292bd7e..5412b73281c 100644 --- a/gnovm/stdlibs/std/banker.gno +++ b/gnovm/stdlibs/std/banker.gno @@ -65,6 +65,7 @@ func (b BankerType) String() string { // GetBanker returns a new Banker, with its capabilities matching the given // [BankerType]. func GetBanker(bt BankerType) Banker { + assertCallerIsRealm() if bt >= maxBanker { panic("invalid banker type") } diff --git a/gnovm/stdlibs/std/context.go b/gnovm/stdlibs/std/context.go index ff5c91a14eb..a0dafe5dc44 100644 --- a/gnovm/stdlibs/std/context.go +++ b/gnovm/stdlibs/std/context.go @@ -18,6 +18,7 @@ type ExecContext struct { OrigSend std.Coins OrigSendSpent *std.Coins // mutable Banker BankerInterface + Params ParamsInterface EventLogger *sdk.EventLogger } diff --git a/gnovm/stdlibs/std/native.gno b/gnovm/stdlibs/std/native.gno index 22a16fc18d1..5421e231de2 100644 --- a/gnovm/stdlibs/std/native.gno +++ b/gnovm/stdlibs/std/native.gno @@ -65,3 +65,4 @@ func getRealm(height int) (address string, pkgPath string) func derivePkgAddr(pkgPath string) string func encodeBech32(prefix string, bz [20]byte) string func decodeBech32(addr string) (prefix string, bz [20]byte, ok bool) +func assertCallerIsRealm() diff --git a/gnovm/stdlibs/std/native.go b/gnovm/stdlibs/std/native.go index f185a52f249..3fe5fbb9889 100644 --- a/gnovm/stdlibs/std/native.go +++ b/gnovm/stdlibs/std/native.go @@ -158,6 +158,13 @@ func X_decodeBech32(addr string) (prefix string, bytes [20]byte, ok bool) { return prefix, [20]byte(bz), true } +func X_assertCallerIsRealm(m *gno.Machine) { + frame := m.Frames[m.NumFrames()-2] + if path := frame.LastPackage.PkgPath; !gno.IsRealmPath(path) { + m.Panic(typedString("caller is not a realm")) + } +} + func typedString(s string) gno.TypedValue { tv := gno.TypedValue{T: gno.StringType} tv.SetString(gno.StringValue(s)) diff --git a/gnovm/stdlibs/std/params.gno b/gnovm/stdlibs/std/params.gno new file mode 100644 index 00000000000..ce400270cda --- /dev/null +++ b/gnovm/stdlibs/std/params.gno @@ -0,0 +1,13 @@ +package std + +func setParamString(key string, val string) +func setParamBool(key string, val bool) +func setParamInt64(key string, val int64) +func setParamUint64(key string, val uint64) +func setParamBytes(key string, val []byte) + +func SetParamString(key string, val string) { setParamString(key, val) } +func SetParamBool(key string, val bool) { setParamBool(key, val) } +func SetParamInt64(key string, val int64) { setParamInt64(key, val) } +func SetParamUint64(key string, val uint64) { setParamUint64(key, val) } +func SetParamBytes(key string, val []byte) { setParamBytes(key, val) } diff --git a/gnovm/stdlibs/std/params.go b/gnovm/stdlibs/std/params.go new file mode 100644 index 00000000000..e21bd9912dd --- /dev/null +++ b/gnovm/stdlibs/std/params.go @@ -0,0 +1,72 @@ +package std + +import ( + "fmt" + "strings" + "unicode" + + gno "github.com/gnolang/gno/gnovm/pkg/gnolang" +) + +// ParamsInterface is the interface through which Gno is capable of accessing +// the blockchain's params. +// +// The name is what it is to avoid a collision with Gno's Params, when +// transpiling. +type ParamsInterface interface { + SetString(key, val string) + SetBool(key string, val bool) + SetInt64(key string, val int64) + SetUint64(key string, val uint64) + SetBytes(key string, val []byte) +} + +func X_setParamString(m *gno.Machine, key, val string) { + pk := pkey(m, key, "string") + GetContext(m).Params.SetString(pk, val) +} + +func X_setParamBool(m *gno.Machine, key string, val bool) { + pk := pkey(m, key, "bool") + GetContext(m).Params.SetBool(pk, val) +} + +func X_setParamInt64(m *gno.Machine, key string, val int64) { + pk := pkey(m, key, "int64") + GetContext(m).Params.SetInt64(pk, val) +} + +func X_setParamUint64(m *gno.Machine, key string, val uint64) { + pk := pkey(m, key, "uint64") + GetContext(m).Params.SetUint64(pk, val) +} + +func X_setParamBytes(m *gno.Machine, key string, val []byte) { + pk := pkey(m, key, "bytes") + GetContext(m).Params.SetBytes(pk, val) +} + +func pkey(m *gno.Machine, key string, kind string) string { + // validate key. + untypedKey := strings.TrimSuffix(key, "."+kind) + if key == untypedKey { + m.Panic(typedString("invalid param key: " + key)) + } + + if len(key) == 0 { + m.Panic(typedString("empty param key")) + } + first := rune(key[0]) + if !unicode.IsLetter(first) && first != '_' { + m.Panic(typedString("invalid param key: " + key)) + } + for _, char := range untypedKey[1:] { + if !unicode.IsLetter(char) && !unicode.IsDigit(char) && char != '_' { + m.Panic(typedString("invalid param key: " + key)) + } + } + + // decorate key with realm and type. + _, rlmPath := currentRealm(m) + return fmt.Sprintf("%s.%s", rlmPath, key) +} diff --git a/gnovm/stdlibs/strconv/atob.gno b/gnovm/stdlibs/strconv/atob.gno new file mode 100644 index 00000000000..0a495008d77 --- /dev/null +++ b/gnovm/stdlibs/strconv/atob.gno @@ -0,0 +1,35 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package strconv + +// ParseBool returns the boolean value represented by the string. +// It accepts 1, t, T, TRUE, true, True, 0, f, F, FALSE, false, False. +// Any other value returns an error. +func ParseBool(str string) (bool, error) { + switch str { + case "1", "t", "T", "true", "TRUE", "True": + return true, nil + case "0", "f", "F", "false", "FALSE", "False": + return false, nil + } + return false, syntaxError("ParseBool", str) +} + +// FormatBool returns "true" or "false" according to the value of b. +func FormatBool(b bool) string { + if b { + return "true" + } + return "false" +} + +// AppendBool appends "true" or "false", according to the value of b, +// to dst and returns the extended buffer. +func AppendBool(dst []byte, b bool) []byte { + if b { + return append(dst, "true"...) + } + return append(dst, "false"...) +} diff --git a/gnovm/stdlibs/strconv/atob_test.gno b/gnovm/stdlibs/strconv/atob_test.gno new file mode 100644 index 00000000000..39746f8953d --- /dev/null +++ b/gnovm/stdlibs/strconv/atob_test.gno @@ -0,0 +1,90 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package strconv + +import ( + "bytes" + "testing" +) + +type atobTest struct { + in string + out bool + err error +} + +var atobtests = []atobTest{ + {"", false, ErrSyntax}, + {"asdf", false, ErrSyntax}, + {"0", false, nil}, + {"f", false, nil}, + {"F", false, nil}, + {"FALSE", false, nil}, + {"false", false, nil}, + {"False", false, nil}, + {"1", true, nil}, + {"t", true, nil}, + {"T", true, nil}, + {"TRUE", true, nil}, + {"true", true, nil}, + {"True", true, nil}, +} + +func TestParseBool(t *testing.T) { + for _, test := range atobtests { + b, e := ParseBool(test.in) + if test.err != nil { + // expect an error + if e == nil { + t.Errorf("ParseBool(%s) = nil; want %s", test.in, test.err) + } else { + // NumError assertion must succeed; it's the only thing we return. + if e.(*NumError).Err != test.err { + t.Errorf("ParseBool(%s) = %s; want %s", test.in, e, test.err) + } + } + } else { + if e != nil { + t.Errorf("ParseBool(%s) = %s; want nil", test.in, e) + } + if b != test.out { + t.Errorf("ParseBool(%s) = %t; want %t", test.in, b, test.out) + } + } + } +} + +var boolString = map[bool]string{ + true: "true", + false: "false", +} + +func TestFormatBool(t *testing.T) { + for b, s := range boolString { + if f := FormatBool(b); f != s { + t.Errorf("FormatBool(%v) = %q; want %q", b, f, s) + } + } +} + +type appendBoolTest struct { + b bool + in []byte + out []byte +} + +var appendBoolTests = []appendBoolTest{ + {true, []byte("foo "), []byte("foo true")}, + {false, []byte("foo "), []byte("foo false")}, +} + +func TestAppendBool(t *testing.T) { + for _, test := range appendBoolTests { + b := AppendBool(test.in, test.b) + if !bytes.Equal(b, test.out) { + t.Errorf("AppendBool(%q, %v) = %q; want %q", test.in, test.b, b, test.out) + } + } +} diff --git a/gnovm/stdlibs/strconv/atof.gno b/gnovm/stdlibs/strconv/atof.gno new file mode 100644 index 00000000000..8fc90425f69 --- /dev/null +++ b/gnovm/stdlibs/strconv/atof.gno @@ -0,0 +1,709 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package strconv + +// decimal to binary floating point conversion. +// Algorithm: +// 1) Store input in multiprecision decimal. +// 2) Multiply/divide decimal by powers of two until in range [0.5, 1) +// 3) Multiply by 2^precision and round to get mantissa. + +import "math" + +var optimize = true // set to false to force slow-path conversions for testing + +// commonPrefixLenIgnoreCase returns the length of the common +// prefix of s and prefix, with the character case of s ignored. +// The prefix argument must be all lower-case. +func commonPrefixLenIgnoreCase(s, prefix string) int { + n := len(prefix) + if n > len(s) { + n = len(s) + } + for i := 0; i < n; i++ { + c := s[i] + if 'A' <= c && c <= 'Z' { + c += 'a' - 'A' + } + if c != prefix[i] { + return i + } + } + return n +} + +// special returns the floating-point value for the special, +// possibly signed floating-point representations inf, infinity, +// and NaN. The result is ok if a prefix of s contains one +// of these representations and n is the length of that prefix. +// The character case is ignored. +func special(s string) (f float64, n int, ok bool) { + if len(s) == 0 { + return 0, 0, false + } + sign := 1 + nsign := 0 + switch s[0] { + case '+', '-': + if s[0] == '-' { + sign = -1 + } + nsign = 1 + s = s[1:] + fallthrough + case 'i', 'I': + n := commonPrefixLenIgnoreCase(s, "infinity") + // Anything longer than "inf" is ok, but if we + // don't have "infinity", only consume "inf". + if 3 < n && n < 8 { + n = 3 + } + if n == 3 || n == 8 { + return math.Inf(sign), nsign + n, true + } + case 'n', 'N': + if commonPrefixLenIgnoreCase(s, "nan") == 3 { + return math.NaN(), 3, true + } + } + return 0, 0, false +} + +func (b *decimal) set(s string) (ok bool) { + i := 0 + b.neg = false + b.trunc = false + + // optional sign + if i >= len(s) { + return + } + switch { + case s[i] == '+': + i++ + case s[i] == '-': + b.neg = true + i++ + } + + // digits + sawdot := false + sawdigits := false + for ; i < len(s); i++ { + switch { + case s[i] == '_': + // readFloat already checked underscores + continue + case s[i] == '.': + if sawdot { + return + } + sawdot = true + b.dp = b.nd + continue + + case '0' <= s[i] && s[i] <= '9': + sawdigits = true + if s[i] == '0' && b.nd == 0 { // ignore leading zeros + b.dp-- + continue + } + if b.nd < len(b.d) { + b.d[b.nd] = s[i] + b.nd++ + } else if s[i] != '0' { + b.trunc = true + } + continue + } + break + } + if !sawdigits { + return + } + if !sawdot { + b.dp = b.nd + } + + // optional exponent moves decimal point. + // if we read a very large, very long number, + // just be sure to move the decimal point by + // a lot (say, 100000). it doesn't matter if it's + // not the exact number. + if i < len(s) && lower(s[i]) == 'e' { + i++ + if i >= len(s) { + return + } + esign := 1 + if s[i] == '+' { + i++ + } else if s[i] == '-' { + i++ + esign = -1 + } + if i >= len(s) || s[i] < '0' || s[i] > '9' { + return + } + e := 0 + for ; i < len(s) && ('0' <= s[i] && s[i] <= '9' || s[i] == '_'); i++ { + if s[i] == '_' { + // readFloat already checked underscores + continue + } + if e < 10000 { + e = e*10 + int(s[i]) - '0' + } + } + b.dp += e * esign + } + + if i != len(s) { + return + } + + ok = true + return +} + +// readFloat reads a decimal or hexadecimal mantissa and exponent from a float +// string representation in s; the number may be followed by other characters. +// readFloat reports the number of bytes consumed (i), and whether the number +// is valid (ok). +func readFloat(s string) (mantissa uint64, exp int, neg, trunc, hex bool, i int, ok bool) { + underscores := false + + // optional sign + if i >= len(s) { + return + } + switch { + case s[i] == '+': + i++ + case s[i] == '-': + neg = true + i++ + } + + // digits + base := uint64(10) + maxMantDigits := 19 // 10^19 fits in uint64 + expChar := byte('e') + if i+2 < len(s) && s[i] == '0' && lower(s[i+1]) == 'x' { + base = 16 + maxMantDigits = 16 // 16^16 fits in uint64 + i += 2 + expChar = 'p' + hex = true + } + sawdot := false + sawdigits := false + nd := 0 + ndMant := 0 + dp := 0 +loop: + for ; i < len(s); i++ { + switch c := s[i]; true { + case c == '_': + underscores = true + continue + + case c == '.': + if sawdot { + break loop + } + sawdot = true + dp = nd + continue + + case '0' <= c && c <= '9': + sawdigits = true + if c == '0' && nd == 0 { // ignore leading zeros + dp-- + continue + } + nd++ + if ndMant < maxMantDigits { + mantissa *= base + mantissa += uint64(c - '0') + ndMant++ + } else if c != '0' { + trunc = true + } + continue + + case base == 16 && 'a' <= lower(c) && lower(c) <= 'f': + sawdigits = true + nd++ + if ndMant < maxMantDigits { + mantissa *= 16 + mantissa += uint64(lower(c) - 'a' + 10) + ndMant++ + } else { + trunc = true + } + continue + } + break + } + if !sawdigits { + return + } + if !sawdot { + dp = nd + } + + if base == 16 { + dp *= 4 + ndMant *= 4 + } + + // optional exponent moves decimal point. + // if we read a very large, very long number, + // just be sure to move the decimal point by + // a lot (say, 100000). it doesn't matter if it's + // not the exact number. + if i < len(s) && lower(s[i]) == expChar { + i++ + if i >= len(s) { + return + } + esign := 1 + if s[i] == '+' { + i++ + } else if s[i] == '-' { + i++ + esign = -1 + } + if i >= len(s) || s[i] < '0' || s[i] > '9' { + return + } + e := 0 + for ; i < len(s) && ('0' <= s[i] && s[i] <= '9' || s[i] == '_'); i++ { + if s[i] == '_' { + underscores = true + continue + } + if e < 10000 { + e = e*10 + int(s[i]) - '0' + } + } + dp += e * esign + } else if base == 16 { + // Must have exponent. + return + } + + if mantissa != 0 { + exp = dp - ndMant + } + + if underscores && !underscoreOK(s[:i]) { + return + } + + ok = true + return +} + +// decimal power of ten to binary power of two. +var powtab = []int{1, 3, 6, 9, 13, 16, 19, 23, 26} + +func (d *decimal) floatBits(flt *floatInfo) (b uint64, overflow bool) { + var exp int + var mant uint64 + + // Zero is always a special case. + if d.nd == 0 { + mant = 0 + exp = flt.bias + goto out + } + + // Obvious overflow/underflow. + // These bounds are for 64-bit floats. + // Will have to change if we want to support 80-bit floats in the future. + if d.dp > 310 { + goto overflow + } + if d.dp < -330 { + // zero + mant = 0 + exp = flt.bias + goto out + } + + // Scale by powers of two until in range [0.5, 1.0) + exp = 0 + for d.dp > 0 { + var n int + if d.dp >= len(powtab) { + n = 27 + } else { + n = powtab[d.dp] + } + d.Shift(-n) + exp += n + } + for d.dp < 0 || d.dp == 0 && d.d[0] < '5' { + var n int + if -d.dp >= len(powtab) { + n = 27 + } else { + n = powtab[-d.dp] + } + d.Shift(n) + exp -= n + } + + // Our range is [0.5,1) but floating point range is [1,2). + exp-- + + // Minimum representable exponent is flt.bias+1. + // If the exponent is smaller, move it up and + // adjust d accordingly. + if exp < flt.bias+1 { + n := flt.bias + 1 - exp + d.Shift(-n) + exp += n + } + + if exp-flt.bias >= 1<>= 1 + exp++ + if exp-flt.bias >= 1<>float64info.mantbits != 0 { + return + } + f = float64(mantissa) + if neg { + f = -f + } + switch { + case exp == 0: + // an integer. + return f, true + // Exact integers are <= 10^15. + // Exact powers of ten are <= 10^22. + case exp > 0 && exp <= 15+22: // int * 10^k + // If exponent is big but number of digits is not, + // can move a few zeros into the integer part. + if exp > 22 { + f *= float64pow10[exp-22] + exp = 22 + } + if f > 1e15 || f < -1e15 { + // the exponent was really too large. + return + } + return f * float64pow10[exp], true + case exp < 0 && exp >= -22: // int / 10^k + return f / float64pow10[-exp], true + } + return +} + +// If possible to compute mantissa*10^exp to 32-bit float f exactly, +// entirely in floating-point math, do so, avoiding the machinery above. +func atof32exact(mantissa uint64, exp int, neg bool) (f float32, ok bool) { + if mantissa>>float32info.mantbits != 0 { + return + } + f = float32(mantissa) + if neg { + f = -f + } + switch { + case exp == 0: + return f, true + // Exact integers are <= 10^7. + // Exact powers of ten are <= 10^10. + case exp > 0 && exp <= 7+10: // int * 10^k + // If exponent is big but number of digits is not, + // can move a few zeros into the integer part. + if exp > 10 { + f *= float32pow10[exp-10] + exp = 10 + } + if f > 1e7 || f < -1e7 { + // the exponent was really too large. + return + } + return f * float32pow10[exp], true + case exp < 0 && exp >= -10: // int / 10^k + return f / float32pow10[-exp], true + } + return +} + +// atofHex converts the hex floating-point string s +// to a rounded float32 or float64 value (depending on flt==&float32info or flt==&float64info) +// and returns it as a float64. +// The string s has already been parsed into a mantissa, exponent, and sign (neg==true for negative). +// If trunc is true, trailing non-zero bits have been omitted from the mantissa. +func atofHex(s string, flt *floatInfo, mantissa uint64, exp int, neg, trunc bool) (float64, error) { + maxExp := 1<>(flt.mantbits+2) == 0 { + mantissa <<= 1 + exp-- + } + if trunc { + mantissa |= 1 + } + for mantissa>>(1+flt.mantbits+2) != 0 { + mantissa = mantissa>>1 | mantissa&1 + exp++ + } + + // If exponent is too negative, + // denormalize in hopes of making it representable. + // (The -2 is for the rounding bits.) + for mantissa > 1 && exp < minExp-2 { + mantissa = mantissa>>1 | mantissa&1 + exp++ + } + + // Round using two bottom bits. + round := mantissa & 3 + mantissa >>= 2 + round |= mantissa & 1 // round to even (round up if mantissa is odd) + exp += 2 + if round == 3 { + mantissa++ + if mantissa == 1<<(1+flt.mantbits) { + mantissa >>= 1 + exp++ + } + } + + if mantissa>>flt.mantbits == 0 { // Denormal or zero. + exp = flt.bias + } + var err error + if exp > maxExp { // infinity and range error + mantissa = 1 << flt.mantbits + exp = maxExp + 1 + err = rangeError(fnParseFloat, s) + } + + bits := mantissa & (1<", "(", ")", "i", "init"} { + in := test.in + suffix + _, n, err := ParseFloatPrefix(in, 64) + if err != nil { + t.Errorf("ParseFloatPrefix(%q, 64): err = %v; want no error", in, err) + } + if n != len(test.in) { + t.Errorf("ParseFloatPrefix(%q, 64): n = %d; want %d", in, n, len(test.in)) + } + } + } +} + +func errEqual(e1, e2 error) bool { + // XXX: used in place of reflect.DeepEqual + if e1 == nil || e2 == nil { + return e1 == e2 + } + return e1.Error() == e2.Error() +} + +func printError(err error) string { + // XXX: gonative fns (like fmt.Printf, t.Errorf...) do not support printing errors + // and it would be very complicated to add. hence we're simplifying them to strings here. + if err == nil { + return "" + } + return err.Error() +} + +func testAtof(t *testing.T, opt bool) { + initAtof() + oldopt := SetOptimize(opt) + for i := 0; i < len(atoftests); i++ { + test := &atoftests[i] + out, err := ParseFloat(test.in, 64) + outs := FormatFloat(out, 'g', -1, 64) + if outs != test.out || !errEqual(err, test.err) { + t.Errorf("ParseFloat(%v, 64) = %v, %v want %v, %v", + test.in, out, printError(err), test.out, printError(test.err)) + } + + if float64(float32(out)) == out { + out, err := ParseFloat(test.in, 32) + out32 := float32(out) + if float64(out32) != out { + t.Errorf("ParseFloat(%v, 32) = %v, not a float32 (closest is %v)", test.in, out, float64(out32)) + continue + } + outs := FormatFloat(float64(out32), 'g', -1, 32) + if outs != test.out || !errEqual(err, test.err) { + t.Errorf("ParseFloat(%v, 32) = %v, %v want %v, %v # %v", + test.in, out32, printError(err), test.out, printError(test.err), out) + } + } + } + for _, test := range atof32tests { + out, err := ParseFloat(test.in, 32) + out32 := float32(out) + if float64(out32) != out { + t.Errorf("ParseFloat(%v, 32) = %v, not a float32 (closest is %v)", test.in, out, float64(out32)) + continue + } + outs := FormatFloat(float64(out32), 'g', -1, 32) + if outs != test.out || !errEqual(err, test.err) { + t.Errorf("ParseFloat(%v, 32) = %v, %v want %v, %v # %v", + test.in, out32, printError(err), test.out, printError(test.err), out) + } + } + SetOptimize(oldopt) +} + +func TestAtof(t *testing.T) { testAtof(t, true) } + +func TestAtofSlow(t *testing.T) { testAtof(t, false) } + +func TestAtofRandom(t *testing.T) { + initAtof() + for _, test := range atofRandomTests { + x, _ := ParseFloat(test.s, 64) + switch { + default: + t.Errorf("number %s badly parsed as %b (expected %b)", test.s, x, test.x) + case x == test.x: + case math.IsNaN(test.x) && math.IsNaN(x): + } + } + t.Logf("tested %d random numbers", len(atofRandomTests)) +} + +var roundTripCases = []struct { + f float64 + s string +}{ + // Issue 2917. + // This test will break the optimized conversion if the + // FPU is using 80-bit registers instead of 64-bit registers, + // usually because the operating system initialized the + // thread with 80-bit precision and the Go runtime didn't + // fix the FP control word. + {8865794286000691 << 39, "4.87402195346389e+27"}, + {8865794286000692 << 39, "4.8740219534638903e+27"}, +} + +func TestRoundTrip(t *testing.T) { + for _, tt := range roundTripCases { + old := SetOptimize(false) + s := FormatFloat(tt.f, 'g', -1, 64) + if s != tt.s { + t.Errorf("no-opt FormatFloat(%b) = %s, want %s", tt.f, s, tt.s) + } + f, err := ParseFloat(tt.s, 64) + if f != tt.f || err != nil { + t.Errorf("no-opt ParseFloat(%s) = %b, %v want %b, nil", tt.s, f, err, tt.f) + } + SetOptimize(true) + s = FormatFloat(tt.f, 'g', -1, 64) + if s != tt.s { + t.Errorf("opt FormatFloat(%b) = %s, want %s", tt.f, s, tt.s) + } + f, err = ParseFloat(tt.s, 64) + if f != tt.f || err != nil { + t.Errorf("opt ParseFloat(%s) = %b, %v want %b, nil", tt.s, f, err, tt.f) + } + SetOptimize(old) + } +} + +// TestRoundTrip32 tries a fraction of all finite positive float32 values. +func TestRoundTrip32(t *testing.T) { + step := uint32(997) + if testing.Short() { + step = 99991 + } + count := 0 + for i := uint32(0); i < 0xff<<23; i += step { + f := math.Float32frombits(i) + if i&1 == 1 { + f = -f // negative + } + s := FormatFloat(float64(f), 'g', -1, 32) + + parsed, err := ParseFloat(s, 32) + parsed32 := float32(parsed) + switch { + case err != nil: + t.Errorf("ParseFloat(%q, 32) gave error %s", s, err) + case float64(parsed32) != parsed: + t.Errorf("ParseFloat(%q, 32) = %v, not a float32 (nearest is %v)", s, parsed, parsed32) + case parsed32 != f: + t.Errorf("ParseFloat(%q, 32) = %b (expected %b)", s, parsed32, f) + } + count++ + } + t.Logf("tested %d float32's", count) +} + +// Issue 42297: a lot of code in the wild accidentally calls ParseFloat(s, 10) +// or ParseFloat(s, 0), so allow bitSize values other than 32 and 64. +func TestParseFloatIncorrectBitSize(t *testing.T) { + const s = "1.5e308" + const want = 1.5e308 + + for _, bitSize := range []int{0, 10, 100, 128} { + f, err := ParseFloat(s, bitSize) + if err != nil { + t.Fatalf("ParseFloat(%q, %d) gave error %s", s, bitSize, err) + } + if f != want { + t.Fatalf("ParseFloat(%q, %d) = %g (expected %g)", s, bitSize, f, want) + } + } +} + +func BenchmarkAtof64Decimal(b *testing.B) { + for i := 0; i < b.N; i++ { + ParseFloat("33909", 64) + } +} + +func BenchmarkAtof64Float(b *testing.B) { + for i := 0; i < b.N; i++ { + ParseFloat("339.7784", 64) + } +} + +func BenchmarkAtof64FloatExp(b *testing.B) { + for i := 0; i < b.N; i++ { + ParseFloat("-5.09e75", 64) + } +} + +func BenchmarkAtof64Big(b *testing.B) { + for i := 0; i < b.N; i++ { + ParseFloat("123456789123456789123456789", 64) + } +} + +func BenchmarkAtof64RandomBits(b *testing.B) { + initAtof() + b.ResetTimer() + for i := 0; i < b.N; i++ { + ParseFloat(benchmarksRandomBits[i%1024], 64) + } +} + +func BenchmarkAtof64RandomFloats(b *testing.B) { + initAtof() + b.ResetTimer() + for i := 0; i < b.N; i++ { + ParseFloat(benchmarksRandomNormal[i%1024], 64) + } +} + +func BenchmarkAtof64RandomLongFloats(b *testing.B) { + initAtof() + samples := make([]string, len(atofRandomTests)) + for i, t := range atofRandomTests { + samples[i] = FormatFloat(t.x, 'g', 20, 64) + } + b.ResetTimer() + idx := 0 + for i := 0; i < b.N; i++ { + ParseFloat(samples[idx], 64) + idx++ + if idx == len(samples) { + idx = 0 + } + } +} + +func BenchmarkAtof32Decimal(b *testing.B) { + for i := 0; i < b.N; i++ { + ParseFloat("33909", 32) + } +} + +func BenchmarkAtof32Float(b *testing.B) { + for i := 0; i < b.N; i++ { + ParseFloat("339.778", 32) + } +} + +func BenchmarkAtof32FloatExp(b *testing.B) { + for i := 0; i < b.N; i++ { + ParseFloat("12.3456e32", 32) + } +} + +func BenchmarkAtof32Random(b *testing.B) { + n := uint32(997) + var float32strings [4096]string + for i := range float32strings { + n = (99991*n + 42) % (0xff << 23) + float32strings[i] = FormatFloat(float64(math.Float32frombits(n)), 'g', -1, 32) + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + ParseFloat(float32strings[i%4096], 32) + } +} + +func BenchmarkAtof32RandomLong(b *testing.B) { + n := uint32(997) + var float32strings [4096]string + for i := range float32strings { + n = (99991*n + 42) % (0xff << 23) + float32strings[i] = FormatFloat(float64(math.Float32frombits(n)), 'g', 20, 32) + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + ParseFloat(float32strings[i%4096], 32) + } +} diff --git a/gnovm/stdlibs/strconv/atoi.gno b/gnovm/stdlibs/strconv/atoi.gno new file mode 100644 index 00000000000..28b8e7f0b14 --- /dev/null +++ b/gnovm/stdlibs/strconv/atoi.gno @@ -0,0 +1,332 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package strconv + +import "errors" + +// lower(c) is a lower-case letter if and only if +// c is either that lower-case letter or the equivalent upper-case letter. +// Instead of writing c == 'x' || c == 'X' one can write lower(c) == 'x'. +// Note that lower of non-letters can produce other non-letters. +func lower(c byte) byte { + return c | ('x' - 'X') +} + +// ErrRange indicates that a value is out of range for the target type. +var ErrRange = errors.New("value out of range") + +// ErrSyntax indicates that a value does not have the right syntax for the target type. +var ErrSyntax = errors.New("invalid syntax") + +// A NumError records a failed conversion. +type NumError struct { + Func string // the failing function (ParseBool, ParseInt, ParseUint, ParseFloat) + Num string // the input + Err error // the reason the conversion failed (e.g. ErrRange, ErrSyntax, etc.) +} + +func (e *NumError) Error() string { + return "strconv." + e.Func + ": " + "parsing " + Quote(e.Num) + ": " + e.Err.Error() +} + +func (e *NumError) Unwrap() error { return e.Err } + +// cloneString returns a string copy of x. +// +// All ParseXXX functions allow the input string to escape to the error value. +// This hurts strconv.ParseXXX(string(b)) calls where b is []byte since +// the conversion from []byte must allocate a string on the heap. +// If we assume errors are infrequent, then we can avoid escaping the input +// back to the output by copying it first. This allows the compiler to call +// strconv.ParseXXX without a heap allocation for most []byte to string +// conversions, since it can now prove that the string cannot escape Parse. +// +// TODO: Use strings.Clone instead? However, we cannot depend on "strings" +// since it incurs a transitive dependency on "unicode". +// Either move strings.Clone to an internal/bytealg or make the +// "strings" to "unicode" dependency lighter (see https://go.dev/issue/54098). +func cloneString(x string) string { return string([]byte(x)) } + +func syntaxError(fn, str string) *NumError { + return &NumError{fn, cloneString(str), ErrSyntax} +} + +func rangeError(fn, str string) *NumError { + return &NumError{fn, cloneString(str), ErrRange} +} + +func baseError(fn, str string, base int) *NumError { + return &NumError{fn, cloneString(str), errors.New("invalid base " + Itoa(base))} +} + +func bitSizeError(fn, str string, bitSize int) *NumError { + return &NumError{fn, cloneString(str), errors.New("invalid bit size " + Itoa(bitSize))} +} + +const intSize = 32 << (^uint(0) >> 63) + +// IntSize is the size in bits of an int or uint value. +const IntSize = intSize + +const maxUint64 = 1<<64 - 1 + +// ParseUint is like ParseInt but for unsigned numbers. +// +// A sign prefix is not permitted. +func ParseUint(s string, base int, bitSize int) (uint64, error) { + const fnParseUint = "ParseUint" + + if s == "" { + return 0, syntaxError(fnParseUint, s) + } + + base0 := base == 0 + + s0 := s + switch { + case 2 <= base && base <= 36: + // valid base; nothing to do + + case base == 0: + // Look for octal, hex prefix. + base = 10 + if s[0] == '0' { + switch { + case len(s) >= 3 && lower(s[1]) == 'b': + base = 2 + s = s[2:] + case len(s) >= 3 && lower(s[1]) == 'o': + base = 8 + s = s[2:] + case len(s) >= 3 && lower(s[1]) == 'x': + base = 16 + s = s[2:] + default: + base = 8 + s = s[1:] + } + } + + default: + return 0, baseError(fnParseUint, s0, base) + } + + if bitSize == 0 { + bitSize = IntSize + } else if bitSize < 0 || bitSize > 64 { + return 0, bitSizeError(fnParseUint, s0, bitSize) + } + + // Cutoff is the smallest number such that cutoff*base > maxUint64. + // Use compile-time constants for common cases. + var cutoff uint64 + switch base { + case 10: + cutoff = maxUint64/10 + 1 + case 16: + cutoff = maxUint64/16 + 1 + default: + cutoff = maxUint64/uint64(base) + 1 + } + + maxVal := uint64(1)<= byte(base) { + return 0, syntaxError(fnParseUint, s0) + } + + if n >= cutoff { + // n*base overflows + return maxVal, rangeError(fnParseUint, s0) + } + n *= uint64(base) + + n1 := n + uint64(d) + if n1 < n || n1 > maxVal { + // n+d overflows + return maxVal, rangeError(fnParseUint, s0) + } + n = n1 + } + + if underscores && !underscoreOK(s0) { + return 0, syntaxError(fnParseUint, s0) + } + + return n, nil +} + +// ParseInt interprets a string s in the given base (0, 2 to 36) and +// bit size (0 to 64) and returns the corresponding value i. +// +// The string may begin with a leading sign: "+" or "-". +// +// If the base argument is 0, the true base is implied by the string's +// prefix following the sign (if present): 2 for "0b", 8 for "0" or "0o", +// 16 for "0x", and 10 otherwise. Also, for argument base 0 only, +// underscore characters are permitted as defined by the Go syntax for +// [integer literals]. +// +// The bitSize argument specifies the integer type +// that the result must fit into. Bit sizes 0, 8, 16, 32, and 64 +// correspond to int, int8, int16, int32, and int64. +// If bitSize is below 0 or above 64, an error is returned. +// +// The errors that ParseInt returns have concrete type *NumError +// and include err.Num = s. If s is empty or contains invalid +// digits, err.Err = ErrSyntax and the returned value is 0; +// if the value corresponding to s cannot be represented by a +// signed integer of the given size, err.Err = ErrRange and the +// returned value is the maximum magnitude integer of the +// appropriate bitSize and sign. +// +// [integer literals]: https://go.dev/ref/spec#Integer_literals +func ParseInt(s string, base int, bitSize int) (i int64, err error) { + const fnParseInt = "ParseInt" + + if s == "" { + return 0, syntaxError(fnParseInt, s) + } + + // Pick off leading sign. + s0 := s + neg := false + if s[0] == '+' { + s = s[1:] + } else if s[0] == '-' { + neg = true + s = s[1:] + } + + // Convert unsigned and check range. + var un uint64 + un, err = ParseUint(s, base, bitSize) + if err != nil && err.(*NumError).Err != ErrRange { + err.(*NumError).Func = fnParseInt + err.(*NumError).Num = cloneString(s0) + return 0, err + } + + if bitSize == 0 { + bitSize = IntSize + } + + cutoff := uint64(1 << uint(bitSize-1)) + if !neg && un >= cutoff { + return int64(cutoff - 1), rangeError(fnParseInt, s0) + } + if neg && un > cutoff { + return -int64(cutoff), rangeError(fnParseInt, s0) + } + n := int64(un) + if neg { + n = -n + } + return n, nil +} + +// Atoi is equivalent to ParseInt(s, 10, 0), converted to type int. +func Atoi(s string) (int, error) { + const fnAtoi = "Atoi" + + sLen := len(s) + if intSize == 32 && (0 < sLen && sLen < 10) || + intSize == 64 && (0 < sLen && sLen < 19) { + // Fast path for small integers that fit int type. + s0 := s + if s[0] == '-' || s[0] == '+' { + s = s[1:] + if len(s) < 1 { + return 0, syntaxError(fnAtoi, s0) + } + } + + n := 0 + for _, ch := range []byte(s) { + ch -= '0' + if ch > 9 { + return 0, syntaxError(fnAtoi, s0) + } + n = n*10 + int(ch) + } + if s0[0] == '-' { + n = -n + } + return n, nil + } + + // Slow path for invalid, big, or underscored integers. + i64, err := ParseInt(s, 10, 0) + if nerr, ok := err.(*NumError); ok { + nerr.Func = fnAtoi + } + return int(i64), err +} + +// underscoreOK reports whether the underscores in s are allowed. +// Checking them in this one function lets all the parsers skip over them simply. +// Underscore must appear only between digits or between a base prefix and a digit. +func underscoreOK(s string) bool { + // saw tracks the last character (class) we saw: + // ^ for beginning of number, + // 0 for a digit or base prefix, + // _ for an underscore, + // ! for none of the above. + saw := '^' + i := 0 + + // Optional sign. + if len(s) >= 1 && (s[0] == '-' || s[0] == '+') { + s = s[1:] + } + + // Optional base prefix. + hex := false + if len(s) >= 2 && s[0] == '0' && (lower(s[1]) == 'b' || lower(s[1]) == 'o' || lower(s[1]) == 'x') { + i = 2 + saw = '0' // base prefix counts as a digit for "underscore as digit separator" + hex = lower(s[1]) == 'x' + } + + // Number proper. + for ; i < len(s); i++ { + // Digits are always okay. + if '0' <= s[i] && s[i] <= '9' || hex && 'a' <= lower(s[i]) && lower(s[i]) <= 'f' { + saw = '0' + continue + } + // Underscore must follow digit. + if s[i] == '_' { + if saw != '0' { + return false + } + saw = '_' + continue + } + // Underscore must also be followed by digit. + if saw == '_' { + return false + } + // Saw non-digit, non-underscore. + saw = '!' + } + return saw != '_' +} diff --git a/gnovm/stdlibs/strconv/atoi_test.gno b/gnovm/stdlibs/strconv/atoi_test.gno new file mode 100644 index 00000000000..cb150628f5c --- /dev/null +++ b/gnovm/stdlibs/strconv/atoi_test.gno @@ -0,0 +1,677 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package strconv + +import ( + "errors" + "fmt" + "testing" +) + +type parseUint64Test struct { + in string + out uint64 + err error +} + +var parseUint64Tests = []parseUint64Test{ + {"", 0, ErrSyntax}, + {"0", 0, nil}, + {"1", 1, nil}, + {"12345", 12345, nil}, + {"012345", 12345, nil}, + {"12345x", 0, ErrSyntax}, + {"98765432100", 98765432100, nil}, + {"18446744073709551615", 1<<64 - 1, nil}, + {"18446744073709551616", 1<<64 - 1, ErrRange}, + {"18446744073709551620", 1<<64 - 1, ErrRange}, + {"1_2_3_4_5", 0, ErrSyntax}, // base=10 so no underscores allowed + {"_12345", 0, ErrSyntax}, + {"1__2345", 0, ErrSyntax}, + {"12345_", 0, ErrSyntax}, + {"-0", 0, ErrSyntax}, + {"-1", 0, ErrSyntax}, + {"+1", 0, ErrSyntax}, +} + +type parseUint64BaseTest struct { + in string + base int + out uint64 + err error +} + +var parseUint64BaseTests = []parseUint64BaseTest{ + {"", 0, 0, ErrSyntax}, + {"0", 0, 0, nil}, + {"0x", 0, 0, ErrSyntax}, + {"0X", 0, 0, ErrSyntax}, + {"1", 0, 1, nil}, + {"12345", 0, 12345, nil}, + {"012345", 0, 012345, nil}, + {"0x12345", 0, 0x12345, nil}, + {"0X12345", 0, 0x12345, nil}, + {"12345x", 0, 0, ErrSyntax}, + {"0xabcdefg123", 0, 0, ErrSyntax}, + {"123456789abc", 0, 0, ErrSyntax}, + {"98765432100", 0, 98765432100, nil}, + {"18446744073709551615", 0, 1<<64 - 1, nil}, + {"18446744073709551616", 0, 1<<64 - 1, ErrRange}, + {"18446744073709551620", 0, 1<<64 - 1, ErrRange}, + {"0xFFFFFFFFFFFFFFFF", 0, 1<<64 - 1, nil}, + {"0x10000000000000000", 0, 1<<64 - 1, ErrRange}, + {"01777777777777777777777", 0, 1<<64 - 1, nil}, + {"01777777777777777777778", 0, 0, ErrSyntax}, + {"02000000000000000000000", 0, 1<<64 - 1, ErrRange}, + {"0200000000000000000000", 0, 1 << 61, nil}, + {"0b", 0, 0, ErrSyntax}, + {"0B", 0, 0, ErrSyntax}, + {"0b101", 0, 5, nil}, + {"0B101", 0, 5, nil}, + {"0o", 0, 0, ErrSyntax}, + {"0O", 0, 0, ErrSyntax}, + {"0o377", 0, 255, nil}, + {"0O377", 0, 255, nil}, + + // underscores allowed with base == 0 only + {"1_2_3_4_5", 0, 12345, nil}, // base 0 => 10 + {"_12345", 0, 0, ErrSyntax}, + {"1__2345", 0, 0, ErrSyntax}, + {"12345_", 0, 0, ErrSyntax}, + + {"1_2_3_4_5", 10, 0, ErrSyntax}, // base 10 + {"_12345", 10, 0, ErrSyntax}, + {"1__2345", 10, 0, ErrSyntax}, + {"12345_", 10, 0, ErrSyntax}, + + {"0x_1_2_3_4_5", 0, 0x12345, nil}, // base 0 => 16 + {"_0x12345", 0, 0, ErrSyntax}, + {"0x__12345", 0, 0, ErrSyntax}, + {"0x1__2345", 0, 0, ErrSyntax}, + {"0x1234__5", 0, 0, ErrSyntax}, + {"0x12345_", 0, 0, ErrSyntax}, + + {"1_2_3_4_5", 16, 0, ErrSyntax}, // base 16 + {"_12345", 16, 0, ErrSyntax}, + {"1__2345", 16, 0, ErrSyntax}, + {"1234__5", 16, 0, ErrSyntax}, + {"12345_", 16, 0, ErrSyntax}, + + {"0_1_2_3_4_5", 0, 012345, nil}, // base 0 => 8 (0377) + {"_012345", 0, 0, ErrSyntax}, + {"0__12345", 0, 0, ErrSyntax}, + {"01234__5", 0, 0, ErrSyntax}, + {"012345_", 0, 0, ErrSyntax}, + + {"0o_1_2_3_4_5", 0, 012345, nil}, // base 0 => 8 (0o377) + {"_0o12345", 0, 0, ErrSyntax}, + {"0o__12345", 0, 0, ErrSyntax}, + {"0o1234__5", 0, 0, ErrSyntax}, + {"0o12345_", 0, 0, ErrSyntax}, + + {"0_1_2_3_4_5", 8, 0, ErrSyntax}, // base 8 + {"_012345", 8, 0, ErrSyntax}, + {"0__12345", 8, 0, ErrSyntax}, + {"01234__5", 8, 0, ErrSyntax}, + {"012345_", 8, 0, ErrSyntax}, + + {"0b_1_0_1", 0, 5, nil}, // base 0 => 2 (0b101) + {"_0b101", 0, 0, ErrSyntax}, + {"0b__101", 0, 0, ErrSyntax}, + {"0b1__01", 0, 0, ErrSyntax}, + {"0b10__1", 0, 0, ErrSyntax}, + {"0b101_", 0, 0, ErrSyntax}, + + {"1_0_1", 2, 0, ErrSyntax}, // base 2 + {"_101", 2, 0, ErrSyntax}, + {"1_01", 2, 0, ErrSyntax}, + {"10_1", 2, 0, ErrSyntax}, + {"101_", 2, 0, ErrSyntax}, +} + +type parseInt64Test struct { + in string + out int64 + err error +} + +var parseInt64Tests = []parseInt64Test{ + {"", 0, ErrSyntax}, + {"0", 0, nil}, + {"-0", 0, nil}, + {"+0", 0, nil}, + {"1", 1, nil}, + {"-1", -1, nil}, + {"+1", 1, nil}, + {"12345", 12345, nil}, + {"-12345", -12345, nil}, + {"012345", 12345, nil}, + {"-012345", -12345, nil}, + {"98765432100", 98765432100, nil}, + {"-98765432100", -98765432100, nil}, + {"9223372036854775807", 1<<63 - 1, nil}, + {"-9223372036854775807", -(1<<63 - 1), nil}, + {"9223372036854775808", 1<<63 - 1, ErrRange}, + {"-9223372036854775808", -1 << 63, nil}, + {"9223372036854775809", 1<<63 - 1, ErrRange}, + {"-9223372036854775809", -1 << 63, ErrRange}, + {"-1_2_3_4_5", 0, ErrSyntax}, // base=10 so no underscores allowed + {"-_12345", 0, ErrSyntax}, + {"_12345", 0, ErrSyntax}, + {"1__2345", 0, ErrSyntax}, + {"12345_", 0, ErrSyntax}, + {"123%45", 0, ErrSyntax}, +} + +type parseInt64BaseTest struct { + in string + base int + out int64 + err error +} + +var parseInt64BaseTests = []parseInt64BaseTest{ + {"", 0, 0, ErrSyntax}, + {"0", 0, 0, nil}, + {"-0", 0, 0, nil}, + {"1", 0, 1, nil}, + {"-1", 0, -1, nil}, + {"12345", 0, 12345, nil}, + {"-12345", 0, -12345, nil}, + {"012345", 0, 012345, nil}, + {"-012345", 0, -012345, nil}, + {"0x12345", 0, 0x12345, nil}, + {"-0X12345", 0, -0x12345, nil}, + {"12345x", 0, 0, ErrSyntax}, + {"-12345x", 0, 0, ErrSyntax}, + {"98765432100", 0, 98765432100, nil}, + {"-98765432100", 0, -98765432100, nil}, + {"9223372036854775807", 0, 1<<63 - 1, nil}, + {"-9223372036854775807", 0, -(1<<63 - 1), nil}, + {"9223372036854775808", 0, 1<<63 - 1, ErrRange}, + {"-9223372036854775808", 0, -1 << 63, nil}, + {"9223372036854775809", 0, 1<<63 - 1, ErrRange}, + {"-9223372036854775809", 0, -1 << 63, ErrRange}, + + // other bases + {"g", 17, 16, nil}, + {"10", 25, 25, nil}, + {"holycow", 35, (((((17*35+24)*35+21)*35+34)*35+12)*35+24)*35 + 32, nil}, + {"holycow", 36, (((((17*36+24)*36+21)*36+34)*36+12)*36+24)*36 + 32, nil}, + + // base 2 + {"0", 2, 0, nil}, + {"-1", 2, -1, nil}, + {"1010", 2, 10, nil}, + {"1000000000000000", 2, 1 << 15, nil}, + {"111111111111111111111111111111111111111111111111111111111111111", 2, 1<<63 - 1, nil}, + {"1000000000000000000000000000000000000000000000000000000000000000", 2, 1<<63 - 1, ErrRange}, + {"-1000000000000000000000000000000000000000000000000000000000000000", 2, -1 << 63, nil}, + {"-1000000000000000000000000000000000000000000000000000000000000001", 2, -1 << 63, ErrRange}, + + // base 8 + {"-10", 8, -8, nil}, + {"57635436545", 8, 057635436545, nil}, + {"100000000", 8, 1 << 24, nil}, + + // base 16 + {"10", 16, 16, nil}, + {"-123456789abcdef", 16, -0x123456789abcdef, nil}, + {"7fffffffffffffff", 16, 1<<63 - 1, nil}, + + // underscores + {"-0x_1_2_3_4_5", 0, -0x12345, nil}, + {"0x_1_2_3_4_5", 0, 0x12345, nil}, + {"-_0x12345", 0, 0, ErrSyntax}, + {"_-0x12345", 0, 0, ErrSyntax}, + {"_0x12345", 0, 0, ErrSyntax}, + {"0x__12345", 0, 0, ErrSyntax}, + {"0x1__2345", 0, 0, ErrSyntax}, + {"0x1234__5", 0, 0, ErrSyntax}, + {"0x12345_", 0, 0, ErrSyntax}, + + {"-0_1_2_3_4_5", 0, -012345, nil}, // octal + {"0_1_2_3_4_5", 0, 012345, nil}, // octal + {"-_012345", 0, 0, ErrSyntax}, + {"_-012345", 0, 0, ErrSyntax}, + {"_012345", 0, 0, ErrSyntax}, + {"0__12345", 0, 0, ErrSyntax}, + {"01234__5", 0, 0, ErrSyntax}, + {"012345_", 0, 0, ErrSyntax}, + + {"+0xf", 0, 0xf, nil}, + {"-0xf", 0, -0xf, nil}, + {"0x+f", 0, 0, ErrSyntax}, + {"0x-f", 0, 0, ErrSyntax}, +} + +type parseUint32Test struct { + in string + out uint32 + err error +} + +var parseUint32Tests = []parseUint32Test{ + {"", 0, ErrSyntax}, + {"0", 0, nil}, + {"1", 1, nil}, + {"12345", 12345, nil}, + {"012345", 12345, nil}, + {"12345x", 0, ErrSyntax}, + {"987654321", 987654321, nil}, + {"4294967295", 1<<32 - 1, nil}, + {"4294967296", 1<<32 - 1, ErrRange}, + {"1_2_3_4_5", 0, ErrSyntax}, // base=10 so no underscores allowed + {"_12345", 0, ErrSyntax}, + {"_12345", 0, ErrSyntax}, + {"1__2345", 0, ErrSyntax}, + {"12345_", 0, ErrSyntax}, +} + +type parseInt32Test struct { + in string + out int32 + err error +} + +var parseInt32Tests = []parseInt32Test{ + {"", 0, ErrSyntax}, + {"0", 0, nil}, + {"-0", 0, nil}, + {"1", 1, nil}, + {"-1", -1, nil}, + {"12345", 12345, nil}, + {"-12345", -12345, nil}, + {"012345", 12345, nil}, + {"-012345", -12345, nil}, + {"12345x", 0, ErrSyntax}, + {"-12345x", 0, ErrSyntax}, + {"987654321", 987654321, nil}, + {"-987654321", -987654321, nil}, + {"2147483647", 1<<31 - 1, nil}, + {"-2147483647", -(1<<31 - 1), nil}, + {"2147483648", 1<<31 - 1, ErrRange}, + {"-2147483648", -1 << 31, nil}, + {"2147483649", 1<<31 - 1, ErrRange}, + {"-2147483649", -1 << 31, ErrRange}, + {"-1_2_3_4_5", 0, ErrSyntax}, // base=10 so no underscores allowed + {"-_12345", 0, ErrSyntax}, + {"_12345", 0, ErrSyntax}, + {"1__2345", 0, ErrSyntax}, + {"12345_", 0, ErrSyntax}, + {"123%45", 0, ErrSyntax}, +} + +type numErrorTest struct { + num, want string +} + +var numErrorTests = []numErrorTest{ + {"0", `strconv.ParseFloat: parsing "0": failed`}, + {"`", "strconv.ParseFloat: parsing \"`\": failed"}, + {"1\x00.2", `strconv.ParseFloat: parsing "1\x00.2": failed`}, +} + +func init() { + // The parse routines return NumErrors wrapping + // the error and the string. Convert the tables above. + for i := range parseUint64Tests { + test := &parseUint64Tests[i] + if test.err != nil { + test.err = &NumError{"ParseUint", test.in, test.err} + } + } + for i := range parseUint64BaseTests { + test := &parseUint64BaseTests[i] + if test.err != nil { + test.err = &NumError{"ParseUint", test.in, test.err} + } + } + for i := range parseInt64Tests { + test := &parseInt64Tests[i] + if test.err != nil { + test.err = &NumError{"ParseInt", test.in, test.err} + } + } + for i := range parseInt64BaseTests { + test := &parseInt64BaseTests[i] + if test.err != nil { + test.err = &NumError{"ParseInt", test.in, test.err} + } + } + for i := range parseUint32Tests { + test := &parseUint32Tests[i] + if test.err != nil { + test.err = &NumError{"ParseUint", test.in, test.err} + } + } + for i := range parseInt32Tests { + test := &parseInt32Tests[i] + if test.err != nil { + test.err = &NumError{"ParseInt", test.in, test.err} + } + } +} + +func TestParseUint32(t *testing.T) { + for i := range parseUint32Tests { + test := &parseUint32Tests[i] + out, err := ParseUint(test.in, 10, 32) + if uint64(test.out) != out || !errEqual(test.err, err) { + t.Errorf("ParseUint(%q, 10, 32) = %v, %v want %v, %v", + test.in, out, err, test.out, test.err) + } + } +} + +func TestParseUint64(t *testing.T) { + for i := range parseUint64Tests { + test := &parseUint64Tests[i] + out, err := ParseUint(test.in, 10, 64) + if test.out != out || !errEqual(test.err, err) { + t.Errorf("ParseUint(%q, 10, 64) = %v, %v want %v, %v", + test.in, out, err, test.out, test.err) + } + } +} + +func TestParseUint64Base(t *testing.T) { + for i := range parseUint64BaseTests { + test := &parseUint64BaseTests[i] + out, err := ParseUint(test.in, test.base, 64) + if test.out != out || !errEqual(test.err, err) { + t.Errorf("ParseUint(%q, %v, 64) = %v, %v want %v, %v", + test.in, test.base, out, err, test.out, test.err) + } + } +} + +func TestParseInt32(t *testing.T) { + for i := range parseInt32Tests { + test := &parseInt32Tests[i] + out, err := ParseInt(test.in, 10, 32) + if int64(test.out) != out || !errEqual(test.err, err) { + t.Errorf("ParseInt(%q, 10 ,32) = %v, %v want %v, %v", + test.in, out, err, test.out, test.err) + } + } +} + +func TestParseInt64(t *testing.T) { + for i := range parseInt64Tests { + test := &parseInt64Tests[i] + out, err := ParseInt(test.in, 10, 64) + if test.out != out || !errEqual(test.err, err) { + t.Errorf("ParseInt(%q, 10, 64) = %v, %v want %v, %v", + test.in, out, err, test.out, test.err) + } + } +} + +func TestParseInt64Base(t *testing.T) { + for i := range parseInt64BaseTests { + test := &parseInt64BaseTests[i] + out, err := ParseInt(test.in, test.base, 64) + if test.out != out || !errEqual(test.err, err) { + t.Errorf("ParseInt(%q, %v, 64) = %v, %v want %v, %v", + test.in, test.base, out, err, test.out, test.err) + } + } +} + +func TestParseUint(t *testing.T) { + switch IntSize { + case 32: + for i := range parseUint32Tests { + test := &parseUint32Tests[i] + out, err := ParseUint(test.in, 10, 0) + if uint64(test.out) != out || !errEqual(test.err, err) { + t.Errorf("ParseUint(%q, 10, 0) = %v, %v want %v, %v", + test.in, out, err, test.out, test.err) + } + } + case 64: + for i := range parseUint64Tests { + test := &parseUint64Tests[i] + out, err := ParseUint(test.in, 10, 0) + if test.out != out || !errEqual(test.err, err) { + t.Errorf("ParseUint(%q, 10, 0) = %v, %v want %v, %v", + test.in, out, err, test.out, test.err) + } + } + } +} + +func TestParseInt(t *testing.T) { + switch IntSize { + case 32: + for i := range parseInt32Tests { + test := &parseInt32Tests[i] + out, err := ParseInt(test.in, 10, 0) + if int64(test.out) != out || !errEqual(test.err, err) { + t.Errorf("ParseInt(%q, 10, 0) = %v, %v want %v, %v", + test.in, out, err, test.out, test.err) + } + } + case 64: + for i := range parseInt64Tests { + test := &parseInt64Tests[i] + out, err := ParseInt(test.in, 10, 0) + if test.out != out || !errEqual(test.err, err) { + t.Errorf("ParseInt(%q, 10, 0) = %v, %v want %v, %v", + test.in, out, err, test.out, test.err) + } + } + } +} + +func TestAtoi(t *testing.T) { + switch IntSize { + case 32: + for i := range parseInt32Tests { + test := &parseInt32Tests[i] + out, err := Atoi(test.in) + var testErr error + if test.err != nil { + testErr = &NumError{"Atoi", test.in, test.err.(*NumError).Err} + } + if int(test.out) != out || !errEqual(testErr, err) { + t.Errorf("Atoi(%q) = %v, %v want %v, %v", + test.in, out, err, test.out, testErr) + } + } + case 64: + for i := range parseInt64Tests { + test := &parseInt64Tests[i] + out, err := Atoi(test.in) + var testErr error + if test.err != nil { + testErr = &NumError{"Atoi", test.in, test.err.(*NumError).Err} + } + if test.out != int64(out) || !errEqual(testErr, err) { + t.Errorf("Atoi(%q) = %v, %v want %v, %v", + test.in, out, err, test.out, testErr) + } + } + } +} + +func bitSizeErrStub(name string, bitSize int) error { + return BitSizeError(name, "0", bitSize) +} + +func baseErrStub(name string, base int) error { + return BaseError(name, "0", base) +} + +func noErrStub(name string, arg int) error { + return nil +} + +type parseErrorTest struct { + arg int + errStub func(name string, arg int) error +} + +var parseBitSizeTests = []parseErrorTest{ + {-1, bitSizeErrStub}, + {0, noErrStub}, + {64, noErrStub}, + {65, bitSizeErrStub}, +} + +var parseBaseTests = []parseErrorTest{ + {-1, baseErrStub}, + {0, noErrStub}, + {1, baseErrStub}, + {2, noErrStub}, + {36, noErrStub}, + {37, baseErrStub}, +} + +func equalError(a, b error) bool { + if a == nil { + return b == nil + } + if b == nil { + return a == nil + } + return a.Error() == b.Error() +} + +func TestParseIntBitSize(t *testing.T) { + for i := range parseBitSizeTests { + test := &parseBitSizeTests[i] + testErr := test.errStub("ParseInt", test.arg) + _, err := ParseInt("0", 0, test.arg) + if !equalError(testErr, err) { + t.Errorf("ParseInt(\"0\", 0, %v) = 0, %v want 0, %v", + test.arg, err, testErr) + } + } +} + +func TestParseUintBitSize(t *testing.T) { + for i := range parseBitSizeTests { + test := &parseBitSizeTests[i] + testErr := test.errStub("ParseUint", test.arg) + _, err := ParseUint("0", 0, test.arg) + if !equalError(testErr, err) { + t.Errorf("ParseUint(\"0\", 0, %v) = 0, %v want 0, %v", + test.arg, err, testErr) + } + } +} + +func TestParseIntBase(t *testing.T) { + for i := range parseBaseTests { + test := &parseBaseTests[i] + testErr := test.errStub("ParseInt", test.arg) + _, err := ParseInt("0", test.arg, 0) + if !equalError(testErr, err) { + t.Errorf("ParseInt(\"0\", %v, 0) = 0, %v want 0, %v", + test.arg, err, testErr) + } + } +} + +func TestParseUintBase(t *testing.T) { + for i := range parseBaseTests { + test := &parseBaseTests[i] + testErr := test.errStub("ParseUint", test.arg) + _, err := ParseUint("0", test.arg, 0) + if !equalError(testErr, err) { + t.Errorf("ParseUint(\"0\", %v, 0) = 0, %v want 0, %v", + test.arg, err, testErr) + } + } +} + +func TestNumError(t *testing.T) { + for _, test := range numErrorTests { + err := &NumError{ + Func: "ParseFloat", + Num: test.num, + Err: errors.New("failed"), + } + if got := err.Error(); got != test.want { + t.Errorf(`(&NumError{"ParseFloat", %q, "failed"}).Error() = %v, want %v`, test.num, got, test.want) + } + } +} + +/* XXX: add when we support reflection / error un/wrapping. +func TestNumErrorUnwrap(t *testing.T) { + err := &NumError{Err: ErrSyntax} + if !errEqual(err, ErrSyntax) { + t.Error("errors.Is failed, wanted success") + } +} +*/ + +func BenchmarkParseInt(b *testing.B) { + b.Run("Pos", func(b *testing.B) { + benchmarkParseInt(b, 1) + }) + b.Run("Neg", func(b *testing.B) { + benchmarkParseInt(b, -1) + }) +} + +type benchCase struct { + name string + num int64 +} + +func benchmarkParseInt(b *testing.B, neg int) { + cases := []benchCase{ + {"7bit", 1<<7 - 1}, + {"26bit", 1<<26 - 1}, + {"31bit", 1<<31 - 1}, + {"56bit", 1<<56 - 1}, + {"63bit", 1<<63 - 1}, + } + for _, cs := range cases { + b.Run(cs.name, func(b *testing.B) { + s := fmt.Sprintf("%d", cs.num*int64(neg)) + for i := 0; i < b.N; i++ { + out, _ := ParseInt(s, 10, 64) + BenchSink += int(out) + } + }) + } +} + +func BenchmarkAtoi(b *testing.B) { + b.Run("Pos", func(b *testing.B) { + benchmarkAtoi(b, 1) + }) + b.Run("Neg", func(b *testing.B) { + benchmarkAtoi(b, -1) + }) +} + +func benchmarkAtoi(b *testing.B, neg int) { + cases := []benchCase{ + {"7bit", 1<<7 - 1}, + {"26bit", 1<<26 - 1}, + {"31bit", 1<<31 - 1}, + } + if IntSize == 64 { + cases = append(cases, []benchCase{ + {"56bit", 1<<56 - 1}, + {"63bit", 1<<63 - 1}, + }...) + } + for _, cs := range cases { + b.Run(cs.name, func(b *testing.B) { + s := fmt.Sprintf("%d", cs.num*int64(neg)) + for i := 0; i < b.N; i++ { + out, _ := Atoi(s) + BenchSink += out + } + }) + } +} diff --git a/gnovm/stdlibs/strconv/bytealg.gno b/gnovm/stdlibs/strconv/bytealg.gno new file mode 100644 index 00000000000..2c813885f53 --- /dev/null +++ b/gnovm/stdlibs/strconv/bytealg.gno @@ -0,0 +1,12 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package strconv + +import "internal/bytealg" + +// index returns the index of the first instance of c in s, or -1 if missing. +func index(s string, c byte) int { + return bytealg.IndexByteString(s, c) +} diff --git a/gnovm/stdlibs/strconv/decimal.gno b/gnovm/stdlibs/strconv/decimal.gno new file mode 100644 index 00000000000..b58001888e8 --- /dev/null +++ b/gnovm/stdlibs/strconv/decimal.gno @@ -0,0 +1,415 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Multiprecision decimal numbers. +// For floating-point formatting only; not general purpose. +// Only operations are assign and (binary) left/right shift. +// Can do binary floating point in multiprecision decimal precisely +// because 2 divides 10; cannot do decimal floating point +// in multiprecision binary precisely. + +package strconv + +type decimal struct { + d [800]byte // digits, big-endian representation + nd int // number of digits used + dp int // decimal point + neg bool // negative flag + trunc bool // discarded nonzero digits beyond d[:nd] +} + +func (a *decimal) String() string { + n := 10 + a.nd + if a.dp > 0 { + n += a.dp + } + if a.dp < 0 { + n += -a.dp + } + + buf := make([]byte, n) + w := 0 + switch { + case a.nd == 0: + return "0" + + case a.dp <= 0: + // zeros fill space between decimal point and digits + buf[w] = '0' + w++ + buf[w] = '.' + w++ + w += digitZero(buf[w : w+-a.dp]) + w += copy(buf[w:], a.d[0:a.nd]) + + case a.dp < a.nd: + // decimal point in middle of digits + w += copy(buf[w:], a.d[0:a.dp]) + buf[w] = '.' + w++ + w += copy(buf[w:], a.d[a.dp:a.nd]) + + default: + // zeros fill space between digits and decimal point + w += copy(buf[w:], a.d[0:a.nd]) + w += digitZero(buf[w : w+a.dp-a.nd]) + } + return string(buf[0:w]) +} + +func digitZero(dst []byte) int { + for i := range dst { + dst[i] = '0' + } + return len(dst) +} + +// trim trailing zeros from number. +// (They are meaningless; the decimal point is tracked +// independent of the number of digits.) +func trim(a *decimal) { + for a.nd > 0 && a.d[a.nd-1] == '0' { + a.nd-- + } + if a.nd == 0 { + a.dp = 0 + } +} + +// Assign v to a. +func (a *decimal) Assign(v uint64) { + var buf [24]byte + + // Write reversed decimal in buf. + n := 0 + for v > 0 { + v1 := v / 10 + v -= 10 * v1 + buf[n] = byte(v + '0') + n++ + v = v1 + } + + // Reverse again to produce forward decimal in a.d. + a.nd = 0 + for n--; n >= 0; n-- { + a.d[a.nd] = buf[n] + a.nd++ + } + a.dp = a.nd + trim(a) +} + +// Maximum shift that we can do in one pass without overflow. +// A uint has 32 or 64 bits, and we have to be able to accommodate 9<> 63) +const maxShift = uintSize - 4 + +// Binary shift right (/ 2) by k bits. k <= maxShift to avoid overflow. +func rightShift(a *decimal, k uint) { + r := 0 // read pointer + w := 0 // write pointer + + // Pick up enough leading digits to cover first shift. + var n uint + for ; n>>k == 0; r++ { + if r >= a.nd { + if n == 0 { + // a == 0; shouldn't get here, but handle anyway. + a.nd = 0 + return + } + for n>>k == 0 { + n = n * 10 + r++ + } + break + } + c := uint(a.d[r]) + n = n*10 + c - '0' + } + a.dp -= r - 1 + + var mask uint = (1 << k) - 1 + + // Pick up a digit, put down a digit. + for ; r < a.nd; r++ { + c := uint(a.d[r]) + dig := n >> k + n &= mask + a.d[w] = byte(dig + '0') + w++ + n = n*10 + c - '0' + } + + // Put down extra digits. + for n > 0 { + dig := n >> k + n &= mask + if w < len(a.d) { + a.d[w] = byte(dig + '0') + w++ + } else if dig > 0 { + a.trunc = true + } + n = n * 10 + } + + a.nd = w + trim(a) +} + +// Cheat sheet for left shift: table indexed by shift count giving +// number of new digits that will be introduced by that shift. +// +// For example, leftcheats[4] = {2, "625"}. That means that +// if we are shifting by 4 (multiplying by 16), it will add 2 digits +// when the string prefix is "625" through "999", and one fewer digit +// if the string prefix is "000" through "624". +// +// Credit for this trick goes to Ken. + +type leftCheat struct { + delta int // number of new digits + cutoff string // minus one digit if original < a. +} + +var leftcheats = []leftCheat{ + // Leading digits of 1/2^i = 5^i. + // 5^23 is not an exact 64-bit floating point number, + // so have to use bc for the math. + // Go up to 60 to be large enough for 32bit and 64bit platforms. + /* + seq 60 | sed 's/^/5^/' | bc | + awk 'BEGIN{ print "\t{ 0, \"\" }," } + { + log2 = log(2)/log(10) + printf("\t{ %d, \"%s\" },\t// * %d\n", + int(log2*NR+1), $0, 2**NR) + }' + */ + {0, ""}, + {1, "5"}, // * 2 + {1, "25"}, // * 4 + {1, "125"}, // * 8 + {2, "625"}, // * 16 + {2, "3125"}, // * 32 + {2, "15625"}, // * 64 + {3, "78125"}, // * 128 + {3, "390625"}, // * 256 + {3, "1953125"}, // * 512 + {4, "9765625"}, // * 1024 + {4, "48828125"}, // * 2048 + {4, "244140625"}, // * 4096 + {4, "1220703125"}, // * 8192 + {5, "6103515625"}, // * 16384 + {5, "30517578125"}, // * 32768 + {5, "152587890625"}, // * 65536 + {6, "762939453125"}, // * 131072 + {6, "3814697265625"}, // * 262144 + {6, "19073486328125"}, // * 524288 + {7, "95367431640625"}, // * 1048576 + {7, "476837158203125"}, // * 2097152 + {7, "2384185791015625"}, // * 4194304 + {7, "11920928955078125"}, // * 8388608 + {8, "59604644775390625"}, // * 16777216 + {8, "298023223876953125"}, // * 33554432 + {8, "1490116119384765625"}, // * 67108864 + {9, "7450580596923828125"}, // * 134217728 + {9, "37252902984619140625"}, // * 268435456 + {9, "186264514923095703125"}, // * 536870912 + {10, "931322574615478515625"}, // * 1073741824 + {10, "4656612873077392578125"}, // * 2147483648 + {10, "23283064365386962890625"}, // * 4294967296 + {10, "116415321826934814453125"}, // * 8589934592 + {11, "582076609134674072265625"}, // * 17179869184 + {11, "2910383045673370361328125"}, // * 34359738368 + {11, "14551915228366851806640625"}, // * 68719476736 + {12, "72759576141834259033203125"}, // * 137438953472 + {12, "363797880709171295166015625"}, // * 274877906944 + {12, "1818989403545856475830078125"}, // * 549755813888 + {13, "9094947017729282379150390625"}, // * 1099511627776 + {13, "45474735088646411895751953125"}, // * 2199023255552 + {13, "227373675443232059478759765625"}, // * 4398046511104 + {13, "1136868377216160297393798828125"}, // * 8796093022208 + {14, "5684341886080801486968994140625"}, // * 17592186044416 + {14, "28421709430404007434844970703125"}, // * 35184372088832 + {14, "142108547152020037174224853515625"}, // * 70368744177664 + {15, "710542735760100185871124267578125"}, // * 140737488355328 + {15, "3552713678800500929355621337890625"}, // * 281474976710656 + {15, "17763568394002504646778106689453125"}, // * 562949953421312 + {16, "88817841970012523233890533447265625"}, // * 1125899906842624 + {16, "444089209850062616169452667236328125"}, // * 2251799813685248 + {16, "2220446049250313080847263336181640625"}, // * 4503599627370496 + {16, "11102230246251565404236316680908203125"}, // * 9007199254740992 + {17, "55511151231257827021181583404541015625"}, // * 18014398509481984 + {17, "277555756156289135105907917022705078125"}, // * 36028797018963968 + {17, "1387778780781445675529539585113525390625"}, // * 72057594037927936 + {18, "6938893903907228377647697925567626953125"}, // * 144115188075855872 + {18, "34694469519536141888238489627838134765625"}, // * 288230376151711744 + {18, "173472347597680709441192448139190673828125"}, // * 576460752303423488 + {19, "867361737988403547205962240695953369140625"}, // * 1152921504606846976 +} + +// Is the leading prefix of b lexicographically less than s? +func prefixIsLessThan(b []byte, s string) bool { + for i := 0; i < len(s); i++ { + if i >= len(b) { + return true + } + if b[i] != s[i] { + return b[i] < s[i] + } + } + return false +} + +// Binary shift left (* 2) by k bits. k <= maxShift to avoid overflow. +func leftShift(a *decimal, k uint) { + delta := leftcheats[k].delta + if prefixIsLessThan(a.d[0:a.nd], leftcheats[k].cutoff) { + delta-- + } + + r := a.nd // read index + w := a.nd + delta // write index + + // Pick up a digit, put down a digit. + var n uint + for r--; r >= 0; r-- { + n += (uint(a.d[r]) - '0') << k + quo := n / 10 + rem := n - 10*quo + w-- + if w < len(a.d) { + a.d[w] = byte(rem + '0') + } else if rem != 0 { + a.trunc = true + } + n = quo + } + + // Put down extra digits. + for n > 0 { + quo := n / 10 + rem := n - 10*quo + w-- + if w < len(a.d) { + a.d[w] = byte(rem + '0') + } else if rem != 0 { + a.trunc = true + } + n = quo + } + + a.nd += delta + if a.nd >= len(a.d) { + a.nd = len(a.d) + } + a.dp += delta + trim(a) +} + +// Binary shift left (k > 0) or right (k < 0). +func (a *decimal) Shift(k int) { + switch { + case a.nd == 0: + // nothing to do: a == 0 + case k > 0: + for k > maxShift { + leftShift(a, maxShift) + k -= maxShift + } + leftShift(a, uint(k)) + case k < 0: + for k < -maxShift { + rightShift(a, maxShift) + k += maxShift + } + rightShift(a, uint(-k)) + } +} + +// If we chop a at nd digits, should we round up? +func shouldRoundUp(a *decimal, nd int) bool { + if nd < 0 || nd >= a.nd { + return false + } + if a.d[nd] == '5' && nd+1 == a.nd { // exactly halfway - round to even + // if we truncated, a little higher than what's recorded - always round up + if a.trunc { + return true + } + return nd > 0 && (a.d[nd-1]-'0')%2 != 0 + } + // not halfway - digit tells all + return a.d[nd] >= '5' +} + +// Round a to nd digits (or fewer). +// If nd is zero, it means we're rounding +// just to the left of the digits, as in +// 0.09 -> 0.1. +func (a *decimal) Round(nd int) { + if nd < 0 || nd >= a.nd { + return + } + if shouldRoundUp(a, nd) { + a.RoundUp(nd) + } else { + a.RoundDown(nd) + } +} + +// Round a down to nd digits (or fewer). +func (a *decimal) RoundDown(nd int) { + if nd < 0 || nd >= a.nd { + return + } + a.nd = nd + trim(a) +} + +// Round a up to nd digits (or fewer). +func (a *decimal) RoundUp(nd int) { + if nd < 0 || nd >= a.nd { + return + } + + // round up + for i := nd - 1; i >= 0; i-- { + c := a.d[i] + if c < '9' { // can stop after this digit + a.d[i]++ + a.nd = i + 1 + return + } + } + + // Number is all 9s. + // Change to single 1 with adjusted decimal point. + a.d[0] = '1' + a.nd = 1 + a.dp++ +} + +// Extract integer part, rounded appropriately. +// No guarantees about overflow. +func (a *decimal) RoundedInteger() uint64 { + if a.dp > 20 { + return 0xFFFFFFFFFFFFFFFF + } + var i int + n := uint64(0) + for i = 0; i < a.dp && i < a.nd; i++ { + n = n*10 + uint64(a.d[i]-'0') + } + for ; i < a.dp; i++ { + n *= 10 + } + if shouldRoundUp(a, a.dp) { + n++ + } + return n +} diff --git a/gnovm/stdlibs/strconv/decimal_test.gno b/gnovm/stdlibs/strconv/decimal_test.gno new file mode 100644 index 00000000000..9dc8c997b9c --- /dev/null +++ b/gnovm/stdlibs/strconv/decimal_test.gno @@ -0,0 +1,126 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package strconv + +import ( + "testing" +) + +type shiftTest struct { + i uint64 + shift int + out string +} + +var shifttests = []shiftTest{ + {0, -100, "0"}, + {0, 100, "0"}, + {1, 100, "1267650600228229401496703205376"}, + {1, -100, + "0.00000000000000000000000000000078886090522101180541" + + "17285652827862296732064351090230047702789306640625", + }, + {12345678, 8, "3160493568"}, + {12345678, -8, "48225.3046875"}, + {195312, 9, "99999744"}, + {1953125, 9, "1000000000"}, +} + +func TestDecimalShift(t *testing.T) { + for i := 0; i < len(shifttests); i++ { + test := &shifttests[i] + d := NewDecimal(test.i) + d.Shift(test.shift) + s := d.String() + if s != test.out { + t.Errorf("Decimal %v << %v = %v, want %v", + test.i, test.shift, s, test.out) + } + } +} + +type roundTest struct { + i uint64 + nd int + down, round, up string + int uint64 +} + +var roundtests = []roundTest{ + {0, 4, "0", "0", "0", 0}, + {12344999, 4, "12340000", "12340000", "12350000", 12340000}, + {12345000, 4, "12340000", "12340000", "12350000", 12340000}, + {12345001, 4, "12340000", "12350000", "12350000", 12350000}, + {23454999, 4, "23450000", "23450000", "23460000", 23450000}, + {23455000, 4, "23450000", "23460000", "23460000", 23460000}, + {23455001, 4, "23450000", "23460000", "23460000", 23460000}, + + {99994999, 4, "99990000", "99990000", "100000000", 99990000}, + {99995000, 4, "99990000", "100000000", "100000000", 100000000}, + {99999999, 4, "99990000", "100000000", "100000000", 100000000}, + + {12994999, 4, "12990000", "12990000", "13000000", 12990000}, + {12995000, 4, "12990000", "13000000", "13000000", 13000000}, + {12999999, 4, "12990000", "13000000", "13000000", 13000000}, +} + +func TestDecimalRound(t *testing.T) { + for i := 0; i < len(roundtests); i++ { + test := &roundtests[i] + d := NewDecimal(test.i) + d.RoundDown(test.nd) + s := d.String() + if s != test.down { + t.Errorf("Decimal %v RoundDown %d = %v, want %v", + test.i, test.nd, s, test.down) + } + d = NewDecimal(test.i) + d.Round(test.nd) + s = d.String() + if s != test.round { + t.Errorf("Decimal %v Round %d = %v, want %v", + test.i, test.nd, s, test.down) + } + d = NewDecimal(test.i) + d.RoundUp(test.nd) + s = d.String() + if s != test.up { + t.Errorf("Decimal %v RoundUp %d = %v, want %v", + test.i, test.nd, s, test.up) + } + } +} + +type roundIntTest struct { + i uint64 + shift int + int uint64 +} + +var roundinttests = []roundIntTest{ + {0, 100, 0}, + {512, -8, 2}, + {513, -8, 2}, + {640, -8, 2}, + {641, -8, 3}, + {384, -8, 2}, + {385, -8, 2}, + {383, -8, 1}, + {1, 100, 1<<64 - 1}, + {1000, 0, 1000}, +} + +func TestDecimalRoundedInteger(t *testing.T) { + for i := 0; i < len(roundinttests); i++ { + test := roundinttests[i] + d := NewDecimal(test.i) + d.Shift(test.shift) + num := d.RoundedInteger() + if num != test.int { + t.Errorf("Decimal %v >> %v RoundedInteger = %v, want %v", + test.i, test.shift, num, test.int) + } + } +} diff --git a/gnovm/stdlibs/strconv/doc.gno b/gnovm/stdlibs/strconv/doc.gno new file mode 100644 index 00000000000..9a22d77a0cd --- /dev/null +++ b/gnovm/stdlibs/strconv/doc.gno @@ -0,0 +1,59 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package strconv implements conversions to and from string representations +// of basic data types. +// +// # Numeric Conversions +// +// The most common numeric conversions are Atoi (string to int) and Itoa (int to string). +// +// i, err := strconv.Atoi("-42") +// s := strconv.Itoa(-42) +// +// These assume decimal and the Go int type. +// +// [ParseBool], [ParseFloat], [ParseInt], and [ParseUint] convert strings to values: +// +// b, err := strconv.ParseBool("true") +// f, err := strconv.ParseFloat("3.1415", 64) +// i, err := strconv.ParseInt("-42", 10, 64) +// u, err := strconv.ParseUint("42", 10, 64) +// +// The parse functions return the widest type (float64, int64, and uint64), +// but if the size argument specifies a narrower width the result can be +// converted to that narrower type without data loss: +// +// s := "2147483647" // biggest int32 +// i64, err := strconv.ParseInt(s, 10, 32) +// ... +// i := int32(i64) +// +// [FormatBool], [FormatFloat], [FormatInt], and [FormatUint] convert values to strings: +// +// s := strconv.FormatBool(true) +// s := strconv.FormatFloat(3.1415, 'E', -1, 64) +// s := strconv.FormatInt(-42, 16) +// s := strconv.FormatUint(42, 16) +// +// [AppendBool], [AppendFloat], [AppendInt], and [AppendUint] are similar but +// append the formatted value to a destination slice. +// +// # String Conversions +// +// [Quote] and [QuoteToASCII] convert strings to quoted Go string literals. +// The latter guarantees that the result is an ASCII string, by escaping +// any non-ASCII Unicode with \u: +// +// q := strconv.Quote("Hello, 世界") +// q := strconv.QuoteToASCII("Hello, 世界") +// +// [QuoteRune] and [QuoteRuneToASCII] are similar but accept runes and +// return quoted Go rune literals. +// +// [Unquote] and [UnquoteChar] unquote Go string and rune literals. +// +// XXX: Gno does not implement any of the functions from Go's strconv which +// pertain to complex numbers, such as FormatComplex and ParseComplex. +package strconv diff --git a/examples/gno.land/p/demo/json/eisel_lemire/eisel_lemire.gno b/gnovm/stdlibs/strconv/eisel_lemire.gno similarity index 93% rename from examples/gno.land/p/demo/json/eisel_lemire/eisel_lemire.gno rename to gnovm/stdlibs/strconv/eisel_lemire.gno index 6a29f7f1350..03842e50797 100644 --- a/examples/gno.land/p/demo/json/eisel_lemire/eisel_lemire.gno +++ b/gnovm/stdlibs/strconv/eisel_lemire.gno @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package eisel_lemire +package strconv // This file implements the Eisel-Lemire ParseFloat algorithm, published in // 2020 and discussed extensively at @@ -22,43 +22,17 @@ import ( "math/bits" ) -const ( - float32ExponentBias = 127 - float64ExponentBias = 1023 -) - -// eiselLemire64 parses a floating-point number from its mantissa and exponent representation. -// This implementation is based on the Eisel-Lemire ParseFloat algorithm, which is efficient -// and precise for converting strings to floating-point numbers. -// -// Arguments: -// man (uint64): The mantissa part of the floating-point number. -// exp10 (int): The exponent part, representing the power of 10. -// neg (bool): Indicates if the number is negative. -// -// Returns: -// f (float64): The parsed floating-point number. -// ok (bool): Indicates whether the parsing was successful. -// -// The function starts by handling special cases, such as zero mantissa. -// It then checks if the exponent is within the allowed range. -// After that, it normalizes the mantissa by left-shifting it to fill -// the leading zeros. This is followed by the main algorithm logic that -// converts the normalized mantissa and exponent into a 64-bit floating-point number. -// The function returns this number along with a boolean indicating the success of the operation. -func EiselLemire64(man uint64, exp10 int, neg bool) (f float64, ok bool) { +func eiselLemire64(man uint64, exp10 int, neg bool) (f float64, ok bool) { // The terse comments in this function body refer to sections of the // https://nigeltao.github.io/blog/2020/eisel-lemire.html blog post. // Exp10 Range. if man == 0 { if neg { - f = math.Float64frombits(0x80000000_00000000) // Negative zero. + f = math.Float64frombits(0x8000000000000000) // Negative zero. } - return f, true } - if exp10 < detailedPowersOfTenMinExp10 || detailedPowersOfTenMaxExp10 < exp10 { return 0, false } @@ -66,6 +40,7 @@ func EiselLemire64(man uint64, exp10 int, neg bool) (f float64, ok bool) { // Normalization. clz := bits.LeadingZeros64(man) man <<= uint(clz) + const float64ExponentBias = 1023 retExp2 := uint64(217706*exp10>>16+64+float64ExponentBias) - uint64(clz) // Multiplication. @@ -78,11 +53,9 @@ func EiselLemire64(man uint64, exp10 int, neg bool) (f float64, ok bool) { if mergedLo < xLo { mergedHi++ } - if mergedHi&0x1FF == 0x1FF && mergedLo+1 == 0 && yLo+man < man { return 0, false } - xHi, xLo = mergedHi, mergedLo } @@ -103,7 +76,6 @@ func EiselLemire64(man uint64, exp10 int, neg bool) (f float64, ok bool) { retMantissa >>= 1 retExp2 += 1 } - // retExp2 is a uint64. Zero or underflow means that we're in subnormal // float64 space. 0x7FF or above means that we're in Inf/NaN float64 space. // @@ -112,15 +84,88 @@ func EiselLemire64(man uint64, exp10 int, neg bool) (f float64, ok bool) { if retExp2-1 >= 0x7FF-1 { return 0, false } - - retBits := retExp2<<52 | retMantissa&0x000FFFFF_FFFFFFFF + retBits := retExp2<<52 | retMantissa&0x000FFFFFFFFFFFFF if neg { - retBits |= 0x80000000_00000000 + retBits |= 0x8000000000000000 } - return math.Float64frombits(retBits), true } +func eiselLemire32(man uint64, exp10 int, neg bool) (f float32, ok bool) { + // The terse comments in this function body refer to sections of the + // https://nigeltao.github.io/blog/2020/eisel-lemire.html blog post. + // + // That blog post discusses the float64 flavor (11 exponent bits with a + // -1023 bias, 52 mantissa bits) of the algorithm, but the same approach + // applies to the float32 flavor (8 exponent bits with a -127 bias, 23 + // mantissa bits). The computation here happens with 64-bit values (e.g. + // man, xHi, retMantissa) before finally converting to a 32-bit float. + + // Exp10 Range. + if man == 0 { + if neg { + f = math.Float32frombits(0x80000000) // Negative zero. + } + return f, true + } + if exp10 < detailedPowersOfTenMinExp10 || detailedPowersOfTenMaxExp10 < exp10 { + return 0, false + } + + // Normalization. + clz := bits.LeadingZeros64(man) + man <<= uint(clz) + const float32ExponentBias = 127 + retExp2 := uint64(217706*exp10>>16+64+float32ExponentBias) - uint64(clz) + + // Multiplication. + xHi, xLo := bits.Mul64(man, detailedPowersOfTen[exp10-detailedPowersOfTenMinExp10][1]) + + // Wider Approximation. + if xHi&0x3FFFFFFFFF == 0x3FFFFFFFFF && xLo+man < man { + yHi, yLo := bits.Mul64(man, detailedPowersOfTen[exp10-detailedPowersOfTenMinExp10][0]) + mergedHi, mergedLo := xHi, xLo+yHi + if mergedLo < xLo { + mergedHi++ + } + if mergedHi&0x3FFFFFFFFF == 0x3FFFFFFFFF && mergedLo+1 == 0 && yLo+man < man { + return 0, false + } + xHi, xLo = mergedHi, mergedLo + } + + // Shifting to 54 Bits (and for float32, it's shifting to 25 bits). + msb := xHi >> 63 + retMantissa := xHi >> (msb + 38) + retExp2 -= 1 ^ msb + + // Half-way Ambiguity. + if xLo == 0 && xHi&0x3FFFFFFFFF == 0 && retMantissa&3 == 1 { + return 0, false + } + + // From 54 to 53 Bits (and for float32, it's from 25 to 24 bits). + retMantissa += retMantissa & 1 + retMantissa >>= 1 + if retMantissa>>24 > 0 { + retMantissa >>= 1 + retExp2 += 1 + } + // retExp2 is a uint64. Zero or underflow means that we're in subnormal + // float32 space. 0xFF or above means that we're in Inf/NaN float32 space. + // + // The if block is equivalent to (but has fewer branches than): + // if retExp2 <= 0 || retExp2 >= 0xFF { etc } + if retExp2-1 >= 0xFF-1 { + return 0, false + } + retBits := retExp2<<23 | retMantissa&0x007FFFFF + if neg { + retBits |= 0x80000000 + } + return math.Float32frombits(uint32(retBits)), true +} + // detailedPowersOfTen{Min,Max}Exp10 is the power of 10 represented by the // first and last rows of detailedPowersOfTen. Both bounds are inclusive. const ( diff --git a/gnovm/stdlibs/strconv/example_test.gno b/gnovm/stdlibs/strconv/example_test.gno new file mode 100644 index 00000000000..428fde4e660 --- /dev/null +++ b/gnovm/stdlibs/strconv/example_test.gno @@ -0,0 +1,440 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package strconv_test + +import ( + "fmt" + "log" + "strconv" +) + +func ExampleAppendBool() { + b := []byte("bool:") + b = strconv.AppendBool(b, true) + fmt.Println(string(b)) + + // Output: + // bool:true +} + +func ExampleAppendFloat() { + b32 := []byte("float32:") + b32 = strconv.AppendFloat(b32, 3.1415926535, 'E', -1, 32) + fmt.Println(string(b32)) + + b64 := []byte("float64:") + b64 = strconv.AppendFloat(b64, 3.1415926535, 'E', -1, 64) + fmt.Println(string(b64)) + + // Output: + // float32:3.1415927E+00 + // float64:3.1415926535E+00 +} + +func ExampleAppendInt() { + b10 := []byte("int (base 10):") + b10 = strconv.AppendInt(b10, -42, 10) + fmt.Println(string(b10)) + + b16 := []byte("int (base 16):") + b16 = strconv.AppendInt(b16, -42, 16) + fmt.Println(string(b16)) + + // Output: + // int (base 10):-42 + // int (base 16):-2a +} + +func ExampleAppendQuote() { + b := []byte("quote:") + b = strconv.AppendQuote(b, `"Fran & Freddie's Diner"`) + fmt.Println(string(b)) + + // Output: + // quote:"\"Fran & Freddie's Diner\"" +} + +func ExampleAppendQuoteRune() { + b := []byte("rune:") + b = strconv.AppendQuoteRune(b, '☺') + fmt.Println(string(b)) + + // Output: + // rune:'☺' +} + +func ExampleAppendQuoteRuneToASCII() { + b := []byte("rune (ascii):") + b = strconv.AppendQuoteRuneToASCII(b, '☺') + fmt.Println(string(b)) + + // Output: + // rune (ascii):'\u263a' +} + +func ExampleAppendQuoteToASCII() { + b := []byte("quote (ascii):") + b = strconv.AppendQuoteToASCII(b, `"Fran & Freddie's Diner"`) + fmt.Println(string(b)) + + // Output: + // quote (ascii):"\"Fran & Freddie's Diner\"" +} + +func ExampleAppendUint() { + b10 := []byte("uint (base 10):") + b10 = strconv.AppendUint(b10, 42, 10) + fmt.Println(string(b10)) + + b16 := []byte("uint (base 16):") + b16 = strconv.AppendUint(b16, 42, 16) + fmt.Println(string(b16)) + + // Output: + // uint (base 10):42 + // uint (base 16):2a +} + +func ExampleAtoi() { + v := "10" + if s, err := strconv.Atoi(v); err == nil { + fmt.Printf("%T, %v", s, s) + } + + // Output: + // int, 10 +} + +func ExampleCanBackquote() { + fmt.Println(strconv.CanBackquote("Fran & Freddie's Diner ☺")) + fmt.Println(strconv.CanBackquote("`can't backquote this`")) + + // Output: + // true + // false +} + +func ExampleFormatBool() { + v := true + s := strconv.FormatBool(v) + fmt.Printf("%T, %v\n", s, s) + + // Output: + // string, true +} + +func ExampleFormatFloat() { + v := 3.1415926535 + + s32 := strconv.FormatFloat(v, 'E', -1, 32) + fmt.Printf("%T, %v\n", s32, s32) + + s64 := strconv.FormatFloat(v, 'E', -1, 64) + fmt.Printf("%T, %v\n", s64, s64) + + // fmt.Println uses these arguments to print floats + fmt64 := strconv.FormatFloat(v, 'g', -1, 64) + fmt.Printf("%T, %v\n", fmt64, fmt64) + + // Output: + // string, 3.1415927E+00 + // string, 3.1415926535E+00 + // string, 3.1415926535 +} + +func ExampleFormatInt() { + v := int64(-42) + + s10 := strconv.FormatInt(v, 10) + fmt.Printf("%T, %v\n", s10, s10) + + s16 := strconv.FormatInt(v, 16) + fmt.Printf("%T, %v\n", s16, s16) + + // Output: + // string, -42 + // string, -2a +} + +func ExampleFormatUint() { + v := uint64(42) + + s10 := strconv.FormatUint(v, 10) + fmt.Printf("%T, %v\n", s10, s10) + + s16 := strconv.FormatUint(v, 16) + fmt.Printf("%T, %v\n", s16, s16) + + // Output: + // string, 42 + // string, 2a +} + +func ExampleIsGraphic() { + shamrock := strconv.IsGraphic('☘') + fmt.Println(shamrock) + + a := strconv.IsGraphic('a') + fmt.Println(a) + + bel := strconv.IsGraphic('\007') + fmt.Println(bel) + + // Output: + // true + // true + // false +} + +func ExampleIsPrint() { + c := strconv.IsPrint('\u263a') + fmt.Println(c) + + bel := strconv.IsPrint('\007') + fmt.Println(bel) + + // Output: + // true + // false +} + +func ExampleItoa() { + i := 10 + s := strconv.Itoa(i) + fmt.Printf("%T, %v\n", s, s) + + // Output: + // string, 10 +} + +func ExampleParseBool() { + v := "true" + if s, err := strconv.ParseBool(v); err == nil { + fmt.Printf("%T, %v\n", s, s) + } + + // Output: + // bool, true +} + +func ExampleParseFloat() { + v := "3.1415926535" + if s, err := strconv.ParseFloat(v, 32); err == nil { + fmt.Printf("%T, %v\n", s, s) + } + if s, err := strconv.ParseFloat(v, 64); err == nil { + fmt.Printf("%T, %v\n", s, s) + } + if s, err := strconv.ParseFloat("NaN", 32); err == nil { + fmt.Printf("%T, %v\n", s, s) + } + // ParseFloat is case insensitive + if s, err := strconv.ParseFloat("nan", 32); err == nil { + fmt.Printf("%T, %v\n", s, s) + } + if s, err := strconv.ParseFloat("inf", 32); err == nil { + fmt.Printf("%T, %v\n", s, s) + } + if s, err := strconv.ParseFloat("+Inf", 32); err == nil { + fmt.Printf("%T, %v\n", s, s) + } + if s, err := strconv.ParseFloat("-Inf", 32); err == nil { + fmt.Printf("%T, %v\n", s, s) + } + if s, err := strconv.ParseFloat("-0", 32); err == nil { + fmt.Printf("%T, %v\n", s, s) + } + if s, err := strconv.ParseFloat("+0", 32); err == nil { + fmt.Printf("%T, %v\n", s, s) + } + + // Output: + // float64, 3.1415927410125732 + // float64, 3.1415926535 + // float64, NaN + // float64, NaN + // float64, +Inf + // float64, +Inf + // float64, -Inf + // float64, -0 + // float64, 0 +} + +func ExampleParseInt() { + v32 := "-354634382" + if s, err := strconv.ParseInt(v32, 10, 32); err == nil { + fmt.Printf("%T, %v\n", s, s) + } + if s, err := strconv.ParseInt(v32, 16, 32); err == nil { + fmt.Printf("%T, %v\n", s, s) + } + + v64 := "-3546343826724305832" + if s, err := strconv.ParseInt(v64, 10, 64); err == nil { + fmt.Printf("%T, %v\n", s, s) + } + if s, err := strconv.ParseInt(v64, 16, 64); err == nil { + fmt.Printf("%T, %v\n", s, s) + } + + // Output: + // int64, -354634382 + // int64, -3546343826724305832 +} + +func ExampleParseUint() { + v := "42" + if s, err := strconv.ParseUint(v, 10, 32); err == nil { + fmt.Printf("%T, %v\n", s, s) + } + if s, err := strconv.ParseUint(v, 10, 64); err == nil { + fmt.Printf("%T, %v\n", s, s) + } + + // Output: + // uint64, 42 + // uint64, 42 +} + +func ExampleQuote() { + // This string literal contains a tab character. + s := strconv.Quote(`"Fran & Freddie's Diner ☺"`) + fmt.Println(s) + + // Output: + // "\"Fran & Freddie's Diner\t☺\"" +} + +func ExampleQuoteRune() { + s := strconv.QuoteRune('☺') + fmt.Println(s) + + // Output: + // '☺' +} + +func ExampleQuoteRuneToASCII() { + s := strconv.QuoteRuneToASCII('☺') + fmt.Println(s) + + // Output: + // '\u263a' +} + +func ExampleQuoteRuneToGraphic() { + s := strconv.QuoteRuneToGraphic('☺') + fmt.Println(s) + + s = strconv.QuoteRuneToGraphic('\u263a') + fmt.Println(s) + + s = strconv.QuoteRuneToGraphic('\u000a') + fmt.Println(s) + + s = strconv.QuoteRuneToGraphic(' ') // tab character + fmt.Println(s) + + // Output: + // '☺' + // '☺' + // '\n' + // '\t' +} + +func ExampleQuoteToASCII() { + // This string literal contains a tab character. + s := strconv.QuoteToASCII(`"Fran & Freddie's Diner ☺"`) + fmt.Println(s) + + // Output: + // "\"Fran & Freddie's Diner\t\u263a\"" +} + +func ExampleQuoteToGraphic() { + s := strconv.QuoteToGraphic("☺") + fmt.Println(s) + + // This string literal contains a tab character. + s = strconv.QuoteToGraphic("This is a \u263a \u000a") + fmt.Println(s) + + s = strconv.QuoteToGraphic(`" This is a ☺ \n "`) + fmt.Println(s) + + // Output: + // "☺" + // "This is a ☺\t\n" + // "\" This is a ☺ \\n \"" +} + +func ExampleQuotedPrefix() { + s, err := strconv.QuotedPrefix("not a quoted string") + fmt.Printf("%q, %v\n", s, err) + s, err = strconv.QuotedPrefix("\"double-quoted string\" with trailing text") + fmt.Printf("%q, %v\n", s, err) + s, err = strconv.QuotedPrefix("`or backquoted` with more trailing text") + fmt.Printf("%q, %v\n", s, err) + s, err = strconv.QuotedPrefix("'\u263a' is also okay") + fmt.Printf("%q, %v\n", s, err) + + // Output: + // "", invalid syntax + // "\"double-quoted string\"", + // "`or backquoted`", + // "'☺'", +} + +func ExampleUnquote() { + s, err := strconv.Unquote("You can't unquote a string without quotes") + fmt.Printf("%q, %v\n", s, err) + s, err = strconv.Unquote("\"The string must be either double-quoted\"") + fmt.Printf("%q, %v\n", s, err) + s, err = strconv.Unquote("`or backquoted.`") + fmt.Printf("%q, %v\n", s, err) + s, err = strconv.Unquote("'\u263a'") // single character only allowed in single quotes + fmt.Printf("%q, %v\n", s, err) + s, err = strconv.Unquote("'\u2639\u2639'") + fmt.Printf("%q, %v\n", s, err) + + // Output: + // "", invalid syntax + // "The string must be either double-quoted", + // "or backquoted.", + // "☺", + // "", invalid syntax +} + +func ExampleUnquoteChar() { + v, mb, t, err := strconv.UnquoteChar(`\"Fran & Freddie's Diner\"`, '"') + if err != nil { + log.Fatal(err) + } + + fmt.Println("value:", string(v)) + fmt.Println("multibyte:", mb) + fmt.Println("tail:", t) + + // Output: + // value: " + // multibyte: false + // tail: Fran & Freddie's Diner\" +} + +func ExampleNumError() { + str := "Not a number" + if _, err := strconv.ParseFloat(str, 64); err != nil { + e := err.(*strconv.NumError) + fmt.Println("Func:", e.Func) + fmt.Println("Num:", e.Num) + fmt.Println("Err:", e.Err) + fmt.Println(err) + } + + // Output: + // Func: ParseFloat + // Num: Not a number + // Err: invalid syntax + // strconv.ParseFloat: parsing "Not a number": invalid syntax +} diff --git a/gnovm/stdlibs/strconv/export_test.gno b/gnovm/stdlibs/strconv/export_test.gno new file mode 100644 index 00000000000..8c03a7ffb4f --- /dev/null +++ b/gnovm/stdlibs/strconv/export_test.gno @@ -0,0 +1,10 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package strconv + +var ( + BitSizeError = bitSizeError + BaseError = baseError +) diff --git a/gnovm/stdlibs/strconv/fp_test.gno b/gnovm/stdlibs/strconv/fp_test.gno new file mode 100644 index 00000000000..76cc95663c4 --- /dev/null +++ b/gnovm/stdlibs/strconv/fp_test.gno @@ -0,0 +1,320 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package strconv_test + +import ( + "bufio" + "fmt" + "strconv" + "strings" + "testing" +) + +func pow2(i int) float64 { + switch { + case i < 0: + return 1 / pow2(-i) + case i == 0: + return 1 + case i == 1: + return 2 + } + return pow2(i/2) * pow2(i-i/2) +} + +// Wrapper around strconv.ParseFloat(x, 64). Handles dddddp+ddd (binary exponent) +// itself, passes the rest on to strconv.ParseFloat. +func myatof64(s string) (f float64, ok bool) { + if mant, exp, ok := strings.Cut(s, "p"); ok { + n, err := strconv.ParseInt(mant, 10, 64) + if err != nil { + return 0, false + } + e, err1 := strconv.Atoi(exp) + if err1 != nil { + println("bad e", exp) + return 0, false + } + v := float64(n) + // We expect that v*pow2(e) fits in a float64, + // but pow2(e) by itself may not. Be careful. + if e <= -1000 { + v *= pow2(-1000) + e += 1000 + for e < 0 { + v /= 2 + e++ + } + return v, true + } + if e >= 1000 { + v *= pow2(1000) + e -= 1000 + for e > 0 { + v *= 2 + e-- + } + return v, true + } + return v * pow2(e), true + } + f1, err := strconv.ParseFloat(s, 64) + if err != nil { + return 0, false + } + return f1, true +} + +// Wrapper around strconv.ParseFloat(x, 32). Handles dddddp+ddd (binary exponent) +// itself, passes the rest on to strconv.ParseFloat. +func myatof32(s string) (f float32, ok bool) { + if mant, exp, ok := strings.Cut(s, "p"); ok { + n, err := strconv.Atoi(mant) + if err != nil { + println("bad n", mant) + return 0, false + } + e, err1 := strconv.Atoi(exp) + if err1 != nil { + println("bad p", exp) + return 0, false + } + return float32(float64(n) * pow2(e)), true + } + f64, err1 := strconv.ParseFloat(s, 32) + f1 := float32(f64) + if err1 != nil { + return 0, false + } + return f1, true +} + +// XXX: copied from go source src/strconv/testdata/testfp.txt +// to avoid using os.Open in our tests +const testfp = `# Floating-point conversion test cases. +# Empty lines and lines beginning with # are ignored. +# The rest have four fields per line: type, format, input, and output. +# The input is given either in decimal or binary scientific notation. +# The output is the string that should be produced by formatting the +# input with the given format. +# +# The formats are as in C's printf, except that %b means print +# binary scientific notation: NpE = N x 2^E. + +# TODO: +# Powers of 10. +# Powers of 2. +# %.20g versions. +# random sources +# random targets +# random targets ± half a ULP + +# Difficult boundary cases, derived from tables given in +# Vern Paxson, A Program for Testing IEEE Decimal-Binary Conversion +# ftp://ftp.ee.lbl.gov/testbase-report.ps.Z + +# Table 1: Stress Inputs for Conversion to 53-bit Binary, < 1/2 ULP +float64 %b 5e+125 6653062250012735p+365 +float64 %b 69e+267 4705683757438170p+841 +float64 %b 999e-026 6798841691080350p-129 +float64 %b 7861e-034 8975675289889240p-153 +float64 %b 75569e-254 6091718967192243p-880 +float64 %b 928609e-261 7849264900213743p-900 +float64 %b 9210917e+080 8341110837370930p+236 +float64 %b 84863171e+114 4625202867375927p+353 +float64 %b 653777767e+273 5068902999763073p+884 +float64 %b 5232604057e-298 5741343011915040p-1010 +float64 %b 27235667517e-109 6707124626673586p-380 +float64 %b 653532977297e-123 7078246407265384p-422 +float64 %b 3142213164987e-294 8219991337640559p-988 +float64 %b 46202199371337e-072 5224462102115359p-246 +float64 %b 231010996856685e-073 5224462102115359p-247 +float64 %b 9324754620109615e+212 5539753864394442p+705 +float64 %b 78459735791271921e+049 8388176519442766p+166 +float64 %b 272104041512242479e+200 5554409530847367p+670 +float64 %b 6802601037806061975e+198 5554409530847367p+668 +float64 %b 20505426358836677347e-221 4524032052079546p-722 +float64 %b 836168422905420598437e-234 5070963299887562p-760 +float64 %b 4891559871276714924261e+222 6452687840519111p+757 + +# Table 2: Stress Inputs for Conversion to 53-bit Binary, > 1/2 ULP +float64 %b 9e-265 8168427841980010p-930 +float64 %b 85e-037 6360455125664090p-169 +float64 %b 623e+100 6263531988747231p+289 +float64 %b 3571e+263 6234526311072170p+833 +float64 %b 81661e+153 6696636728760206p+472 +float64 %b 920657e-023 5975405561110124p-109 +float64 %b 4603285e-024 5975405561110124p-110 +float64 %b 87575437e-309 8452160731874668p-1053 +float64 %b 245540327e+122 4985336549131723p+381 +float64 %b 6138508175e+120 4985336549131723p+379 +float64 %b 83356057653e+193 5986732817132056p+625 +float64 %b 619534293513e+124 4798406992060657p+399 +float64 %b 2335141086879e+218 5419088166961646p+713 +float64 %b 36167929443327e-159 8135819834632444p-536 +float64 %b 609610927149051e-255 4576664294594737p-850 +float64 %b 3743626360493413e-165 6898586531774201p-549 +float64 %b 94080055902682397e-242 6273271706052298p-800 +float64 %b 899810892172646163e+283 7563892574477827p+947 +float64 %b 7120190517612959703e+120 5385467232557565p+409 +float64 %b 25188282901709339043e-252 5635662608542340p-825 +float64 %b 308984926168550152811e-052 5644774693823803p-157 +float64 %b 6372891218502368041059e+064 4616868614322430p+233 + +# Table 3: Stress Inputs for Converting 53-bit Binary to Decimal, < 1/2 ULP +float64 %.0e 8511030020275656p-342 9e-88 +float64 %.1e 5201988407066741p-824 4.6e-233 +float64 %.2e 6406892948269899p+237 1.41e+87 +float64 %.3e 8431154198732492p+72 3.981e+37 +float64 %.4e 6475049196144587p+99 4.1040e+45 +float64 %.5e 8274307542972842p+726 2.92084e+234 +float64 %.6e 5381065484265332p-456 2.891946e-122 +float64 %.7e 6761728585499734p-1057 4.3787718e-303 +float64 %.8e 7976538478610756p+376 1.22770163e+129 +float64 %.9e 5982403858958067p+377 1.841552452e+129 +float64 %.10e 5536995190630837p+93 5.4835744350e+43 +float64 %.11e 7225450889282194p+710 3.89190181146e+229 +float64 %.12e 7225450889282194p+709 1.945950905732e+229 +float64 %.13e 8703372741147379p+117 1.4460958381605e+51 +float64 %.14e 8944262675275217p-1001 4.17367747458531e-286 +float64 %.15e 7459803696087692p-707 1.107950772878888e-197 +float64 %.16e 6080469016670379p-381 1.2345501366327440e-99 +float64 %.17e 8385515147034757p+721 9.25031711960365024e+232 +float64 %.18e 7514216811389786p-828 4.198047150284889840e-234 +float64 %.19e 8397297803260511p-345 1.1716315319786511046e-88 +float64 %.20e 6733459239310543p+202 4.32810072844612493629e+76 +float64 %.21e 8091450587292794p-473 3.317710118160031081518e-127 + +# Table 4: Stress Inputs for Converting 53-bit Binary to Decimal, > 1/2 ULP +float64 %.0e 6567258882077402p+952 3e+302 +float64 %.1e 6712731423444934p+535 7.6e+176 +float64 %.2e 6712731423444934p+534 3.78e+176 +float64 %.3e 5298405411573037p-957 4.350e-273 +float64 %.4e 5137311167659507p-144 2.3037e-28 +float64 %.5e 6722280709661868p+363 1.26301e+125 +float64 %.6e 5344436398034927p-169 7.142211e-36 +float64 %.7e 8369123604277281p-853 1.3934574e-241 +float64 %.8e 8995822108487663p-780 1.41463449e-219 +float64 %.9e 8942832835564782p-383 4.539277920e-100 +float64 %.10e 8942832835564782p-384 2.2696389598e-100 +float64 %.11e 8942832835564782p-385 1.13481947988e-100 +float64 %.12e 6965949469487146p-249 7.700366561890e-60 +float64 %.13e 6965949469487146p-250 3.8501832809448e-60 +float64 %.14e 6965949469487146p-251 1.92509164047238e-60 +float64 %.15e 7487252720986826p+548 6.898586531774201e+180 +float64 %.16e 5592117679628511p+164 1.3076622631878654e+65 +float64 %.17e 8887055249355788p+665 1.36052020756121240e+216 +float64 %.18e 6994187472632449p+690 3.592810217475959676e+223 +float64 %.19e 8797576579012143p+588 8.9125197712484551899e+192 +float64 %.20e 7363326733505337p+272 5.58769757362301140950e+97 +float64 %.21e 8549497411294502p-448 1.176257830728540379990e-119 + +# Table 14: Stress Inputs for Conversion to 24-bit Binary, <1/2 ULP +# NOTE: The lines with exponent p-149 have been changed from the +# paper. Those entries originally read p-150 and had a mantissa +# twice as large (and even), but IEEE single-precision has no p-150: +# that's the start of the denormals. +float32 %b 5e-20 15474250p-88 +float32 %b 67e+14 12479722p+29 +float32 %b 985e+15 14333636p+36 +# float32 %b 7693e-42 10979816p-150 +float32 %b 7693e-42 5489908p-149 +float32 %b 55895e-16 12888509p-61 +# float32 %b 996622e-44 14224264p-150 +float32 %b 996622e-44 7112132p-149 +float32 %b 7038531e-32 11420669p-107 +# float32 %b 60419369e-46 8623340p-150 +float32 %b 60419369e-46 4311670p-149 +float32 %b 702990899e-20 16209866p-61 +# float32 %b 6930161142e-48 9891056p-150 +float32 %b 6930161142e-48 4945528p-149 +float32 %b 25933168707e+13 14395800p+54 +float32 %b 596428896559e+20 12333860p+82 + +# Table 15: Stress Inputs for Conversion to 24-bit Binary, >1/2 ULP +float32 %b 3e-23 9507380p-98 +float32 %b 57e+18 12960300p+42 +float32 %b 789e-35 10739312p-130 +float32 %b 2539e-18 11990089p-72 +float32 %b 76173e+28 9845130p+86 +float32 %b 887745e-11 9760860p-40 +float32 %b 5382571e-37 11447463p-124 +float32 %b 82381273e-35 8554961p-113 +float32 %b 750486563e-38 9975678p-120 +float32 %b 3752432815e-39 9975678p-121 +float32 %b 75224575729e-45 13105970p-137 +float32 %b 459926601011e+15 12466336p+65 + +# Table 16: Stress Inputs for Converting 24-bit Binary to Decimal, < 1/2 ULP +float32 %.0e 12676506p-102 2e-24 +float32 %.1e 12676506p-103 1.2e-24 +float32 %.2e 15445013p+86 1.19e+33 +float32 %.3e 13734123p-138 3.941e-35 +float32 %.4e 12428269p-130 9.1308e-33 +float32 %.5e 15334037p-146 1.71900e-37 +float32 %.6e 11518287p-41 5.237910e-06 +float32 %.7e 12584953p-145 2.8216440e-37 +float32 %.8e 15961084p-125 3.75243281e-31 +float32 %.9e 14915817p-146 1.672120916e-37 +float32 %.10e 10845484p-102 2.1388945814e-24 +float32 %.11e 16431059p-61 7.12583594561e-12 + +# Table 17: Stress Inputs for Converting 24-bit Binary to Decimal, > 1/2 ULP +float32 %.0e 16093626p+69 1e+28 +float32 %.1e 9983778p+25 3.4e+14 +float32 %.2e 12745034p+104 2.59e+38 +float32 %.3e 12706553p+72 6.001e+28 +float32 %.4e 11005028p+45 3.8721e+20 +float32 %.5e 15059547p+71 3.55584e+28 +float32 %.6e 16015691p-99 2.526831e-23 +float32 %.7e 8667859p+56 6.2458507e+23 +float32 %.8e 14855922p-82 3.07213267e-18 +float32 %.9e 14855922p-83 1.536066333e-18 +float32 %.10e 10144164p-110 7.8147796834e-27 +float32 %.11e 13248074p+95 5.24810279937e+35 +` + +func TestFp(t *testing.T) { + s := bufio.NewScanner(strings.NewReader(testfp)) + + for lineno := 1; s.Scan(); lineno++ { + line := s.Text() + if len(line) == 0 || line[0] == '#' { + continue + } + a := strings.Split(line, " ") + if len(a) != 4 { + t.Error("testdata/testfp.txt:", lineno, ": wrong field count") + continue + } + var s string + var v float64 + switch a[0] { + case "float64": + var ok bool + v, ok = myatof64(a[2]) + if !ok { + t.Error("testdata/testfp.txt:", lineno, ": cannot atof64 ", a[2]) + continue + } + s = fmt.Sprintf(a[1], v) + case "float32": + v1, ok := myatof32(a[2]) + if !ok { + t.Error("testdata/testfp.txt:", lineno, ": cannot atof32 ", a[2]) + continue + } + s = fmt.Sprintf(a[1], v1) + v = float64(v1) + } + if s != a[3] { + t.Error("testdata/testfp.txt:", lineno, ": ", a[0], " ", a[1], " ", a[2], " (", v, ") ", + "want ", a[3], " got ", s) + } + } + if s.Err() != nil { + t.Fatal("testfp: read testdata/testfp.txt: ", s.Err()) + } +} diff --git a/gnovm/stdlibs/strconv/ftoa.gno b/gnovm/stdlibs/strconv/ftoa.gno new file mode 100644 index 00000000000..fcbf4df13b6 --- /dev/null +++ b/gnovm/stdlibs/strconv/ftoa.gno @@ -0,0 +1,584 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Binary to decimal floating point conversion. +// Algorithm: +// 1) store mantissa in multiprecision decimal +// 2) shift decimal by exponent +// 3) read digits out & format + +package strconv + +import "math" + +// TODO: move elsewhere? +type floatInfo struct { + mantbits uint + expbits uint + bias int +} + +var float32info = floatInfo{23, 8, -127} +var float64info = floatInfo{52, 11, -1023} + +// FormatFloat converts the floating-point number f to a string, +// according to the format fmt and precision prec. It rounds the +// result assuming that the original was obtained from a floating-point +// value of bitSize bits (32 for float32, 64 for float64). +// +// The format fmt is one of +// 'b' (-ddddp±ddd, a binary exponent), +// 'e' (-d.dddde±dd, a decimal exponent), +// 'E' (-d.ddddE±dd, a decimal exponent), +// 'f' (-ddd.dddd, no exponent), +// 'g' ('e' for large exponents, 'f' otherwise), +// 'G' ('E' for large exponents, 'f' otherwise), +// 'x' (-0xd.ddddp±ddd, a hexadecimal fraction and binary exponent), or +// 'X' (-0Xd.ddddP±ddd, a hexadecimal fraction and binary exponent). +// +// The precision prec controls the number of digits (excluding the exponent) +// printed by the 'e', 'E', 'f', 'g', 'G', 'x', and 'X' formats. +// For 'e', 'E', 'f', 'x', and 'X', it is the number of digits after the decimal point. +// For 'g' and 'G' it is the maximum number of significant digits (trailing +// zeros are removed). +// The special precision -1 uses the smallest number of digits +// necessary such that ParseFloat will return f exactly. +func FormatFloat(f float64, fmt byte, prec, bitSize int) string { + return string(genericFtoa(make([]byte, 0, max(prec+4, 24)), f, fmt, prec, bitSize)) +} + +// AppendFloat appends the string form of the floating-point number f, +// as generated by FormatFloat, to dst and returns the extended buffer. +func AppendFloat(dst []byte, f float64, fmt byte, prec, bitSize int) []byte { + return genericFtoa(dst, f, fmt, prec, bitSize) +} + +func genericFtoa(dst []byte, val float64, fmt byte, prec, bitSize int) []byte { + var bits uint64 + var flt *floatInfo + switch bitSize { + case 32: + bits = uint64(math.Float32bits(float32(val))) + flt = &float32info + case 64: + bits = math.Float64bits(val) + flt = &float64info + default: + panic("strconv: illegal AppendFloat/FormatFloat bitSize") + } + + neg := bits>>(flt.expbits+flt.mantbits) != 0 + exp := int(bits>>flt.mantbits) & (1< digs.nd && digs.nd >= digs.dp { + eprec = digs.nd + } + // %e is used if the exponent from the conversion + // is less than -4 or greater than or equal to the precision. + // if precision was the shortest possible, use precision 6 for this decision. + if shortest { + eprec = 6 + } + exp := digs.dp - 1 + if exp < -4 || exp >= eprec { + if prec > digs.nd { + prec = digs.nd + } + return fmtE(dst, neg, digs, prec-1, fmt+'e'-'g') + } + if prec > digs.dp { + prec = digs.nd + } + return fmtF(dst, neg, digs, max(prec-digs.dp, 0)) + } + + // unknown format + return append(dst, '%', fmt) +} + +// roundShortest rounds d (= mant * 2^exp) to the shortest number of digits +// that will let the original floating point value be precisely reconstructed. +func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) { + // If mantissa is zero, the number is zero; stop now. + if mant == 0 { + d.nd = 0 + return + } + + // Compute upper and lower such that any decimal number + // between upper and lower (possibly inclusive) + // will round to the original floating point number. + + // We may see at once that the number is already shortest. + // + // Suppose d is not denormal, so that 2^exp <= d < 10^dp. + // The closest shorter number is at least 10^(dp-nd) away. + // The lower/upper bounds computed below are at distance + // at most 2^(exp-mantbits). + // + // So the number is already shortest if 10^(dp-nd) > 2^(exp-mantbits), + // or equivalently log2(10)*(dp-nd) > exp-mantbits. + // It is true if 332/100*(dp-nd) >= exp-mantbits (log2(10) > 3.32). + minexp := flt.bias + 1 // minimum possible exponent + if exp > minexp && 332*(d.dp-d.nd) >= 100*(exp-int(flt.mantbits)) { + // The number is already shortest. + return + } + + // d = mant << (exp - mantbits) + // Next highest floating point number is mant+1 << exp-mantbits. + // Our upper bound is halfway between, mant*2+1 << exp-mantbits-1. + upper := new(decimal) + upper.Assign(mant*2 + 1) + upper.Shift(exp - int(flt.mantbits) - 1) + + // d = mant << (exp - mantbits) + // Next lowest floating point number is mant-1 << exp-mantbits, + // unless mant-1 drops the significant bit and exp is not the minimum exp, + // in which case the next lowest is mant*2-1 << exp-mantbits-1. + // Either way, call it mantlo << explo-mantbits. + // Our lower bound is halfway between, mantlo*2+1 << explo-mantbits-1. + var mantlo uint64 + var explo int + if mant > 1<= d.nd { + break + } + li := ui - upper.dp + lower.dp + l := byte('0') // lower digit + if li >= 0 && li < lower.nd { + l = lower.d[li] + } + m := byte('0') // middle digit + if mi >= 0 { + m = d.d[mi] + } + u := byte('0') // upper digit + if ui < upper.nd { + u = upper.d[ui] + } + + // Okay to round down (truncate) if lower has a different digit + // or if lower is inclusive and is exactly the result of rounding + // down (i.e., and we have reached the final digit of lower). + okdown := l != m || inclusive && li+1 == lower.nd + + switch { + case upperdelta == 0 && m+1 < u: + // Example: + // m = 12345xxx + // u = 12347xxx + upperdelta = 2 + case upperdelta == 0 && m != u: + // Example: + // m = 12345xxx + // u = 12346xxx + upperdelta = 1 + case upperdelta == 1 && (m != '9' || u != '0'): + // Example: + // m = 1234598x + // u = 1234600x + upperdelta = 2 + } + // Okay to round up if upper has a different digit and either upper + // is inclusive or upper is bigger than the result of rounding up. + okup := upperdelta > 0 && (inclusive || upperdelta > 1 || ui+1 < upper.nd) + + // If it's okay to do either, then round to the nearest one. + // If it's okay to do only one, do it. + switch { + case okdown && okup: + d.Round(mi + 1) + return + case okdown: + d.RoundDown(mi + 1) + return + case okup: + d.RoundUp(mi + 1) + return + } + } +} + +type decimalSlice struct { + d []byte + nd, dp int +} + +// %e: -d.ddddde±dd +func fmtE(dst []byte, neg bool, d decimalSlice, prec int, fmt byte) []byte { + // sign + if neg { + dst = append(dst, '-') + } + + // first digit + ch := byte('0') + if d.nd != 0 { + ch = d.d[0] + } + dst = append(dst, ch) + + // .moredigits + if prec > 0 { + dst = append(dst, '.') + i := 1 + m := min(d.nd, prec+1) + if i < m { + dst = append(dst, d.d[i:m]...) + i = m + } + for ; i <= prec; i++ { + dst = append(dst, '0') + } + } + + // e± + dst = append(dst, fmt) + exp := d.dp - 1 + if d.nd == 0 { // special case: 0 has exponent 0 + exp = 0 + } + if exp < 0 { + ch = '-' + exp = -exp + } else { + ch = '+' + } + dst = append(dst, ch) + + // dd or ddd + switch { + case exp < 10: + dst = append(dst, '0', byte(exp)+'0') + case exp < 100: + dst = append(dst, byte(exp/10)+'0', byte(exp%10)+'0') + default: + dst = append(dst, byte(exp/100)+'0', byte(exp/10)%10+'0', byte(exp%10)+'0') + } + + return dst +} + +// %f: -ddddddd.ddddd +func fmtF(dst []byte, neg bool, d decimalSlice, prec int) []byte { + // sign + if neg { + dst = append(dst, '-') + } + + // integer, padded with zeros as needed. + if d.dp > 0 { + m := min(d.nd, d.dp) + dst = append(dst, d.d[:m]...) + for ; m < d.dp; m++ { + dst = append(dst, '0') + } + } else { + dst = append(dst, '0') + } + + // fraction + if prec > 0 { + dst = append(dst, '.') + for i := 0; i < prec; i++ { + ch := byte('0') + if j := d.dp + i; 0 <= j && j < d.nd { + ch = d.d[j] + } + dst = append(dst, ch) + } + } + + return dst +} + +// %b: -ddddddddp±ddd +func fmtB(dst []byte, neg bool, mant uint64, exp int, flt *floatInfo) []byte { + // sign + if neg { + dst = append(dst, '-') + } + + // mantissa + dst, _ = formatBits(dst, mant, 10, false, true) + + // p + dst = append(dst, 'p') + + // ±exponent + exp -= int(flt.mantbits) + if exp >= 0 { + dst = append(dst, '+') + } + dst, _ = formatBits(dst, uint64(exp), 10, exp < 0, true) + + return dst +} + +// %x: -0x1.yyyyyyyyp±ddd or -0x0p+0. (y is hex digit, d is decimal digit) +func fmtX(dst []byte, prec int, fmt byte, neg bool, mant uint64, exp int, flt *floatInfo) []byte { + if mant == 0 { + exp = 0 + } + + // Shift digits so leading 1 (if any) is at bit 1<<60. + mant <<= 60 - flt.mantbits + for mant != 0 && mant&(1<<60) == 0 { + mant <<= 1 + exp-- + } + + // Round if requested. + if prec >= 0 && prec < 15 { + shift := uint(prec * 4) + extra := (mant << shift) & (1<<60 - 1) + mant >>= 60 - shift + if extra|(mant&1) > 1<<59 { + mant++ + } + mant <<= 60 - shift + if mant&(1<<61) != 0 { + // Wrapped around. + mant >>= 1 + exp++ + } + } + + hex := lowerhex + if fmt == 'X' { + hex = upperhex + } + + // sign, 0x, leading digit + if neg { + dst = append(dst, '-') + } + dst = append(dst, '0', fmt, '0'+byte((mant>>60)&1)) + + // .fraction + mant <<= 4 // remove leading 0 or 1 + if prec < 0 && mant != 0 { + dst = append(dst, '.') + for mant != 0 { + dst = append(dst, hex[(mant>>60)&15]) + mant <<= 4 + } + } else if prec > 0 { + dst = append(dst, '.') + for i := 0; i < prec; i++ { + dst = append(dst, hex[(mant>>60)&15]) + mant <<= 4 + } + } + + // p± + ch := byte('P') + if fmt == lower(fmt) { + ch = 'p' + } + dst = append(dst, ch) + if exp < 0 { + ch = '-' + exp = -exp + } else { + ch = '+' + } + dst = append(dst, ch) + + // dd or ddd or dddd + switch { + case exp < 100: + dst = append(dst, byte(exp/10)+'0', byte(exp%10)+'0') + case exp < 1000: + dst = append(dst, byte(exp/100)+'0', byte((exp/10)%10)+'0', byte(exp%10)+'0') + default: + dst = append(dst, byte(exp/1000)+'0', byte(exp/100)%10+'0', byte((exp/10)%10)+'0', byte(exp%10)+'0') + } + + return dst +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} diff --git a/gnovm/stdlibs/strconv/ftoa_test.gno b/gnovm/stdlibs/strconv/ftoa_test.gno new file mode 100644 index 00000000000..df1cc733827 --- /dev/null +++ b/gnovm/stdlibs/strconv/ftoa_test.gno @@ -0,0 +1,323 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package strconv + +import ( + "math" + "math/rand" + "testing" +) + +type ftoaTest struct { + f float64 + fmt byte + prec int + s string +} + +func fdiv(a, b float64) float64 { return a / b } + +const ( + below1e23 = 99999999999999974834176 + above1e23 = 100000000000000008388608 +) + +var ftoatests = []ftoaTest{ + {1, 'e', 5, "1.00000e+00"}, + {1, 'f', 5, "1.00000"}, + {1, 'g', 5, "1"}, + {1, 'g', -1, "1"}, + {1, 'x', -1, "0x1p+00"}, + {1, 'x', 5, "0x1.00000p+00"}, + {20, 'g', -1, "20"}, + {20, 'x', -1, "0x1.4p+04"}, + {1234567.8, 'g', -1, "1.2345678e+06"}, + {1234567.8, 'x', -1, "0x1.2d687cccccccdp+20"}, + {200000, 'g', -1, "200000"}, + {200000, 'x', -1, "0x1.86ap+17"}, + {200000, 'X', -1, "0X1.86AP+17"}, + {2000000, 'g', -1, "2e+06"}, + {1e10, 'g', -1, "1e+10"}, + + // g conversion and zero suppression + {400, 'g', 2, "4e+02"}, + {40, 'g', 2, "40"}, + {4, 'g', 2, "4"}, + {.4, 'g', 2, "0.4"}, + {.04, 'g', 2, "0.04"}, + {.004, 'g', 2, "0.004"}, + {.0004, 'g', 2, "0.0004"}, + {.00004, 'g', 2, "4e-05"}, + {.000004, 'g', 2, "4e-06"}, + + {0, 'e', 5, "0.00000e+00"}, + {0, 'f', 5, "0.00000"}, + {0, 'g', 5, "0"}, + {0, 'g', -1, "0"}, + {0, 'x', 5, "0x0.00000p+00"}, + + {-1, 'e', 5, "-1.00000e+00"}, + {-1, 'f', 5, "-1.00000"}, + {-1, 'g', 5, "-1"}, + {-1, 'g', -1, "-1"}, + + {12, 'e', 5, "1.20000e+01"}, + {12, 'f', 5, "12.00000"}, + {12, 'g', 5, "12"}, + {12, 'g', -1, "12"}, + + {123456700, 'e', 5, "1.23457e+08"}, + {123456700, 'f', 5, "123456700.00000"}, + {123456700, 'g', 5, "1.2346e+08"}, + {123456700, 'g', -1, "1.234567e+08"}, + + {1.2345e6, 'e', 5, "1.23450e+06"}, + {1.2345e6, 'f', 5, "1234500.00000"}, + {1.2345e6, 'g', 5, "1.2345e+06"}, + + // Round to even + {1.2345e6, 'e', 3, "1.234e+06"}, + {1.2355e6, 'e', 3, "1.236e+06"}, + {1.2345, 'f', 3, "1.234"}, + {1.2355, 'f', 3, "1.236"}, + {1234567890123456.5, 'e', 15, "1.234567890123456e+15"}, + {1234567890123457.5, 'e', 15, "1.234567890123458e+15"}, + {108678236358137.625, 'g', -1, "1.0867823635813762e+14"}, + + {1e23, 'e', 17, "9.99999999999999916e+22"}, + {1e23, 'f', 17, "99999999999999991611392.00000000000000000"}, + {1e23, 'g', 17, "9.9999999999999992e+22"}, + + {1e23, 'e', -1, "1e+23"}, + {1e23, 'f', -1, "100000000000000000000000"}, + {1e23, 'g', -1, "1e+23"}, + + {below1e23, 'e', 17, "9.99999999999999748e+22"}, + {below1e23, 'f', 17, "99999999999999974834176.00000000000000000"}, + {below1e23, 'g', 17, "9.9999999999999975e+22"}, + + {below1e23, 'e', -1, "9.999999999999997e+22"}, + {below1e23, 'f', -1, "99999999999999970000000"}, + {below1e23, 'g', -1, "9.999999999999997e+22"}, + + {above1e23, 'e', 17, "1.00000000000000008e+23"}, + {above1e23, 'f', 17, "100000000000000008388608.00000000000000000"}, + {above1e23, 'g', 17, "1.0000000000000001e+23"}, + + {above1e23, 'e', -1, "1.0000000000000001e+23"}, + {above1e23, 'f', -1, "100000000000000010000000"}, + {above1e23, 'g', -1, "1.0000000000000001e+23"}, + + {fdiv(5e-304, 1e20), 'g', -1, "5e-324"}, // avoid constant arithmetic + {fdiv(-5e-304, 1e20), 'g', -1, "-5e-324"}, // avoid constant arithmetic + + {32, 'g', -1, "32"}, + {32, 'g', 0, "3e+01"}, + + {100, 'x', -1, "0x1.9p+06"}, + {100, 'y', -1, "%y"}, + + {math.NaN(), 'g', -1, "NaN"}, + {-math.NaN(), 'g', -1, "NaN"}, + {math.Inf(0), 'g', -1, "+Inf"}, + {math.Inf(-1), 'g', -1, "-Inf"}, + {-math.Inf(0), 'g', -1, "-Inf"}, + + {-1, 'b', -1, "-4503599627370496p-52"}, + + // fixed bugs + {0.9, 'f', 1, "0.9"}, + {0.09, 'f', 1, "0.1"}, + {0.0999, 'f', 1, "0.1"}, + {0.05, 'f', 1, "0.1"}, + {0.05, 'f', 0, "0"}, + {0.5, 'f', 1, "0.5"}, + {0.5, 'f', 0, "0"}, + {1.5, 'f', 0, "2"}, + + // https://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/ + {2.2250738585072012e-308, 'g', -1, "2.2250738585072014e-308"}, + // https://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/ + {2.2250738585072011e-308, 'g', -1, "2.225073858507201e-308"}, + + // Issue 2625. + {383260575764816448, 'f', 0, "383260575764816448"}, + {383260575764816448, 'g', -1, "3.8326057576481645e+17"}, + + // Issue 29491. + {498484681984085570, 'f', -1, "498484681984085570"}, + {-5.8339553793802237e+23, 'g', -1, "-5.8339553793802237e+23"}, + + // Issue 52187 + {123.45, '?', 0, "%?"}, + {123.45, '?', 1, "%?"}, + {123.45, '?', -1, "%?"}, + + // rounding + {2.275555555555555, 'x', -1, "0x1.23456789abcdep+01"}, + {2.275555555555555, 'x', 0, "0x1p+01"}, + {2.275555555555555, 'x', 2, "0x1.23p+01"}, + {2.275555555555555, 'x', 16, "0x1.23456789abcde000p+01"}, + {2.275555555555555, 'x', 21, "0x1.23456789abcde00000000p+01"}, + {2.2755555510520935, 'x', -1, "0x1.2345678p+01"}, + {2.2755555510520935, 'x', 6, "0x1.234568p+01"}, + {2.275555431842804, 'x', -1, "0x1.2345668p+01"}, + {2.275555431842804, 'x', 6, "0x1.234566p+01"}, + {3.999969482421875, 'x', -1, "0x1.ffffp+01"}, + {3.999969482421875, 'x', 4, "0x1.ffffp+01"}, + {3.999969482421875, 'x', 3, "0x1.000p+02"}, + {3.999969482421875, 'x', 2, "0x1.00p+02"}, + {3.999969482421875, 'x', 1, "0x1.0p+02"}, + {3.999969482421875, 'x', 0, "0x1p+02"}, +} + +func TestFtoa(t *testing.T) { + for i := 0; i < len(ftoatests); i++ { + test := &ftoatests[i] + s := FormatFloat(test.f, test.fmt, test.prec, 64) + if s != test.s { + t.Error("testN=64", test.f, string(test.fmt), test.prec, "want", test.s, "got", s) + } + x := AppendFloat([]byte("abc"), test.f, test.fmt, test.prec, 64) + if string(x) != "abc"+test.s { + t.Error("AppendFloat testN=64", test.f, string(test.fmt), test.prec, "want", "abc"+test.s, "got", string(x)) + } + if float64(float32(test.f)) == test.f && test.fmt != 'b' { + s := FormatFloat(test.f, test.fmt, test.prec, 32) + if s != test.s { + t.Error("testN=32", test.f, string(test.fmt), test.prec, "want", test.s, "got", s) + } + x := AppendFloat([]byte("abc"), test.f, test.fmt, test.prec, 32) + if string(x) != "abc"+test.s { + t.Error("AppendFloat testN=32", test.f, string(test.fmt), test.prec, "want", "abc"+test.s, "got", string(x)) + } + } + } +} + +func TestFtoaPowersOfTwo(t *testing.T) { + for exp := -2048; exp <= 2048; exp++ { + f := math.Ldexp(1, exp) + if !math.IsInf(f, 0) { + s := FormatFloat(f, 'e', -1, 64) + if x, _ := ParseFloat(s, 64); x != f { + t.Errorf("failed roundtrip %v => %s => %v", f, s, x) + } + } + f32 := float32(f) + if !math.IsInf(float64(f32), 0) { + s := FormatFloat(float64(f32), 'e', -1, 32) + if x, _ := ParseFloat(s, 32); float32(x) != f32 { + t.Errorf("failed roundtrip %v => %s => %v", f32, s, float32(x)) + } + } + } +} + +func TestFtoaRandom(t *testing.T) { + N := int(1e4) + if testing.Short() { + N = 100 + } + t.Logf("testing %d random numbers with fast and slow FormatFloat", N) + for i := 0; i < N; i++ { + bits := uint64(rand.Uint32())<<32 | uint64(rand.Uint32()) + x := math.Float64frombits(bits) + + shortFast := FormatFloat(x, 'g', -1, 64) + SetOptimize(false) + shortSlow := FormatFloat(x, 'g', -1, 64) + SetOptimize(true) + if shortSlow != shortFast { + t.Errorf("%b printed as %s, want %s", x, shortFast, shortSlow) + } + + prec := rand.IntN(12) + 5 + shortFast = FormatFloat(x, 'e', prec, 64) + SetOptimize(false) + shortSlow = FormatFloat(x, 'e', prec, 64) + SetOptimize(true) + if shortSlow != shortFast { + t.Errorf("%b printed as %s, want %s", x, shortFast, shortSlow) + } + } +} + +func TestFormatFloatInvalidBitSize(t *testing.T) { + defer func() { + if r := recover(); r == nil { + t.Fatalf("expected panic due to invalid bitSize") + } + }() + _ = FormatFloat(3.14, 'g', -1, 100) +} + +var ftoaBenches = []struct { + name string + float float64 + fmt byte + prec int + bitSize int +}{ + {"Decimal", 33909, 'g', -1, 64}, + {"Float", 339.7784, 'g', -1, 64}, + {"Exp", -5.09e75, 'g', -1, 64}, + {"NegExp", -5.11e-95, 'g', -1, 64}, + {"LongExp", 1.234567890123456e-78, 'g', -1, 64}, + + {"Big", 123456789123456789123456789, 'g', -1, 64}, + {"BinaryExp", -1, 'b', -1, 64}, + + {"32Integer", 33909, 'g', -1, 32}, + {"32ExactFraction", 3.375, 'g', -1, 32}, + {"32Point", 339.7784, 'g', -1, 32}, + {"32Exp", -5.09e25, 'g', -1, 32}, + {"32NegExp", -5.11e-25, 'g', -1, 32}, + {"32Shortest", 1.234567e-8, 'g', -1, 32}, + {"32Fixed8Hard", math.Ldexp(15961084, -125), 'e', 8, 32}, + {"32Fixed9Hard", math.Ldexp(14855922, -83), 'e', 9, 32}, + + {"64Fixed1", 123456, 'e', 3, 64}, + {"64Fixed2", 123.456, 'e', 3, 64}, + {"64Fixed3", 1.23456e+78, 'e', 3, 64}, + {"64Fixed4", 1.23456e-78, 'e', 3, 64}, + {"64Fixed12", 1.23456e-78, 'e', 12, 64}, + {"64Fixed16", 1.23456e-78, 'e', 16, 64}, + // From testdata/testfp.txt + {"64Fixed12Hard", math.Ldexp(6965949469487146, -249), 'e', 12, 64}, + {"64Fixed17Hard", math.Ldexp(8887055249355788, 665), 'e', 17, 64}, + {"64Fixed18Hard", math.Ldexp(6994187472632449, 690), 'e', 18, 64}, + + // Trigger slow path (see issue #15672). + // The shortest is: 8.034137530808823e+43 + {"Slowpath64", 8.03413753080882349e+43, 'e', -1, 64}, + // This denormal is pathological because the lower/upper + // halfways to neighboring floats are: + // 622666234635.321003e-320 ~= 622666234635.321e-320 + // 622666234635.321497e-320 ~= 622666234635.3215e-320 + // making it hard to find the 3rd digit + {"SlowpathDenormal64", 622666234635.3213e-320, 'e', -1, 64}, +} + +func BenchmarkFormatFloat(b *testing.B) { + for _, c := range ftoaBenches { + b.Run(c.name, func(b *testing.B) { + for i := 0; i < b.N; i++ { + FormatFloat(c.float, c.fmt, c.prec, c.bitSize) + } + }) + } +} + +func BenchmarkAppendFloat(b *testing.B) { + dst := make([]byte, 30) + for _, c := range ftoaBenches { + b.Run(c.name, func(b *testing.B) { + for i := 0; i < b.N; i++ { + AppendFloat(dst[:0], c.float, c.fmt, c.prec, c.bitSize) + } + }) + } +} diff --git a/gnovm/stdlibs/strconv/ftoaryu.gno b/gnovm/stdlibs/strconv/ftoaryu.gno new file mode 100644 index 00000000000..2e7bf71df0b --- /dev/null +++ b/gnovm/stdlibs/strconv/ftoaryu.gno @@ -0,0 +1,569 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package strconv + +import ( + "math/bits" +) + +// binary to decimal conversion using the Ryū algorithm. +// +// See Ulf Adams, "Ryū: Fast Float-to-String Conversion" (doi:10.1145/3192366.3192369) +// +// Fixed precision formatting is a variant of the original paper's +// algorithm, where a single multiplication by 10^k is required, +// sharing the same rounding guarantees. + +// ryuFtoaFixed32 formats mant*(2^exp) with prec decimal digits. +func ryuFtoaFixed32(d *decimalSlice, mant uint32, exp int, prec int) { + if prec < 0 { + panic("ryuFtoaFixed32 called with negative prec") + } + if prec > 9 { + panic("ryuFtoaFixed32 called with prec > 9") + } + // Zero input. + if mant == 0 { + d.nd, d.dp = 0, 0 + return + } + // Renormalize to a 25-bit mantissa. + e2 := exp + if b := bits.Len32(mant); b < 25 { + mant <<= uint(25 - b) + e2 += b - 25 + } + // Choose an exponent such that rounded mant*(2^e2)*(10^q) has + // at least prec decimal digits, i.e + // mant*(2^e2)*(10^q) >= 10^(prec-1) + // Because mant >= 2^24, it is enough to choose: + // 2^(e2+24) >= 10^(-q+prec-1) + // or q = -mulByLog2Log10(e2+24) + prec - 1 + q := -mulByLog2Log10(e2+24) + prec - 1 + + // Now compute mant*(2^e2)*(10^q). + // Is it an exact computation? + // Only small positive powers of 10 are exact (5^28 has 66 bits). + exact := q <= 27 && q >= 0 + + di, dexp2, d0 := mult64bitPow10(mant, e2, q) + if dexp2 >= 0 { + panic("not enough significant bits after mult64bitPow10") + } + // As a special case, computation might still be exact, if exponent + // was negative and if it amounts to computing an exact division. + // In that case, we ignore all lower bits. + // Note that division by 10^11 cannot be exact as 5^11 has 26 bits. + if q < 0 && q >= -10 && divisibleByPower5(uint64(mant), -q) { + exact = true + d0 = true + } + // Remove extra lower bits and keep rounding info. + extra := uint(-dexp2) + extraMask := uint32(1<>extra, di&extraMask + roundUp := false + if exact { + // If we computed an exact product, d + 1/2 + // should round to d+1 if 'd' is odd. + roundUp = dfrac > 1<<(extra-1) || + (dfrac == 1<<(extra-1) && !d0) || + (dfrac == 1<<(extra-1) && d0 && di&1 == 1) + } else { + // otherwise, d+1/2 always rounds up because + // we truncated below. + roundUp = dfrac>>(extra-1) == 1 + } + if dfrac != 0 { + d0 = false + } + // Proceed to the requested number of digits + formatDecimal(d, uint64(di), !d0, roundUp, prec) + // Adjust exponent + d.dp -= q +} + +// ryuFtoaFixed64 formats mant*(2^exp) with prec decimal digits. +func ryuFtoaFixed64(d *decimalSlice, mant uint64, exp int, prec int) { + if prec > 18 { + panic("ryuFtoaFixed64 called with prec > 18") + } + // Zero input. + if mant == 0 { + d.nd, d.dp = 0, 0 + return + } + // Renormalize to a 55-bit mantissa. + e2 := exp + if b := bits.Len64(mant); b < 55 { + mant = mant << uint(55-b) + e2 += b - 55 + } + // Choose an exponent such that rounded mant*(2^e2)*(10^q) has + // at least prec decimal digits, i.e + // mant*(2^e2)*(10^q) >= 10^(prec-1) + // Because mant >= 2^54, it is enough to choose: + // 2^(e2+54) >= 10^(-q+prec-1) + // or q = -mulByLog2Log10(e2+54) + prec - 1 + // + // The minimal required exponent is -mulByLog2Log10(1025)+18 = -291 + // The maximal required exponent is mulByLog2Log10(1074)+18 = 342 + q := -mulByLog2Log10(e2+54) + prec - 1 + + // Now compute mant*(2^e2)*(10^q). + // Is it an exact computation? + // Only small positive powers of 10 are exact (5^55 has 128 bits). + exact := q <= 55 && q >= 0 + + di, dexp2, d0 := mult128bitPow10(mant, e2, q) + if dexp2 >= 0 { + panic("not enough significant bits after mult128bitPow10") + } + // As a special case, computation might still be exact, if exponent + // was negative and if it amounts to computing an exact division. + // In that case, we ignore all lower bits. + // Note that division by 10^23 cannot be exact as 5^23 has 54 bits. + if q < 0 && q >= -22 && divisibleByPower5(mant, -q) { + exact = true + d0 = true + } + // Remove extra lower bits and keep rounding info. + extra := uint(-dexp2) + extraMask := uint64(1<>extra, di&extraMask + roundUp := false + if exact { + // If we computed an exact product, d + 1/2 + // should round to d+1 if 'd' is odd. + roundUp = dfrac > 1<<(extra-1) || + (dfrac == 1<<(extra-1) && !d0) || + (dfrac == 1<<(extra-1) && d0 && di&1 == 1) + } else { + // otherwise, d+1/2 always rounds up because + // we truncated below. + roundUp = dfrac>>(extra-1) == 1 + } + if dfrac != 0 { + d0 = false + } + // Proceed to the requested number of digits + formatDecimal(d, di, !d0, roundUp, prec) + // Adjust exponent + d.dp -= q +} + +var uint64pow10 = [...]uint64{ + 1, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, + 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, +} + +// formatDecimal fills d with at most prec decimal digits +// of mantissa m. The boolean trunc indicates whether m +// is truncated compared to the original number being formatted. +func formatDecimal(d *decimalSlice, m uint64, trunc bool, roundUp bool, prec int) { + max := uint64pow10[prec] + trimmed := 0 + for m >= max { + a, b := m/10, m%10 + m = a + trimmed++ + if b > 5 { + roundUp = true + } else if b < 5 { + roundUp = false + } else { // b == 5 + // round up if there are trailing digits, + // or if the new value of m is odd (round-to-even convention) + roundUp = trunc || m&1 == 1 + } + if b != 0 { + trunc = true + } + } + if roundUp { + m++ + } + if m >= max { + // Happens if di was originally 99999....xx + m /= 10 + trimmed++ + } + // render digits (similar to formatBits) + n := uint(prec) + d.nd = prec + v := m + for v >= 100 { + var v1, v2 uint64 + if v>>32 == 0 { + v1, v2 = uint64(uint32(v)/100), uint64(uint32(v)%100) + } else { + v1, v2 = v/100, v%100 + } + n -= 2 + d.d[n+1] = smallsString[2*v2+1] + d.d[n+0] = smallsString[2*v2+0] + v = v1 + } + if v > 0 { + n-- + d.d[n] = smallsString[2*v+1] + } + if v >= 10 { + n-- + d.d[n] = smallsString[2*v] + } + for d.d[d.nd-1] == '0' { + d.nd-- + trimmed++ + } + d.dp = d.nd + trimmed +} + +// ryuFtoaShortest formats mant*2^exp with prec decimal digits. +func ryuFtoaShortest(d *decimalSlice, mant uint64, exp int, flt *floatInfo) { + if mant == 0 { + d.nd, d.dp = 0, 0 + return + } + // If input is an exact integer with fewer bits than the mantissa, + // the previous and next integer are not admissible representations. + if exp <= 0 && bits.TrailingZeros64(mant) >= -exp { + mant >>= uint(-exp) + ryuDigits(d, mant, mant, mant, true, false) + return + } + ml, mc, mu, e2 := computeBounds(mant, exp, flt) + if e2 == 0 { + ryuDigits(d, ml, mc, mu, true, false) + return + } + // Find 10^q *larger* than 2^-e2 + q := mulByLog2Log10(-e2) + 1 + + // We are going to multiply by 10^q using 128-bit arithmetic. + // The exponent is the same for all 3 numbers. + var dl, dc, du uint64 + var dl0, dc0, du0 bool + if flt == &float32info { + var dl32, dc32, du32 uint32 + dl32, _, dl0 = mult64bitPow10(uint32(ml), e2, q) + dc32, _, dc0 = mult64bitPow10(uint32(mc), e2, q) + du32, e2, du0 = mult64bitPow10(uint32(mu), e2, q) + dl, dc, du = uint64(dl32), uint64(dc32), uint64(du32) + } else { + dl, _, dl0 = mult128bitPow10(ml, e2, q) + dc, _, dc0 = mult128bitPow10(mc, e2, q) + du, e2, du0 = mult128bitPow10(mu, e2, q) + } + if e2 >= 0 { + panic("not enough significant bits after mult128bitPow10") + } + // Is it an exact computation? + if q > 55 { + // Large positive powers of ten are not exact + dl0, dc0, du0 = false, false, false + } + if q < 0 && q >= -24 { + // Division by a power of ten may be exact. + // (note that 5^25 is a 59-bit number so division by 5^25 is never exact). + if divisibleByPower5(ml, -q) { + dl0 = true + } + if divisibleByPower5(mc, -q) { + dc0 = true + } + if divisibleByPower5(mu, -q) { + du0 = true + } + } + // Express the results (dl, dc, du)*2^e2 as integers. + // Extra bits must be removed and rounding hints computed. + extra := uint(-e2) + extraMask := uint64(1<>extra, dl&extraMask + dc, fracc := dc>>extra, dc&extraMask + du, fracu := du>>extra, du&extraMask + // Is it allowed to use 'du' as a result? + // It is always allowed when it is truncated, but also + // if it is exact and the original binary mantissa is even + // When disallowed, we can subtract 1. + uok := !du0 || fracu > 0 + if du0 && fracu == 0 { + uok = mant&1 == 0 + } + if !uok { + du-- + } + // Is 'dc' the correctly rounded base 10 mantissa? + // The correct rounding might be dc+1 + cup := false // don't round up. + if dc0 { + // If we computed an exact product, the half integer + // should round to next (even) integer if 'dc' is odd. + cup = fracc > 1<<(extra-1) || + (fracc == 1<<(extra-1) && dc&1 == 1) + } else { + // otherwise, the result is a lower truncation of the ideal + // result. + cup = fracc>>(extra-1) == 1 + } + // Is 'dl' an allowed representation? + // Only if it is an exact value, and if the original binary mantissa + // was even. + lok := dl0 && fracl == 0 && (mant&1 == 0) + if !lok { + dl++ + } + // We need to remember whether the trimmed digits of 'dc' are zero. + c0 := dc0 && fracc == 0 + // render digits + ryuDigits(d, dl, dc, du, c0, cup) + d.dp -= q +} + +// mulByLog2Log10 returns math.Floor(x * log(2)/log(10)) for an integer x in +// the range -1600 <= x && x <= +1600. +// +// The range restriction lets us work in faster integer arithmetic instead of +// slower floating point arithmetic. Correctness is verified by unit tests. +func mulByLog2Log10(x int) int { + // log(2)/log(10) ≈ 0.30102999566 ≈ 78913 / 2^18 + return (x * 78913) >> 18 +} + +// mulByLog10Log2 returns math.Floor(x * log(10)/log(2)) for an integer x in +// the range -500 <= x && x <= +500. +// +// The range restriction lets us work in faster integer arithmetic instead of +// slower floating point arithmetic. Correctness is verified by unit tests. +func mulByLog10Log2(x int) int { + // log(10)/log(2) ≈ 3.32192809489 ≈ 108853 / 2^15 + return (x * 108853) >> 15 +} + +// computeBounds returns a floating-point vector (l, c, u)×2^e2 +// where the mantissas are 55-bit (or 26-bit) integers, describing the interval +// represented by the input float64 or float32. +func computeBounds(mant uint64, exp int, flt *floatInfo) (lower, central, upper uint64, e2 int) { + if mant != 1< 5e8) || (clo == 5e8 && cup) + ryuDigits32(d, lhi, chi, uhi, c0, cup, 8) + d.dp += 9 + } else { + d.nd = 0 + // emit high part + n := uint(9) + for v := chi; v > 0; { + v1, v2 := v/10, v%10 + v = v1 + n-- + d.d[n] = byte(v2 + '0') + } + d.d = d.d[n:] + d.nd = int(9 - n) + // emit low part + ryuDigits32(d, llo, clo, ulo, + c0, cup, d.nd+8) + } + // trim trailing zeros + for d.nd > 0 && d.d[d.nd-1] == '0' { + d.nd-- + } + // trim initial zeros + for d.nd > 0 && d.d[0] == '0' { + d.nd-- + d.dp-- + d.d = d.d[1:] + } +} + +// ryuDigits32 emits decimal digits for a number less than 1e9. +func ryuDigits32(d *decimalSlice, lower, central, upper uint32, + c0, cup bool, endindex int) { + if upper == 0 { + d.dp = endindex + 1 + return + } + trimmed := 0 + // Remember last trimmed digit to check for round-up. + // c0 will be used to remember zeroness of following digits. + cNextDigit := 0 + for upper > 0 { + // Repeatedly compute: + // l = Ceil(lower / 10^k) + // c = Round(central / 10^k) + // u = Floor(upper / 10^k) + // and stop when c goes out of the (l, u) interval. + l := (lower + 9) / 10 + c, cdigit := central/10, central%10 + u := upper / 10 + if l > u { + // don't trim the last digit as it is forbidden to go below l + // other, trim and exit now. + break + } + // Check that we didn't cross the lower boundary. + // The case where l < u but c == l-1 is essentially impossible, + // but may happen if: + // lower = ..11 + // central = ..19 + // upper = ..31 + // and means that 'central' is very close but less than + // an integer ending with many zeros, and usually + // the "round-up" logic hides the problem. + if l == c+1 && c < u { + c++ + cdigit = 0 + cup = false + } + trimmed++ + // Remember trimmed digits of c + c0 = c0 && cNextDigit == 0 + cNextDigit = int(cdigit) + lower, central, upper = l, c, u + } + // should we round up? + if trimmed > 0 { + cup = cNextDigit > 5 || + (cNextDigit == 5 && !c0) || + (cNextDigit == 5 && c0 && central&1 == 1) + } + if central < upper && cup { + central++ + } + // We know where the number ends, fill directly + endindex -= trimmed + v := central + n := endindex + for n > d.nd { + v1, v2 := v/100, v%100 + d.d[n] = smallsString[2*v2+1] + d.d[n-1] = smallsString[2*v2+0] + n -= 2 + v = v1 + } + if n == d.nd { + d.d[n] = byte(v + '0') + } + d.nd = endindex + 1 + d.dp = d.nd + trimmed +} + +// mult64bitPow10 takes a floating-point input with a 25-bit +// mantissa and multiplies it with 10^q. The resulting mantissa +// is m*P >> 57 where P is a 64-bit element of the detailedPowersOfTen tables. +// It is typically 31 or 32-bit wide. +// The returned boolean is true if all trimmed bits were zero. +// +// That is: +// +// m*2^e2 * round(10^q) = resM * 2^resE + ε +// exact = ε == 0 +func mult64bitPow10(m uint32, e2, q int) (resM uint32, resE int, exact bool) { + if q == 0 { + // P == 1<<63 + return m << 6, e2 - 6, true + } + if q < detailedPowersOfTenMinExp10 || detailedPowersOfTenMaxExp10 < q { + // This never happens due to the range of float32/float64 exponent + panic("mult64bitPow10: power of 10 is out of range") + } + pow := detailedPowersOfTen[q-detailedPowersOfTenMinExp10][1] + if q < 0 { + // Inverse powers of ten must be rounded up. + pow += 1 + } + hi, lo := bits.Mul64(uint64(m), pow) + e2 += mulByLog10Log2(q) - 63 + 57 + return uint32(hi<<7 | lo>>57), e2, lo<<7 == 0 +} + +// mult128bitPow10 takes a floating-point input with a 55-bit +// mantissa and multiplies it with 10^q. The resulting mantissa +// is m*P >> 119 where P is a 128-bit element of the detailedPowersOfTen tables. +// It is typically 63 or 64-bit wide. +// The returned boolean is true is all trimmed bits were zero. +// +// That is: +// +// m*2^e2 * round(10^q) = resM * 2^resE + ε +// exact = ε == 0 +func mult128bitPow10(m uint64, e2, q int) (resM uint64, resE int, exact bool) { + if q == 0 { + // P == 1<<127 + return m << 8, e2 - 8, true + } + if q < detailedPowersOfTenMinExp10 || detailedPowersOfTenMaxExp10 < q { + // This never happens due to the range of float32/float64 exponent + panic("mult128bitPow10: power of 10 is out of range") + } + pow := detailedPowersOfTen[q-detailedPowersOfTenMinExp10] + if q < 0 { + // Inverse powers of ten must be rounded up. + pow[0] += 1 + } + e2 += mulByLog10Log2(q) - 127 + 119 + + // long multiplication + l1, l0 := bits.Mul64(m, pow[0]) + h1, h0 := bits.Mul64(m, pow[1]) + mid, carry := bits.Add64(l1, h0, 0) + h1 += carry + return h1<<9 | mid>>55, e2, mid<<9 == 0 && l0 == 0 +} + +func divisibleByPower5(m uint64, k int) bool { + if m == 0 { + return true + } + for i := 0; i < k; i++ { + if m%5 != 0 { + return false + } + m /= 5 + } + return true +} + +// divmod1e9 computes quotient and remainder of division by 1e9, +// avoiding runtime uint64 division on 32-bit platforms. +func divmod1e9(x uint64) (uint32, uint32) { + if !host32bit { + return uint32(x / 1e9), uint32(x % 1e9) + } + // Use the same sequence of operations as the amd64 compiler. + hi, _ := bits.Mul64(x>>1, 0x89705f4136b4a598) // binary digits of 1e-9 + q := hi >> 28 + return uint32(q), uint32(x - q*1e9) +} diff --git a/gnovm/stdlibs/strconv/ftoaryu_test.gno b/gnovm/stdlibs/strconv/ftoaryu_test.gno new file mode 100644 index 00000000000..bd969e8e997 --- /dev/null +++ b/gnovm/stdlibs/strconv/ftoaryu_test.gno @@ -0,0 +1,30 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package strconv + +import ( + "math" + "testing" +) + +func TestMulByLog2Log10(t *testing.T) { + for x := -1600; x <= +1600; x++ { + iMath := MulByLog2Log10(x) + fMath := int(math.Floor(float64(x) * math.Ln2 / math.Ln10)) + if iMath != fMath { + t.Errorf("mulByLog2Log10(%d) failed: %d vs %d\n", x, iMath, fMath) + } + } +} + +func TestMulByLog10Log2(t *testing.T) { + for x := -500; x <= +500; x++ { + iMath := MulByLog10Log2(x) + fMath := int(math.Floor(float64(x) * math.Ln10 / math.Ln2)) + if iMath != fMath { + t.Errorf("mulByLog10Log2(%d) failed: %d vs %d\n", x, iMath, fMath) + } + } +} diff --git a/gnovm/stdlibs/strconv/internal_test.gno b/gnovm/stdlibs/strconv/internal_test.gno new file mode 100644 index 00000000000..f2cceff20eb --- /dev/null +++ b/gnovm/stdlibs/strconv/internal_test.gno @@ -0,0 +1,31 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// export access to strconv internals for tests + +package strconv + +func NewDecimal(i uint64) *decimal { + d := new(decimal) + d.Assign(i) + return d +} + +func SetOptimize(b bool) bool { + old := optimize + optimize = b + return old +} + +func ParseFloatPrefix(s string, bitSize int) (float64, int, error) { + return parseFloatPrefix(s, bitSize) +} + +func MulByLog2Log10(x int) int { + return mulByLog2Log10(x) +} + +func MulByLog10Log2(x int) int { + return mulByLog10Log2(x) +} diff --git a/gnovm/stdlibs/strconv/isprint.gno b/gnovm/stdlibs/strconv/isprint.gno new file mode 100644 index 00000000000..baa14a65bd6 --- /dev/null +++ b/gnovm/stdlibs/strconv/isprint.gno @@ -0,0 +1,752 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated by go run makeisprint.go -output isprint.go; DO NOT EDIT. + +package strconv + +// (424+133+112)*2 + (508)*4 = 3370 bytes + +var isPrint16 = []uint16{ + 0x0020, 0x007e, + 0x00a1, 0x0377, + 0x037a, 0x037f, + 0x0384, 0x0556, + 0x0559, 0x058a, + 0x058d, 0x05c7, + 0x05d0, 0x05ea, + 0x05ef, 0x05f4, + 0x0606, 0x070d, + 0x0710, 0x074a, + 0x074d, 0x07b1, + 0x07c0, 0x07fa, + 0x07fd, 0x082d, + 0x0830, 0x085b, + 0x085e, 0x086a, + 0x0870, 0x088e, + 0x0898, 0x098c, + 0x098f, 0x0990, + 0x0993, 0x09b2, + 0x09b6, 0x09b9, + 0x09bc, 0x09c4, + 0x09c7, 0x09c8, + 0x09cb, 0x09ce, + 0x09d7, 0x09d7, + 0x09dc, 0x09e3, + 0x09e6, 0x09fe, + 0x0a01, 0x0a0a, + 0x0a0f, 0x0a10, + 0x0a13, 0x0a39, + 0x0a3c, 0x0a42, + 0x0a47, 0x0a48, + 0x0a4b, 0x0a4d, + 0x0a51, 0x0a51, + 0x0a59, 0x0a5e, + 0x0a66, 0x0a76, + 0x0a81, 0x0ab9, + 0x0abc, 0x0acd, + 0x0ad0, 0x0ad0, + 0x0ae0, 0x0ae3, + 0x0ae6, 0x0af1, + 0x0af9, 0x0b0c, + 0x0b0f, 0x0b10, + 0x0b13, 0x0b39, + 0x0b3c, 0x0b44, + 0x0b47, 0x0b48, + 0x0b4b, 0x0b4d, + 0x0b55, 0x0b57, + 0x0b5c, 0x0b63, + 0x0b66, 0x0b77, + 0x0b82, 0x0b8a, + 0x0b8e, 0x0b95, + 0x0b99, 0x0b9f, + 0x0ba3, 0x0ba4, + 0x0ba8, 0x0baa, + 0x0bae, 0x0bb9, + 0x0bbe, 0x0bc2, + 0x0bc6, 0x0bcd, + 0x0bd0, 0x0bd0, + 0x0bd7, 0x0bd7, + 0x0be6, 0x0bfa, + 0x0c00, 0x0c39, + 0x0c3c, 0x0c4d, + 0x0c55, 0x0c5a, + 0x0c5d, 0x0c5d, + 0x0c60, 0x0c63, + 0x0c66, 0x0c6f, + 0x0c77, 0x0cb9, + 0x0cbc, 0x0ccd, + 0x0cd5, 0x0cd6, + 0x0cdd, 0x0ce3, + 0x0ce6, 0x0cf3, + 0x0d00, 0x0d4f, + 0x0d54, 0x0d63, + 0x0d66, 0x0d96, + 0x0d9a, 0x0dbd, + 0x0dc0, 0x0dc6, + 0x0dca, 0x0dca, + 0x0dcf, 0x0ddf, + 0x0de6, 0x0def, + 0x0df2, 0x0df4, + 0x0e01, 0x0e3a, + 0x0e3f, 0x0e5b, + 0x0e81, 0x0ebd, + 0x0ec0, 0x0ed9, + 0x0edc, 0x0edf, + 0x0f00, 0x0f6c, + 0x0f71, 0x0fda, + 0x1000, 0x10c7, + 0x10cd, 0x10cd, + 0x10d0, 0x124d, + 0x1250, 0x125d, + 0x1260, 0x128d, + 0x1290, 0x12b5, + 0x12b8, 0x12c5, + 0x12c8, 0x1315, + 0x1318, 0x135a, + 0x135d, 0x137c, + 0x1380, 0x1399, + 0x13a0, 0x13f5, + 0x13f8, 0x13fd, + 0x1400, 0x169c, + 0x16a0, 0x16f8, + 0x1700, 0x1715, + 0x171f, 0x1736, + 0x1740, 0x1753, + 0x1760, 0x1773, + 0x1780, 0x17dd, + 0x17e0, 0x17e9, + 0x17f0, 0x17f9, + 0x1800, 0x1819, + 0x1820, 0x1878, + 0x1880, 0x18aa, + 0x18b0, 0x18f5, + 0x1900, 0x192b, + 0x1930, 0x193b, + 0x1940, 0x1940, + 0x1944, 0x196d, + 0x1970, 0x1974, + 0x1980, 0x19ab, + 0x19b0, 0x19c9, + 0x19d0, 0x19da, + 0x19de, 0x1a1b, + 0x1a1e, 0x1a7c, + 0x1a7f, 0x1a89, + 0x1a90, 0x1a99, + 0x1aa0, 0x1aad, + 0x1ab0, 0x1ace, + 0x1b00, 0x1b4c, + 0x1b50, 0x1bf3, + 0x1bfc, 0x1c37, + 0x1c3b, 0x1c49, + 0x1c4d, 0x1c88, + 0x1c90, 0x1cba, + 0x1cbd, 0x1cc7, + 0x1cd0, 0x1cfa, + 0x1d00, 0x1f15, + 0x1f18, 0x1f1d, + 0x1f20, 0x1f45, + 0x1f48, 0x1f4d, + 0x1f50, 0x1f7d, + 0x1f80, 0x1fd3, + 0x1fd6, 0x1fef, + 0x1ff2, 0x1ffe, + 0x2010, 0x2027, + 0x2030, 0x205e, + 0x2070, 0x2071, + 0x2074, 0x209c, + 0x20a0, 0x20c0, + 0x20d0, 0x20f0, + 0x2100, 0x218b, + 0x2190, 0x2426, + 0x2440, 0x244a, + 0x2460, 0x2b73, + 0x2b76, 0x2cf3, + 0x2cf9, 0x2d27, + 0x2d2d, 0x2d2d, + 0x2d30, 0x2d67, + 0x2d6f, 0x2d70, + 0x2d7f, 0x2d96, + 0x2da0, 0x2e5d, + 0x2e80, 0x2ef3, + 0x2f00, 0x2fd5, + 0x2ff0, 0x2ffb, + 0x3001, 0x3096, + 0x3099, 0x30ff, + 0x3105, 0x31e3, + 0x31f0, 0xa48c, + 0xa490, 0xa4c6, + 0xa4d0, 0xa62b, + 0xa640, 0xa6f7, + 0xa700, 0xa7ca, + 0xa7d0, 0xa7d9, + 0xa7f2, 0xa82c, + 0xa830, 0xa839, + 0xa840, 0xa877, + 0xa880, 0xa8c5, + 0xa8ce, 0xa8d9, + 0xa8e0, 0xa953, + 0xa95f, 0xa97c, + 0xa980, 0xa9d9, + 0xa9de, 0xaa36, + 0xaa40, 0xaa4d, + 0xaa50, 0xaa59, + 0xaa5c, 0xaac2, + 0xaadb, 0xaaf6, + 0xab01, 0xab06, + 0xab09, 0xab0e, + 0xab11, 0xab16, + 0xab20, 0xab6b, + 0xab70, 0xabed, + 0xabf0, 0xabf9, + 0xac00, 0xd7a3, + 0xd7b0, 0xd7c6, + 0xd7cb, 0xd7fb, + 0xf900, 0xfa6d, + 0xfa70, 0xfad9, + 0xfb00, 0xfb06, + 0xfb13, 0xfb17, + 0xfb1d, 0xfbc2, + 0xfbd3, 0xfd8f, + 0xfd92, 0xfdc7, + 0xfdcf, 0xfdcf, + 0xfdf0, 0xfe19, + 0xfe20, 0xfe6b, + 0xfe70, 0xfefc, + 0xff01, 0xffbe, + 0xffc2, 0xffc7, + 0xffca, 0xffcf, + 0xffd2, 0xffd7, + 0xffda, 0xffdc, + 0xffe0, 0xffee, + 0xfffc, 0xfffd, +} + +var isNotPrint16 = []uint16{ + 0x00ad, + 0x038b, + 0x038d, + 0x03a2, + 0x0530, + 0x0590, + 0x061c, + 0x06dd, + 0x083f, + 0x085f, + 0x08e2, + 0x0984, + 0x09a9, + 0x09b1, + 0x09de, + 0x0a04, + 0x0a29, + 0x0a31, + 0x0a34, + 0x0a37, + 0x0a3d, + 0x0a5d, + 0x0a84, + 0x0a8e, + 0x0a92, + 0x0aa9, + 0x0ab1, + 0x0ab4, + 0x0ac6, + 0x0aca, + 0x0b00, + 0x0b04, + 0x0b29, + 0x0b31, + 0x0b34, + 0x0b5e, + 0x0b84, + 0x0b91, + 0x0b9b, + 0x0b9d, + 0x0bc9, + 0x0c0d, + 0x0c11, + 0x0c29, + 0x0c45, + 0x0c49, + 0x0c57, + 0x0c8d, + 0x0c91, + 0x0ca9, + 0x0cb4, + 0x0cc5, + 0x0cc9, + 0x0cdf, + 0x0cf0, + 0x0d0d, + 0x0d11, + 0x0d45, + 0x0d49, + 0x0d80, + 0x0d84, + 0x0db2, + 0x0dbc, + 0x0dd5, + 0x0dd7, + 0x0e83, + 0x0e85, + 0x0e8b, + 0x0ea4, + 0x0ea6, + 0x0ec5, + 0x0ec7, + 0x0ecf, + 0x0f48, + 0x0f98, + 0x0fbd, + 0x0fcd, + 0x10c6, + 0x1249, + 0x1257, + 0x1259, + 0x1289, + 0x12b1, + 0x12bf, + 0x12c1, + 0x12d7, + 0x1311, + 0x1680, + 0x176d, + 0x1771, + 0x180e, + 0x191f, + 0x1a5f, + 0x1b7f, + 0x1f58, + 0x1f5a, + 0x1f5c, + 0x1f5e, + 0x1fb5, + 0x1fc5, + 0x1fdc, + 0x1ff5, + 0x208f, + 0x2b96, + 0x2d26, + 0x2da7, + 0x2daf, + 0x2db7, + 0x2dbf, + 0x2dc7, + 0x2dcf, + 0x2dd7, + 0x2ddf, + 0x2e9a, + 0x3040, + 0x3130, + 0x318f, + 0x321f, + 0xa7d2, + 0xa7d4, + 0xa9ce, + 0xa9ff, + 0xab27, + 0xab2f, + 0xfb37, + 0xfb3d, + 0xfb3f, + 0xfb42, + 0xfb45, + 0xfe53, + 0xfe67, + 0xfe75, + 0xffe7, +} + +var isPrint32 = []uint32{ + 0x010000, 0x01004d, + 0x010050, 0x01005d, + 0x010080, 0x0100fa, + 0x010100, 0x010102, + 0x010107, 0x010133, + 0x010137, 0x01019c, + 0x0101a0, 0x0101a0, + 0x0101d0, 0x0101fd, + 0x010280, 0x01029c, + 0x0102a0, 0x0102d0, + 0x0102e0, 0x0102fb, + 0x010300, 0x010323, + 0x01032d, 0x01034a, + 0x010350, 0x01037a, + 0x010380, 0x0103c3, + 0x0103c8, 0x0103d5, + 0x010400, 0x01049d, + 0x0104a0, 0x0104a9, + 0x0104b0, 0x0104d3, + 0x0104d8, 0x0104fb, + 0x010500, 0x010527, + 0x010530, 0x010563, + 0x01056f, 0x0105bc, + 0x010600, 0x010736, + 0x010740, 0x010755, + 0x010760, 0x010767, + 0x010780, 0x0107ba, + 0x010800, 0x010805, + 0x010808, 0x010838, + 0x01083c, 0x01083c, + 0x01083f, 0x01089e, + 0x0108a7, 0x0108af, + 0x0108e0, 0x0108f5, + 0x0108fb, 0x01091b, + 0x01091f, 0x010939, + 0x01093f, 0x01093f, + 0x010980, 0x0109b7, + 0x0109bc, 0x0109cf, + 0x0109d2, 0x010a06, + 0x010a0c, 0x010a35, + 0x010a38, 0x010a3a, + 0x010a3f, 0x010a48, + 0x010a50, 0x010a58, + 0x010a60, 0x010a9f, + 0x010ac0, 0x010ae6, + 0x010aeb, 0x010af6, + 0x010b00, 0x010b35, + 0x010b39, 0x010b55, + 0x010b58, 0x010b72, + 0x010b78, 0x010b91, + 0x010b99, 0x010b9c, + 0x010ba9, 0x010baf, + 0x010c00, 0x010c48, + 0x010c80, 0x010cb2, + 0x010cc0, 0x010cf2, + 0x010cfa, 0x010d27, + 0x010d30, 0x010d39, + 0x010e60, 0x010ead, + 0x010eb0, 0x010eb1, + 0x010efd, 0x010f27, + 0x010f30, 0x010f59, + 0x010f70, 0x010f89, + 0x010fb0, 0x010fcb, + 0x010fe0, 0x010ff6, + 0x011000, 0x01104d, + 0x011052, 0x011075, + 0x01107f, 0x0110c2, + 0x0110d0, 0x0110e8, + 0x0110f0, 0x0110f9, + 0x011100, 0x011147, + 0x011150, 0x011176, + 0x011180, 0x0111f4, + 0x011200, 0x011241, + 0x011280, 0x0112a9, + 0x0112b0, 0x0112ea, + 0x0112f0, 0x0112f9, + 0x011300, 0x01130c, + 0x01130f, 0x011310, + 0x011313, 0x011344, + 0x011347, 0x011348, + 0x01134b, 0x01134d, + 0x011350, 0x011350, + 0x011357, 0x011357, + 0x01135d, 0x011363, + 0x011366, 0x01136c, + 0x011370, 0x011374, + 0x011400, 0x011461, + 0x011480, 0x0114c7, + 0x0114d0, 0x0114d9, + 0x011580, 0x0115b5, + 0x0115b8, 0x0115dd, + 0x011600, 0x011644, + 0x011650, 0x011659, + 0x011660, 0x01166c, + 0x011680, 0x0116b9, + 0x0116c0, 0x0116c9, + 0x011700, 0x01171a, + 0x01171d, 0x01172b, + 0x011730, 0x011746, + 0x011800, 0x01183b, + 0x0118a0, 0x0118f2, + 0x0118ff, 0x011906, + 0x011909, 0x011909, + 0x01190c, 0x011938, + 0x01193b, 0x011946, + 0x011950, 0x011959, + 0x0119a0, 0x0119a7, + 0x0119aa, 0x0119d7, + 0x0119da, 0x0119e4, + 0x011a00, 0x011a47, + 0x011a50, 0x011aa2, + 0x011ab0, 0x011af8, + 0x011b00, 0x011b09, + 0x011c00, 0x011c45, + 0x011c50, 0x011c6c, + 0x011c70, 0x011c8f, + 0x011c92, 0x011cb6, + 0x011d00, 0x011d36, + 0x011d3a, 0x011d47, + 0x011d50, 0x011d59, + 0x011d60, 0x011d98, + 0x011da0, 0x011da9, + 0x011ee0, 0x011ef8, + 0x011f00, 0x011f3a, + 0x011f3e, 0x011f59, + 0x011fb0, 0x011fb0, + 0x011fc0, 0x011ff1, + 0x011fff, 0x012399, + 0x012400, 0x012474, + 0x012480, 0x012543, + 0x012f90, 0x012ff2, + 0x013000, 0x01342f, + 0x013440, 0x013455, + 0x014400, 0x014646, + 0x016800, 0x016a38, + 0x016a40, 0x016a69, + 0x016a6e, 0x016ac9, + 0x016ad0, 0x016aed, + 0x016af0, 0x016af5, + 0x016b00, 0x016b45, + 0x016b50, 0x016b77, + 0x016b7d, 0x016b8f, + 0x016e40, 0x016e9a, + 0x016f00, 0x016f4a, + 0x016f4f, 0x016f87, + 0x016f8f, 0x016f9f, + 0x016fe0, 0x016fe4, + 0x016ff0, 0x016ff1, + 0x017000, 0x0187f7, + 0x018800, 0x018cd5, + 0x018d00, 0x018d08, + 0x01aff0, 0x01b122, + 0x01b132, 0x01b132, + 0x01b150, 0x01b152, + 0x01b155, 0x01b155, + 0x01b164, 0x01b167, + 0x01b170, 0x01b2fb, + 0x01bc00, 0x01bc6a, + 0x01bc70, 0x01bc7c, + 0x01bc80, 0x01bc88, + 0x01bc90, 0x01bc99, + 0x01bc9c, 0x01bc9f, + 0x01cf00, 0x01cf2d, + 0x01cf30, 0x01cf46, + 0x01cf50, 0x01cfc3, + 0x01d000, 0x01d0f5, + 0x01d100, 0x01d126, + 0x01d129, 0x01d172, + 0x01d17b, 0x01d1ea, + 0x01d200, 0x01d245, + 0x01d2c0, 0x01d2d3, + 0x01d2e0, 0x01d2f3, + 0x01d300, 0x01d356, + 0x01d360, 0x01d378, + 0x01d400, 0x01d49f, + 0x01d4a2, 0x01d4a2, + 0x01d4a5, 0x01d4a6, + 0x01d4a9, 0x01d50a, + 0x01d50d, 0x01d546, + 0x01d54a, 0x01d6a5, + 0x01d6a8, 0x01d7cb, + 0x01d7ce, 0x01da8b, + 0x01da9b, 0x01daaf, + 0x01df00, 0x01df1e, + 0x01df25, 0x01df2a, + 0x01e000, 0x01e018, + 0x01e01b, 0x01e02a, + 0x01e030, 0x01e06d, + 0x01e08f, 0x01e08f, + 0x01e100, 0x01e12c, + 0x01e130, 0x01e13d, + 0x01e140, 0x01e149, + 0x01e14e, 0x01e14f, + 0x01e290, 0x01e2ae, + 0x01e2c0, 0x01e2f9, + 0x01e2ff, 0x01e2ff, + 0x01e4d0, 0x01e4f9, + 0x01e7e0, 0x01e8c4, + 0x01e8c7, 0x01e8d6, + 0x01e900, 0x01e94b, + 0x01e950, 0x01e959, + 0x01e95e, 0x01e95f, + 0x01ec71, 0x01ecb4, + 0x01ed01, 0x01ed3d, + 0x01ee00, 0x01ee24, + 0x01ee27, 0x01ee3b, + 0x01ee42, 0x01ee42, + 0x01ee47, 0x01ee54, + 0x01ee57, 0x01ee64, + 0x01ee67, 0x01ee9b, + 0x01eea1, 0x01eebb, + 0x01eef0, 0x01eef1, + 0x01f000, 0x01f02b, + 0x01f030, 0x01f093, + 0x01f0a0, 0x01f0ae, + 0x01f0b1, 0x01f0f5, + 0x01f100, 0x01f1ad, + 0x01f1e6, 0x01f202, + 0x01f210, 0x01f23b, + 0x01f240, 0x01f248, + 0x01f250, 0x01f251, + 0x01f260, 0x01f265, + 0x01f300, 0x01f6d7, + 0x01f6dc, 0x01f6ec, + 0x01f6f0, 0x01f6fc, + 0x01f700, 0x01f776, + 0x01f77b, 0x01f7d9, + 0x01f7e0, 0x01f7eb, + 0x01f7f0, 0x01f7f0, + 0x01f800, 0x01f80b, + 0x01f810, 0x01f847, + 0x01f850, 0x01f859, + 0x01f860, 0x01f887, + 0x01f890, 0x01f8ad, + 0x01f8b0, 0x01f8b1, + 0x01f900, 0x01fa53, + 0x01fa60, 0x01fa6d, + 0x01fa70, 0x01fa7c, + 0x01fa80, 0x01fa88, + 0x01fa90, 0x01fac5, + 0x01face, 0x01fadb, + 0x01fae0, 0x01fae8, + 0x01faf0, 0x01faf8, + 0x01fb00, 0x01fbca, + 0x01fbf0, 0x01fbf9, + 0x020000, 0x02a6df, + 0x02a700, 0x02b739, + 0x02b740, 0x02b81d, + 0x02b820, 0x02cea1, + 0x02ceb0, 0x02ebe0, + 0x02f800, 0x02fa1d, + 0x030000, 0x03134a, + 0x031350, 0x0323af, + 0x0e0100, 0x0e01ef, +} + +var isNotPrint32 = []uint16{ // add 0x10000 to each entry + 0x000c, + 0x0027, + 0x003b, + 0x003e, + 0x018f, + 0x039e, + 0x057b, + 0x058b, + 0x0593, + 0x0596, + 0x05a2, + 0x05b2, + 0x05ba, + 0x0786, + 0x07b1, + 0x0809, + 0x0836, + 0x0856, + 0x08f3, + 0x0a04, + 0x0a14, + 0x0a18, + 0x0e7f, + 0x0eaa, + 0x10bd, + 0x1135, + 0x11e0, + 0x1212, + 0x1287, + 0x1289, + 0x128e, + 0x129e, + 0x1304, + 0x1329, + 0x1331, + 0x1334, + 0x133a, + 0x145c, + 0x1914, + 0x1917, + 0x1936, + 0x1c09, + 0x1c37, + 0x1ca8, + 0x1d07, + 0x1d0a, + 0x1d3b, + 0x1d3e, + 0x1d66, + 0x1d69, + 0x1d8f, + 0x1d92, + 0x1f11, + 0x246f, + 0x6a5f, + 0x6abf, + 0x6b5a, + 0x6b62, + 0xaff4, + 0xaffc, + 0xafff, + 0xd455, + 0xd49d, + 0xd4ad, + 0xd4ba, + 0xd4bc, + 0xd4c4, + 0xd506, + 0xd515, + 0xd51d, + 0xd53a, + 0xd53f, + 0xd545, + 0xd551, + 0xdaa0, + 0xe007, + 0xe022, + 0xe025, + 0xe7e7, + 0xe7ec, + 0xe7ef, + 0xe7ff, + 0xee04, + 0xee20, + 0xee23, + 0xee28, + 0xee33, + 0xee38, + 0xee3a, + 0xee48, + 0xee4a, + 0xee4c, + 0xee50, + 0xee53, + 0xee58, + 0xee5a, + 0xee5c, + 0xee5e, + 0xee60, + 0xee63, + 0xee6b, + 0xee73, + 0xee78, + 0xee7d, + 0xee7f, + 0xee8a, + 0xeea4, + 0xeeaa, + 0xf0c0, + 0xf0d0, + 0xfabe, + 0xfb93, +} + +// isGraphic lists the graphic runes not matched by IsPrint. +var isGraphic = []uint16{ + 0x00a0, + 0x1680, + 0x2000, + 0x2001, + 0x2002, + 0x2003, + 0x2004, + 0x2005, + 0x2006, + 0x2007, + 0x2008, + 0x2009, + 0x200a, + 0x202f, + 0x205f, + 0x3000, +} diff --git a/gnovm/stdlibs/strconv/itoa.gno b/gnovm/stdlibs/strconv/itoa.gno new file mode 100644 index 00000000000..b0c2666e7cb --- /dev/null +++ b/gnovm/stdlibs/strconv/itoa.gno @@ -0,0 +1,205 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package strconv + +import "math/bits" + +const fastSmalls = true // enable fast path for small integers + +// FormatUint returns the string representation of i in the given base, +// for 2 <= base <= 36. The result uses the lower-case letters 'a' to 'z' +// for digit values >= 10. +func FormatUint(i uint64, base int) string { + if fastSmalls && i < nSmalls && base == 10 { + return small(int(i)) + } + _, s := formatBits(nil, i, base, false, false) + return s +} + +// FormatInt returns the string representation of i in the given base, +// for 2 <= base <= 36. The result uses the lower-case letters 'a' to 'z' +// for digit values >= 10. +func FormatInt(i int64, base int) string { + if fastSmalls && 0 <= i && i < nSmalls && base == 10 { + return small(int(i)) + } + _, s := formatBits(nil, uint64(i), base, i < 0, false) + return s +} + +// Itoa is equivalent to FormatInt(int64(i), 10). +func Itoa(i int) string { + return FormatInt(int64(i), 10) +} + +// AppendInt appends the string form of the integer i, +// as generated by FormatInt, to dst and returns the extended buffer. +func AppendInt(dst []byte, i int64, base int) []byte { + if fastSmalls && 0 <= i && i < nSmalls && base == 10 { + return append(dst, small(int(i))...) + } + dst, _ = formatBits(dst, uint64(i), base, i < 0, true) + return dst +} + +// AppendUint appends the string form of the unsigned integer i, +// as generated by FormatUint, to dst and returns the extended buffer. +func AppendUint(dst []byte, i uint64, base int) []byte { + if fastSmalls && i < nSmalls && base == 10 { + return append(dst, small(int(i))...) + } + dst, _ = formatBits(dst, i, base, false, true) + return dst +} + +// small returns the string for an i with 0 <= i < nSmalls. +func small(i int) string { + if i < 10 { + return digits[i : i+1] + } + return smallsString[i*2 : i*2+2] +} + +const nSmalls = 100 + +const smallsString = "00010203040506070809" + + "10111213141516171819" + + "20212223242526272829" + + "30313233343536373839" + + "40414243444546474849" + + "50515253545556575859" + + "60616263646566676869" + + "70717273747576777879" + + "80818283848586878889" + + "90919293949596979899" + +const host32bit = ^uint(0)>>32 == 0 + +const digits = "0123456789abcdefghijklmnopqrstuvwxyz" + +// formatBits computes the string representation of u in the given base. +// If neg is set, u is treated as negative int64 value. If append_ is +// set, the string is appended to dst and the resulting byte slice is +// returned as the first result value; otherwise the string is returned +// as the second result value. +func formatBits(dst []byte, u uint64, base int, neg, append_ bool) (d []byte, s string) { + if base < 2 || base > len(digits) { + panic("strconv: illegal AppendInt/FormatInt base") + } + // 2 <= base && base <= len(digits) + + var a [64 + 1]byte // +1 for sign of 64bit value in base 2 + i := len(a) + + if neg { + u = -u + } + + // convert bits + // We use uint values where we can because those will + // fit into a single register even on a 32bit machine. + if base == 10 { + // common case: use constants for / because + // the compiler can optimize it into a multiply+shift + + if host32bit { + // convert the lower digits using 32bit operations + for u >= 1e9 { + // Avoid using r = a%b in addition to q = a/b + // since 64bit division and modulo operations + // are calculated by runtime functions on 32bit machines. + q := u / 1e9 + us := uint(u - q*1e9) // u % 1e9 fits into a uint + for j := 4; j > 0; j-- { + is := us % 100 * 2 + us /= 100 + i -= 2 + a[i+1] = smallsString[is+1] + a[i+0] = smallsString[is+0] + } + + // us < 10, since it contains the last digit + // from the initial 9-digit us. + i-- + a[i] = smallsString[us*2+1] + + u = q + } + // u < 1e9 + } + + // u guaranteed to fit into a uint + us := uint(u) + for us >= 100 { + is := us % 100 * 2 + us /= 100 + i -= 2 + a[i+1] = smallsString[is+1] + a[i+0] = smallsString[is+0] + } + + // us < 100 + is := us * 2 + i-- + a[i] = smallsString[is+1] + if us >= 10 { + i-- + a[i] = smallsString[is] + } + + } else if isPowerOfTwo(base) { + // Use shifts and masks instead of / and %. + // Base is a power of 2 and 2 <= base <= len(digits) where len(digits) is 36. + // The largest power of 2 below or equal to 36 is 32, which is 1 << 5; + // i.e., the largest possible shift count is 5. By &-ind that value with + // the constant 7 we tell the compiler that the shift count is always + // less than 8 which is smaller than any register width. This allows + // the compiler to generate better code for the shift operation. + shift := uint(bits.TrailingZeros(uint(base))) & 7 + b := uint64(base) + m := uint(base) - 1 // == 1<= b { + i-- + a[i] = digits[uint(u)&m] + u >>= shift + } + // u < base + i-- + a[i] = digits[uint(u)] + } else { + // general case + b := uint64(base) + for u >= b { + i-- + // Avoid using r = a%b in addition to q = a/b + // since 64bit division and modulo operations + // are calculated by runtime functions on 32bit machines. + q := u / b + a[i] = digits[uint(u-q*b)] + u = q + } + // u < base + i-- + a[i] = digits[uint(u)] + } + + // add sign, if any + if neg { + i-- + a[i] = '-' + } + + if append_ { + d = append(dst, a[i:]...) + return + } + s = string(a[i:]) + return +} + +func isPowerOfTwo(x int) bool { + return x&(x-1) == 0 +} diff --git a/gnovm/stdlibs/strconv/itoa_test.gno b/gnovm/stdlibs/strconv/itoa_test.gno new file mode 100644 index 00000000000..b76acc78183 --- /dev/null +++ b/gnovm/stdlibs/strconv/itoa_test.gno @@ -0,0 +1,242 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package strconv + +import ( + "testing" +) + +type itob64Test struct { + in int64 + base int + out string +} + +var itob64tests = []itob64Test{ + {0, 10, "0"}, + {1, 10, "1"}, + {-1, 10, "-1"}, + {12345678, 10, "12345678"}, + {-987654321, 10, "-987654321"}, + {1<<31 - 1, 10, "2147483647"}, + {-1<<31 + 1, 10, "-2147483647"}, + {1 << 31, 10, "2147483648"}, + {-1 << 31, 10, "-2147483648"}, + {1<<31 + 1, 10, "2147483649"}, + {-1<<31 - 1, 10, "-2147483649"}, + {1<<32 - 1, 10, "4294967295"}, + {-1<<32 + 1, 10, "-4294967295"}, + {1 << 32, 10, "4294967296"}, + {-1 << 32, 10, "-4294967296"}, + {1<<32 + 1, 10, "4294967297"}, + {-1<<32 - 1, 10, "-4294967297"}, + {1 << 50, 10, "1125899906842624"}, + {1<<63 - 1, 10, "9223372036854775807"}, + {-1<<63 + 1, 10, "-9223372036854775807"}, + {-1 << 63, 10, "-9223372036854775808"}, + + {0, 2, "0"}, + {10, 2, "1010"}, + {-1, 2, "-1"}, + {1 << 15, 2, "1000000000000000"}, + + {-8, 8, "-10"}, + {057635436545, 8, "57635436545"}, + {1 << 24, 8, "100000000"}, + + {16, 16, "10"}, + {-0x123456789abcdef, 16, "-123456789abcdef"}, + {1<<63 - 1, 16, "7fffffffffffffff"}, + {1<<63 - 1, 2, "111111111111111111111111111111111111111111111111111111111111111"}, + {-1 << 63, 2, "-1000000000000000000000000000000000000000000000000000000000000000"}, + + {16, 17, "g"}, + {25, 25, "10"}, + {(((((17*35+24)*35+21)*35+34)*35+12)*35+24)*35 + 32, 35, "holycow"}, + {(((((17*36+24)*36+21)*36+34)*36+12)*36+24)*36 + 32, 36, "holycow"}, +} + +func TestItoa(t *testing.T) { + for _, test := range itob64tests { + s := FormatInt(test.in, test.base) + if s != test.out { + t.Errorf("FormatInt(%v, %v) = %v want %v", + test.in, test.base, s, test.out) + } + x := AppendInt([]byte("abc"), test.in, test.base) + if string(x) != "abc"+test.out { + t.Errorf("AppendInt(%q, %v, %v) = %q want %v", + "abc", test.in, test.base, x, test.out) + } + + if test.in >= 0 { + s := FormatUint(uint64(test.in), test.base) + if s != test.out { + t.Errorf("FormatUint(%v, %v) = %v want %v", + test.in, test.base, s, test.out) + } + x := AppendUint(nil, uint64(test.in), test.base) + if string(x) != test.out { + t.Errorf("AppendUint(%q, %v, %v) = %q want %v", + "abc", uint64(test.in), test.base, x, test.out) + } + } + + if test.base == 10 && int64(int(test.in)) == test.in { + s := Itoa(int(test.in)) + if s != test.out { + t.Errorf("Itoa(%v) = %v want %v", + test.in, s, test.out) + } + } + } + + // Override when base is illegal + defer func() { + if r := recover(); r == nil { + t.Fatalf("expected panic due to illegal base") + } + }() + FormatUint(12345678, 1) +} + +type uitob64Test struct { + in uint64 + base int + out string +} + +var uitob64tests = []uitob64Test{ + {1<<63 - 1, 10, "9223372036854775807"}, + {1 << 63, 10, "9223372036854775808"}, + {1<<63 + 1, 10, "9223372036854775809"}, + {1<<64 - 2, 10, "18446744073709551614"}, + {1<<64 - 1, 10, "18446744073709551615"}, + {1<<64 - 1, 2, "1111111111111111111111111111111111111111111111111111111111111111"}, +} + +func TestUitoa(t *testing.T) { + for _, test := range uitob64tests { + s := FormatUint(test.in, test.base) + if s != test.out { + t.Errorf("FormatUint(%v, %v) = %v want %v", + test.in, test.base, s, test.out) + } + x := AppendUint([]byte("abc"), test.in, test.base) + if string(x) != "abc"+test.out { + t.Errorf("AppendUint(%q, %v, %v) = %q want %v", + "abc", test.in, test.base, x, test.out) + } + + } +} + +var varlenUints = []struct { + in uint64 + out string +}{ + {1, "1"}, + {12, "12"}, + {123, "123"}, + {1234, "1234"}, + {12345, "12345"}, + {123456, "123456"}, + {1234567, "1234567"}, + {12345678, "12345678"}, + {123456789, "123456789"}, + {1234567890, "1234567890"}, + {12345678901, "12345678901"}, + {123456789012, "123456789012"}, + {1234567890123, "1234567890123"}, + {12345678901234, "12345678901234"}, + {123456789012345, "123456789012345"}, + {1234567890123456, "1234567890123456"}, + {12345678901234567, "12345678901234567"}, + {123456789012345678, "123456789012345678"}, + {1234567890123456789, "1234567890123456789"}, + {12345678901234567890, "12345678901234567890"}, +} + +func TestFormatUintVarlen(t *testing.T) { + for _, test := range varlenUints { + s := FormatUint(test.in, 10) + if s != test.out { + t.Errorf("FormatUint(%v, 10) = %v want %v", test.in, s, test.out) + } + } +} + +func BenchmarkFormatInt(b *testing.B) { + for i := 0; i < b.N; i++ { + for _, test := range itob64tests { + s := FormatInt(test.in, test.base) + BenchSink += len(s) + } + } +} + +func BenchmarkAppendInt(b *testing.B) { + dst := make([]byte, 0, 30) + for i := 0; i < b.N; i++ { + for _, test := range itob64tests { + dst = AppendInt(dst[:0], test.in, test.base) + BenchSink += len(dst) + } + } +} + +func BenchmarkFormatUint(b *testing.B) { + for i := 0; i < b.N; i++ { + for _, test := range uitob64tests { + s := FormatUint(test.in, test.base) + BenchSink += len(s) + } + } +} + +func BenchmarkAppendUint(b *testing.B) { + dst := make([]byte, 0, 30) + for i := 0; i < b.N; i++ { + for _, test := range uitob64tests { + dst = AppendUint(dst[:0], test.in, test.base) + BenchSink += len(dst) + } + } +} + +func BenchmarkFormatIntSmall(b *testing.B) { + smallInts := []int64{7, 42} + for _, smallInt := range smallInts { + b.Run(Itoa(int(smallInt)), func(b *testing.B) { + for i := 0; i < b.N; i++ { + s := FormatInt(smallInt, 10) + BenchSink += len(s) + } + }) + } +} + +func BenchmarkAppendIntSmall(b *testing.B) { + dst := make([]byte, 0, 30) + const smallInt = 42 + for i := 0; i < b.N; i++ { + dst = AppendInt(dst[:0], smallInt, 10) + BenchSink += len(dst) + } +} + +func BenchmarkAppendUintVarlen(b *testing.B) { + for _, test := range varlenUints { + b.Run(test.out, func(b *testing.B) { + dst := make([]byte, 0, 30) + for j := 0; j < b.N; j++ { + dst = AppendUint(dst[:0], test.in, 10) + BenchSink += len(dst) + } + }) + } +} + +var BenchSink int // make sure compiler cannot optimize away benchmarks diff --git a/gnovm/stdlibs/strconv/quote.gno b/gnovm/stdlibs/strconv/quote.gno new file mode 100644 index 00000000000..7c384336795 --- /dev/null +++ b/gnovm/stdlibs/strconv/quote.gno @@ -0,0 +1,599 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:generate go run makeisprint.go -output isprint.go + +package strconv + +import ( + "unicode/utf8" +) + +const ( + lowerhex = "0123456789abcdef" + upperhex = "0123456789ABCDEF" +) + +// contains reports whether the string contains the byte c. +func contains(s string, c byte) bool { + return index(s, c) != -1 +} + +func quoteWith(s string, quote byte, ASCIIonly, graphicOnly bool) string { + return string(appendQuotedWith(make([]byte, 0, 3*len(s)/2), s, quote, ASCIIonly, graphicOnly)) +} + +func quoteRuneWith(r rune, quote byte, ASCIIonly, graphicOnly bool) string { + return string(appendQuotedRuneWith(nil, r, quote, ASCIIonly, graphicOnly)) +} + +func appendQuotedWith(buf []byte, s string, quote byte, ASCIIonly, graphicOnly bool) []byte { + // Often called with big strings, so preallocate. If there's quoting, + // this is conservative but still helps a lot. + if cap(buf)-len(buf) < len(s) { + nBuf := make([]byte, len(buf), len(buf)+1+len(s)+1) + copy(nBuf, buf) + buf = nBuf + } + buf = append(buf, quote) + for width := 0; len(s) > 0; s = s[width:] { + r := rune(s[0]) + width = 1 + if r >= utf8.RuneSelf { + r, width = utf8.DecodeRuneInString(s) + } + if width == 1 && r == utf8.RuneError { + buf = append(buf, `\x`...) + buf = append(buf, lowerhex[s[0]>>4]) + buf = append(buf, lowerhex[s[0]&0xF]) + continue + } + buf = appendEscapedRune(buf, r, quote, ASCIIonly, graphicOnly) + } + buf = append(buf, quote) + return buf +} + +func appendQuotedRuneWith(buf []byte, r rune, quote byte, ASCIIonly, graphicOnly bool) []byte { + buf = append(buf, quote) + if !utf8.ValidRune(r) { + r = utf8.RuneError + } + buf = appendEscapedRune(buf, r, quote, ASCIIonly, graphicOnly) + buf = append(buf, quote) + return buf +} + +func appendEscapedRune(buf []byte, r rune, quote byte, ASCIIonly, graphicOnly bool) []byte { + if r == rune(quote) || r == '\\' { // always backslashed + buf = append(buf, '\\') + buf = append(buf, byte(r)) + return buf + } + if ASCIIonly { + if r < utf8.RuneSelf && IsPrint(r) { + buf = append(buf, byte(r)) + return buf + } + } else if IsPrint(r) || graphicOnly && isInGraphicList(r) { + return utf8.AppendRune(buf, r) + } + switch r { + case '\a': + buf = append(buf, `\a`...) + case '\b': + buf = append(buf, `\b`...) + case '\f': + buf = append(buf, `\f`...) + case '\n': + buf = append(buf, `\n`...) + case '\r': + buf = append(buf, `\r`...) + case '\t': + buf = append(buf, `\t`...) + case '\v': + buf = append(buf, `\v`...) + default: + switch { + case r < ' ' || r == 0x7f: + buf = append(buf, `\x`...) + buf = append(buf, lowerhex[byte(r)>>4]) + buf = append(buf, lowerhex[byte(r)&0xF]) + case !utf8.ValidRune(r): + r = 0xFFFD + fallthrough + case r < 0x10000: + buf = append(buf, `\u`...) + for s := 12; s >= 0; s -= 4 { + buf = append(buf, lowerhex[r>>uint(s)&0xF]) + } + default: + buf = append(buf, `\U`...) + for s := 28; s >= 0; s -= 4 { + buf = append(buf, lowerhex[r>>uint(s)&0xF]) + } + } + } + return buf +} + +// Quote returns a double-quoted Go string literal representing s. The +// returned string uses Go escape sequences (\t, \n, \xFF, \u0100) for +// control characters and non-printable characters as defined by +// IsPrint. +func Quote(s string) string { + return quoteWith(s, '"', false, false) +} + +// AppendQuote appends a double-quoted Go string literal representing s, +// as generated by Quote, to dst and returns the extended buffer. +func AppendQuote(dst []byte, s string) []byte { + return appendQuotedWith(dst, s, '"', false, false) +} + +// QuoteToASCII returns a double-quoted Go string literal representing s. +// The returned string uses Go escape sequences (\t, \n, \xFF, \u0100) for +// non-ASCII characters and non-printable characters as defined by IsPrint. +func QuoteToASCII(s string) string { + return quoteWith(s, '"', true, false) +} + +// AppendQuoteToASCII appends a double-quoted Go string literal representing s, +// as generated by QuoteToASCII, to dst and returns the extended buffer. +func AppendQuoteToASCII(dst []byte, s string) []byte { + return appendQuotedWith(dst, s, '"', true, false) +} + +// QuoteToGraphic returns a double-quoted Go string literal representing s. +// The returned string leaves Unicode graphic characters, as defined by +// IsGraphic, unchanged and uses Go escape sequences (\t, \n, \xFF, \u0100) +// for non-graphic characters. +func QuoteToGraphic(s string) string { + return quoteWith(s, '"', false, true) +} + +// AppendQuoteToGraphic appends a double-quoted Go string literal representing s, +// as generated by QuoteToGraphic, to dst and returns the extended buffer. +func AppendQuoteToGraphic(dst []byte, s string) []byte { + return appendQuotedWith(dst, s, '"', false, true) +} + +// QuoteRune returns a single-quoted Go character literal representing the +// rune. The returned string uses Go escape sequences (\t, \n, \xFF, \u0100) +// for control characters and non-printable characters as defined by IsPrint. +// If r is not a valid Unicode code point, it is interpreted as the Unicode +// replacement character U+FFFD. +func QuoteRune(r rune) string { + return quoteRuneWith(r, '\'', false, false) +} + +// AppendQuoteRune appends a single-quoted Go character literal representing the rune, +// as generated by QuoteRune, to dst and returns the extended buffer. +func AppendQuoteRune(dst []byte, r rune) []byte { + return appendQuotedRuneWith(dst, r, '\'', false, false) +} + +// QuoteRuneToASCII returns a single-quoted Go character literal representing +// the rune. The returned string uses Go escape sequences (\t, \n, \xFF, +// \u0100) for non-ASCII characters and non-printable characters as defined +// by IsPrint. +// If r is not a valid Unicode code point, it is interpreted as the Unicode +// replacement character U+FFFD. +func QuoteRuneToASCII(r rune) string { + return quoteRuneWith(r, '\'', true, false) +} + +// AppendQuoteRuneToASCII appends a single-quoted Go character literal representing the rune, +// as generated by QuoteRuneToASCII, to dst and returns the extended buffer. +func AppendQuoteRuneToASCII(dst []byte, r rune) []byte { + return appendQuotedRuneWith(dst, r, '\'', true, false) +} + +// QuoteRuneToGraphic returns a single-quoted Go character literal representing +// the rune. If the rune is not a Unicode graphic character, +// as defined by IsGraphic, the returned string will use a Go escape sequence +// (\t, \n, \xFF, \u0100). +// If r is not a valid Unicode code point, it is interpreted as the Unicode +// replacement character U+FFFD. +func QuoteRuneToGraphic(r rune) string { + return quoteRuneWith(r, '\'', false, true) +} + +// AppendQuoteRuneToGraphic appends a single-quoted Go character literal representing the rune, +// as generated by QuoteRuneToGraphic, to dst and returns the extended buffer. +func AppendQuoteRuneToGraphic(dst []byte, r rune) []byte { + return appendQuotedRuneWith(dst, r, '\'', false, true) +} + +// CanBackquote reports whether the string s can be represented +// unchanged as a single-line backquoted string without control +// characters other than tab. +func CanBackquote(s string) bool { + for len(s) > 0 { + r, wid := utf8.DecodeRuneInString(s) + s = s[wid:] + if wid > 1 { + if r == '\ufeff' { + return false // BOMs are invisible and should not be quoted. + } + continue // All other multibyte runes are correctly encoded and assumed printable. + } + if r == utf8.RuneError { + return false + } + if (r < ' ' && r != '\t') || r == '`' || r == '\u007F' { + return false + } + } + return true +} + +func unhex(b byte) (v rune, ok bool) { + c := rune(b) + switch { + case '0' <= c && c <= '9': + return c - '0', true + case 'a' <= c && c <= 'f': + return c - 'a' + 10, true + case 'A' <= c && c <= 'F': + return c - 'A' + 10, true + } + return +} + +// UnquoteChar decodes the first character or byte in the escaped string +// or character literal represented by the string s. +// It returns four values: +// +// 1. value, the decoded Unicode code point or byte value; +// 2. multibyte, a boolean indicating whether the decoded character requires a multibyte UTF-8 representation; +// 3. tail, the remainder of the string after the character; and +// 4. an error that will be nil if the character is syntactically valid. +// +// The second argument, quote, specifies the type of literal being parsed +// and therefore which escaped quote character is permitted. +// If set to a single quote, it permits the sequence \' and disallows unescaped '. +// If set to a double quote, it permits \" and disallows unescaped ". +// If set to zero, it does not permit either escape and allows both quote characters to appear unescaped. +func UnquoteChar(s string, quote byte) (value rune, multibyte bool, tail string, err error) { + // easy cases + if len(s) == 0 { + err = ErrSyntax + return + } + switch c := s[0]; { + case c == quote && (quote == '\'' || quote == '"'): + err = ErrSyntax + return + case c >= utf8.RuneSelf: + r, size := utf8.DecodeRuneInString(s) + return r, true, s[size:], nil + case c != '\\': + return rune(s[0]), false, s[1:], nil + } + + // hard case: c is backslash + if len(s) <= 1 { + err = ErrSyntax + return + } + c := s[1] + s = s[2:] + + switch c { + case 'a': + value = '\a' + case 'b': + value = '\b' + case 'f': + value = '\f' + case 'n': + value = '\n' + case 'r': + value = '\r' + case 't': + value = '\t' + case 'v': + value = '\v' + case 'x', 'u', 'U': + n := 0 + switch c { + case 'x': + n = 2 + case 'u': + n = 4 + case 'U': + n = 8 + } + var v rune + if len(s) < n { + err = ErrSyntax + return + } + for j := 0; j < n; j++ { + x, ok := unhex(s[j]) + if !ok { + err = ErrSyntax + return + } + v = v<<4 | x + } + s = s[n:] + if c == 'x' { + // single-byte string, possibly not UTF-8 + value = v + break + } + if !utf8.ValidRune(v) { + err = ErrSyntax + return + } + value = v + multibyte = true + case '0', '1', '2', '3', '4', '5', '6', '7': + v := rune(c) - '0' + if len(s) < 2 { + err = ErrSyntax + return + } + for j := 0; j < 2; j++ { // one digit already; two more + x := rune(s[j]) - '0' + if x < 0 || x > 7 { + err = ErrSyntax + return + } + v = (v << 3) | x + } + s = s[2:] + if v > 255 { + err = ErrSyntax + return + } + value = v + case '\\': + value = '\\' + case '\'', '"': + if c != quote { + err = ErrSyntax + return + } + value = rune(c) + default: + err = ErrSyntax + return + } + tail = s + return +} + +// QuotedPrefix returns the quoted string (as understood by Unquote) at the prefix of s. +// If s does not start with a valid quoted string, QuotedPrefix returns an error. +func QuotedPrefix(s string) (string, error) { + out, _, err := unquote(s, false) + return out, err +} + +// Unquote interprets s as a single-quoted, double-quoted, +// or backquoted Go string literal, returning the string value +// that s quotes. (If s is single-quoted, it would be a Go +// character literal; Unquote returns the corresponding +// one-character string.) +func Unquote(s string) (string, error) { + out, rem, err := unquote(s, true) + if len(rem) > 0 { + return "", ErrSyntax + } + return out, err +} + +// unquote parses a quoted string at the start of the input, +// returning the parsed prefix, the remaining suffix, and any parse errors. +// If unescape is true, the parsed prefix is unescaped, +// otherwise the input prefix is provided verbatim. +func unquote(in string, unescape bool) (out, rem string, err error) { + // Determine the quote form and optimistically find the terminating quote. + if len(in) < 2 { + return "", in, ErrSyntax + } + quote := in[0] + end := index(in[1:], quote) + if end < 0 { + return "", in, ErrSyntax + } + end += 2 // position after terminating quote; may be wrong if escape sequences are present + + switch quote { + case '`': + switch { + case !unescape: + out = in[:end] // include quotes + case !contains(in[:end], '\r'): + out = in[len("`") : end-len("`")] // exclude quotes + default: + // Carriage return characters ('\r') inside raw string literals + // are discarded from the raw string value. + buf := make([]byte, 0, end-len("`")-len("\r")-len("`")) + for i := len("`"); i < end-len("`"); i++ { + if in[i] != '\r' { + buf = append(buf, in[i]) + } + } + out = string(buf) + } + // NOTE: Prior implementations did not verify that raw strings consist + // of valid UTF-8 characters and we continue to not verify it as such. + // The Go specification does not explicitly require valid UTF-8, + // but only mention that it is implicitly valid for Go source code + // (which must be valid UTF-8). + return out, in[end:], nil + case '"', '\'': + // Handle quoted strings without any escape sequences. + if !contains(in[:end], '\\') && !contains(in[:end], '\n') { + var valid bool + switch quote { + case '"': + valid = utf8.ValidString(in[len(`"`) : end-len(`"`)]) + case '\'': + r, n := utf8.DecodeRuneInString(in[len("'") : end-len("'")]) + valid = len("'")+n+len("'") == end && (r != utf8.RuneError || n != 1) + } + if valid { + out = in[:end] + if unescape { + out = out[1 : end-1] // exclude quotes + } + return out, in[end:], nil + } + } + + // Handle quoted strings with escape sequences. + var buf []byte + in0 := in + in = in[1:] // skip starting quote + if unescape { + buf = make([]byte, 0, 3*end/2) // try to avoid more allocations + } + for len(in) > 0 && in[0] != quote { + // Process the next character, + // rejecting any unescaped newline characters which are invalid. + r, multibyte, rem, err := UnquoteChar(in, quote) + if in[0] == '\n' || err != nil { + return "", in0, ErrSyntax + } + in = rem + + // Append the character if unescaping the input. + if unescape { + if r < utf8.RuneSelf || !multibyte { + buf = append(buf, byte(r)) + } else { + buf = utf8.AppendRune(buf, r) + } + } + + // Single quoted strings must be a single character. + if quote == '\'' { + break + } + } + + // Verify that the string ends with a terminating quote. + if !(len(in) > 0 && in[0] == quote) { + return "", in0, ErrSyntax + } + in = in[1:] // skip terminating quote + + if unescape { + return string(buf), in, nil + } + return in0[:len(in0)-len(in)], in, nil + default: + return "", in, ErrSyntax + } +} + +// bsearch16 returns the smallest i such that a[i] >= x. +// If there is no such i, bsearch16 returns len(a). +func bsearch16(a []uint16, x uint16) int { + i, j := 0, len(a) + for i < j { + h := i + (j-i)>>1 + if a[h] < x { + i = h + 1 + } else { + j = h + } + } + return i +} + +// bsearch32 returns the smallest i such that a[i] >= x. +// If there is no such i, bsearch32 returns len(a). +func bsearch32(a []uint32, x uint32) int { + i, j := 0, len(a) + for i < j { + h := i + (j-i)>>1 + if a[h] < x { + i = h + 1 + } else { + j = h + } + } + return i +} + +// TODO: IsPrint is a local implementation of unicode.IsPrint, verified by the tests +// to give the same answer. It allows this package not to depend on unicode, +// and therefore not pull in all the Unicode tables. If the linker were better +// at tossing unused tables, we could get rid of this implementation. +// That would be nice. + +// IsPrint reports whether the rune is defined as printable by Go, with +// the same definition as unicode.IsPrint: letters, numbers, punctuation, +// symbols and ASCII space. +func IsPrint(r rune) bool { + // Fast check for Latin-1 + if r <= 0xFF { + if 0x20 <= r && r <= 0x7E { + // All the ASCII is printable from space through DEL-1. + return true + } + if 0xA1 <= r && r <= 0xFF { + // Similarly for ¡ through ÿ... + return r != 0xAD // ...except for the bizarre soft hyphen. + } + return false + } + + // Same algorithm, either on uint16 or uint32 value. + // First, find first i such that isPrint[i] >= x. + // This is the index of either the start or end of a pair that might span x. + // The start is even (isPrint[i&^1]) and the end is odd (isPrint[i|1]). + // If we find x in a range, make sure x is not in isNotPrint list. + + if 0 <= r && r < 1<<16 { + rr, isPrint, isNotPrint := uint16(r), isPrint16, isNotPrint16 + i := bsearch16(isPrint, rr) + if i >= len(isPrint) || rr < isPrint[i&^1] || isPrint[i|1] < rr { + return false + } + j := bsearch16(isNotPrint, rr) + return j >= len(isNotPrint) || isNotPrint[j] != rr + } + + rr, isPrint, isNotPrint := uint32(r), isPrint32, isNotPrint32 + i := bsearch32(isPrint, rr) + if i >= len(isPrint) || rr < isPrint[i&^1] || isPrint[i|1] < rr { + return false + } + if r >= 0x20000 { + return true + } + r -= 0x10000 + j := bsearch16(isNotPrint, uint16(r)) + return j >= len(isNotPrint) || isNotPrint[j] != uint16(r) +} + +// IsGraphic reports whether the rune is defined as a Graphic by Unicode. Such +// characters include letters, marks, numbers, punctuation, symbols, and +// spaces, from categories L, M, N, P, S, and Zs. +func IsGraphic(r rune) bool { + if IsPrint(r) { + return true + } + return isInGraphicList(r) +} + +// isInGraphicList reports whether the rune is in the isGraphic list. This separation +// from IsGraphic allows quoteWith to avoid two calls to IsPrint. +// Should be called only if IsPrint fails. +func isInGraphicList(r rune) bool { + // We know r must fit in 16 bits - see makeisprint.go. + if r > 0xFFFF { + return false + } + rr := uint16(r) + i := bsearch16(isGraphic, rr) + return i < len(isGraphic) && rr == isGraphic[i] +} diff --git a/gnovm/stdlibs/strconv/quote_test.gno b/gnovm/stdlibs/strconv/quote_test.gno new file mode 100644 index 00000000000..b11e95461b0 --- /dev/null +++ b/gnovm/stdlibs/strconv/quote_test.gno @@ -0,0 +1,383 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package strconv + +import ( + "strings" + "testing" + "unicode" +) + +// Verify that our IsPrint agrees with unicode.IsPrint. +func TestIsPrint(t *testing.T) { + n := 0 + for r := rune(0); r <= unicode.MaxRune; r++ { + if IsPrint(r) != unicode.IsPrint(r) { + t.Errorf("IsPrint(%U)=%t incorrect", r, IsPrint(r)) + n++ + if n > 10 { + return + } + } + } +} + +// Verify that our IsGraphic agrees with unicode.IsGraphic. +func TestIsGraphic(t *testing.T) { + n := 0 + for r := rune(0); r <= unicode.MaxRune; r++ { + if IsGraphic(r) != unicode.IsGraphic(r) { + t.Errorf("IsGraphic(%U)=%t incorrect", r, IsGraphic(r)) + n++ + if n > 10 { + return + } + } + } +} + +type quoteTest struct { + in string + out string + ascii string + graphic string +} + +var quotetests = []quoteTest{ + {"\a\b\f\r\n\t\v", `"\a\b\f\r\n\t\v"`, `"\a\b\f\r\n\t\v"`, `"\a\b\f\r\n\t\v"`}, + {"\\", `"\\"`, `"\\"`, `"\\"`}, + {"abc\xffdef", `"abc\xffdef"`, `"abc\xffdef"`, `"abc\xffdef"`}, + {"\u263a", `"☺"`, `"\u263a"`, `"☺"`}, + {"\U0010ffff", `"\U0010ffff"`, `"\U0010ffff"`, `"\U0010ffff"`}, + {"\x04", `"\x04"`, `"\x04"`, `"\x04"`}, + // Some non-printable but graphic runes. Final column is double-quoted. + {"!\u00a0!\u2000!\u3000!", `"!\u00a0!\u2000!\u3000!"`, `"!\u00a0!\u2000!\u3000!"`, "\"!\u00a0!\u2000!\u3000!\""}, + {"\x7f", `"\x7f"`, `"\x7f"`, `"\x7f"`}, +} + +func TestQuote(t *testing.T) { + for _, tt := range quotetests { + if out := Quote(tt.in); out != tt.out { + t.Errorf("Quote(%s) = %s, want %s", tt.in, out, tt.out) + } + if out := AppendQuote([]byte("abc"), tt.in); string(out) != "abc"+tt.out { + t.Errorf("AppendQuote(%q, %s) = %s, want %s", "abc", tt.in, out, "abc"+tt.out) + } + } +} + +func TestQuoteToASCII(t *testing.T) { + for _, tt := range quotetests { + if out := QuoteToASCII(tt.in); out != tt.ascii { + t.Errorf("QuoteToASCII(%s) = %s, want %s", tt.in, out, tt.ascii) + } + if out := AppendQuoteToASCII([]byte("abc"), tt.in); string(out) != "abc"+tt.ascii { + t.Errorf("AppendQuoteToASCII(%q, %s) = %s, want %s", "abc", tt.in, out, "abc"+tt.ascii) + } + } +} + +func TestQuoteToGraphic(t *testing.T) { + for _, tt := range quotetests { + if out := QuoteToGraphic(tt.in); out != tt.graphic { + t.Errorf("QuoteToGraphic(%s) = %s, want %s", tt.in, out, tt.graphic) + } + if out := AppendQuoteToGraphic([]byte("abc"), tt.in); string(out) != "abc"+tt.graphic { + t.Errorf("AppendQuoteToGraphic(%q, %s) = %s, want %s", "abc", tt.in, out, "abc"+tt.graphic) + } + } +} + +func BenchmarkQuote(b *testing.B) { + for i := 0; i < b.N; i++ { + Quote("\a\b\f\r\n\t\v\a\b\f\r\n\t\v\a\b\f\r\n\t\v") + } +} + +func BenchmarkQuoteRune(b *testing.B) { + for i := 0; i < b.N; i++ { + QuoteRune('\a') + } +} + +var benchQuoteBuf []byte + +func BenchmarkAppendQuote(b *testing.B) { + for i := 0; i < b.N; i++ { + benchQuoteBuf = AppendQuote(benchQuoteBuf[:0], "\a\b\f\r\n\t\v\a\b\f\r\n\t\v\a\b\f\r\n\t\v") + } +} + +var benchQuoteRuneBuf []byte + +func BenchmarkAppendQuoteRune(b *testing.B) { + for i := 0; i < b.N; i++ { + benchQuoteRuneBuf = AppendQuoteRune(benchQuoteRuneBuf[:0], '\a') + } +} + +type quoteRuneTest struct { + in rune + out string + ascii string + graphic string +} + +var quoterunetests = []quoteRuneTest{ + {'a', `'a'`, `'a'`, `'a'`}, + {'\a', `'\a'`, `'\a'`, `'\a'`}, + {'\\', `'\\'`, `'\\'`, `'\\'`}, + {0xFF, `'ÿ'`, `'\u00ff'`, `'ÿ'`}, + {0x263a, `'☺'`, `'\u263a'`, `'☺'`}, + {0xdead, `'�'`, `'\ufffd'`, `'�'`}, + {0xfffd, `'�'`, `'\ufffd'`, `'�'`}, + {0x0010ffff, `'\U0010ffff'`, `'\U0010ffff'`, `'\U0010ffff'`}, + {0x0010ffff + 1, `'�'`, `'\ufffd'`, `'�'`}, + {0x04, `'\x04'`, `'\x04'`, `'\x04'`}, + // Some differences between graphic and printable. Note the last column is double-quoted. + {'\u00a0', `'\u00a0'`, `'\u00a0'`, "'\u00a0'"}, + {'\u2000', `'\u2000'`, `'\u2000'`, "'\u2000'"}, + {'\u3000', `'\u3000'`, `'\u3000'`, "'\u3000'"}, +} + +func TestQuoteRune(t *testing.T) { + for _, tt := range quoterunetests { + if out := QuoteRune(tt.in); out != tt.out { + t.Errorf("QuoteRune(%U) = %s, want %s", tt.in, out, tt.out) + } + if out := AppendQuoteRune([]byte("abc"), tt.in); string(out) != "abc"+tt.out { + t.Errorf("AppendQuoteRune(%q, %U) = %s, want %s", "abc", tt.in, out, "abc"+tt.out) + } + } +} + +func TestQuoteRuneToASCII(t *testing.T) { + for _, tt := range quoterunetests { + if out := QuoteRuneToASCII(tt.in); out != tt.ascii { + t.Errorf("QuoteRuneToASCII(%U) = %s, want %s", tt.in, out, tt.ascii) + } + if out := AppendQuoteRuneToASCII([]byte("abc"), tt.in); string(out) != "abc"+tt.ascii { + t.Errorf("AppendQuoteRuneToASCII(%q, %U) = %s, want %s", "abc", tt.in, out, "abc"+tt.ascii) + } + } +} + +func TestQuoteRuneToGraphic(t *testing.T) { + for _, tt := range quoterunetests { + if out := QuoteRuneToGraphic(tt.in); out != tt.graphic { + t.Errorf("QuoteRuneToGraphic(%U) = %s, want %s", tt.in, out, tt.graphic) + } + if out := AppendQuoteRuneToGraphic([]byte("abc"), tt.in); string(out) != "abc"+tt.graphic { + t.Errorf("AppendQuoteRuneToGraphic(%q, %U) = %s, want %s", "abc", tt.in, out, "abc"+tt.graphic) + } + } +} + +type canBackquoteTest struct { + in string + out bool +} + +var canbackquotetests = []canBackquoteTest{ + {"`", false}, + {string(rune(0)), false}, + {string(rune(1)), false}, + {string(rune(2)), false}, + {string(rune(3)), false}, + {string(rune(4)), false}, + {string(rune(5)), false}, + {string(rune(6)), false}, + {string(rune(7)), false}, + {string(rune(8)), false}, + {string(rune(9)), true}, // \t + {string(rune(10)), false}, + {string(rune(11)), false}, + {string(rune(12)), false}, + {string(rune(13)), false}, + {string(rune(14)), false}, + {string(rune(15)), false}, + {string(rune(16)), false}, + {string(rune(17)), false}, + {string(rune(18)), false}, + {string(rune(19)), false}, + {string(rune(20)), false}, + {string(rune(21)), false}, + {string(rune(22)), false}, + {string(rune(23)), false}, + {string(rune(24)), false}, + {string(rune(25)), false}, + {string(rune(26)), false}, + {string(rune(27)), false}, + {string(rune(28)), false}, + {string(rune(29)), false}, + {string(rune(30)), false}, + {string(rune(31)), false}, + {string(rune(0x7F)), false}, + {`' !"#$%&'()*+,-./:;<=>?@[\]^_{|}~`, true}, + {`0123456789`, true}, + {`ABCDEFGHIJKLMNOPQRSTUVWXYZ`, true}, + {`abcdefghijklmnopqrstuvwxyz`, true}, + {`☺`, true}, + {"\x80", false}, + {"a\xe0\xa0z", false}, + {"\ufeffabc", false}, + {"a\ufeffz", false}, +} + +func TestCanBackquote(t *testing.T) { + for _, tt := range canbackquotetests { + if out := CanBackquote(tt.in); out != tt.out { + t.Errorf("CanBackquote(%q) = %v, want %v", tt.in, out, tt.out) + } + } +} + +type unQuoteTest struct { + in string + out string +} + +var unquotetests = []unQuoteTest{ + {`""`, ""}, + {`"a"`, "a"}, + {`"abc"`, "abc"}, + {`"☺"`, "☺"}, + {`"hello world"`, "hello world"}, + {`"\xFF"`, "\xFF"}, + {`"\377"`, "\377"}, + {`"\u1234"`, "\u1234"}, + {`"\U00010111"`, "\U00010111"}, + {`"\U0001011111"`, "\U0001011111"}, + {`"\a\b\f\n\r\t\v\\\""`, "\a\b\f\n\r\t\v\\\""}, + {`"'"`, "'"}, + + {`'a'`, "a"}, + {`'☹'`, "☹"}, + {`'\a'`, "\a"}, + {`'\x10'`, "\x10"}, + {`'\377'`, "\377"}, + {`'\u1234'`, "\u1234"}, + {`'\U00010111'`, "\U00010111"}, + {`'\t'`, "\t"}, + {`' '`, " "}, + {`'\''`, "'"}, + {`'"'`, "\""}, + + {"``", ``}, + {"`a`", `a`}, + {"`abc`", `abc`}, + {"`☺`", `☺`}, + {"`hello world`", `hello world`}, + {"`\\xFF`", `\xFF`}, + {"`\\377`", `\377`}, + {"`\\`", `\`}, + {"`\n`", "\n"}, + {"` `", ` `}, + {"` `", ` `}, + {"`a\rb`", "ab"}, +} + +var misquoted = []string{ + ``, + `"`, + `"a`, + `"'`, + `b"`, + `"\"`, + `"\9"`, + `"\19"`, + `"\129"`, + `'\'`, + `'\9'`, + `'\19'`, + `'\129'`, + `'ab'`, + `"\x1!"`, + `"\U12345678"`, + `"\z"`, + "`", + "`xxx", + "``x\r", + "`\"", + `"\'"`, + `'\"'`, + "\"\n\"", + "\"\\n\n\"", + "'\n'", + `"\udead"`, + `"\ud83d\ude4f"`, +} + +func TestUnquote(t *testing.T) { + for _, tt := range unquotetests { + testUnquote(t, tt.in, tt.out, nil) + } + for _, tt := range quotetests { + testUnquote(t, tt.out, tt.in, nil) + } + for _, s := range misquoted { + testUnquote(t, s, "", ErrSyntax) + } +} + +// Issue 23685: invalid UTF-8 should not go through the fast path. +func TestUnquoteInvalidUTF8(t *testing.T) { + tests := []struct { + in string + + // one of: + want string + wantErr error + }{ + {in: `"foo"`, want: "foo"}, + {in: `"foo`, wantErr: ErrSyntax}, + {in: `"` + "\xc0" + `"`, want: "\xef\xbf\xbd"}, + {in: `"a` + "\xc0" + `"`, want: "a\xef\xbf\xbd"}, + {in: `"\t` + "\xc0" + `"`, want: "\t\xef\xbf\xbd"}, + } + for _, tt := range tests { + testUnquote(t, tt.in, tt.want, tt.wantErr) + } +} + +func testUnquote(t *testing.T, in, want string, wantErr error) { + // Test Unquote. + got, gotErr := Unquote(in) + if got != want || gotErr != wantErr { + t.Errorf("Unquote(%q) = (%q, %v), want (%q, %v)", in, got, gotErr, want, wantErr) + } + + // Test QuotedPrefix. + // Adding an arbitrary suffix should not change the result of QuotedPrefix + // assume that the suffix doesn't accidentally terminate a truncated input. + if gotErr == nil { + want = in + } + suffix := "\n\r\\\"`'" // special characters for quoted strings + if len(in) > 0 { + suffix = strings.ReplaceAll(suffix, in[:1], "") + } + in += suffix + got, gotErr = QuotedPrefix(in) + if gotErr == nil && wantErr != nil { + _, wantErr = Unquote(got) // original input had trailing junk, reparse with only valid prefix + want = got + } + if got != want || gotErr != wantErr { + t.Errorf("QuotedPrefix(%q) = (%q, %v), want (%q, %v)", in, got, gotErr, want, wantErr) + } +} + +func BenchmarkUnquoteEasy(b *testing.B) { + for i := 0; i < b.N; i++ { + Unquote(`"Give me a rock, paper and scissors and I will move the world."`) + } +} + +func BenchmarkUnquoteHard(b *testing.B) { + for i := 0; i < b.N; i++ { + Unquote(`"\x47ive me a \x72ock, \x70aper and \x73cissors and \x49 will move the world."`) + } +} diff --git a/gnovm/stdlibs/strconv/strconv.gno b/gnovm/stdlibs/strconv/strconv.gno deleted file mode 100644 index bc7b5d8d1b6..00000000000 --- a/gnovm/stdlibs/strconv/strconv.gno +++ /dev/null @@ -1,10 +0,0 @@ -package strconv - -func Itoa(n int) string // injected -func AppendUint(dst []byte, i uint64, base int) []byte // injected -func Atoi(s string) (int, error) // injected -func CanBackquote(s string) bool // injected -func FormatInt(i int64, base int) string // injected -func FormatUint(i uint64, base int) string // injected -func Quote(s string) string // injected -func QuoteToASCII(s string) string // injected diff --git a/gnovm/stdlibs/strconv/strconv.go b/gnovm/stdlibs/strconv/strconv.go deleted file mode 100644 index 782a63e84b6..00000000000 --- a/gnovm/stdlibs/strconv/strconv.go +++ /dev/null @@ -1,12 +0,0 @@ -package strconv - -import "strconv" - -func Itoa(n int) string { return strconv.Itoa(n) } -func AppendUint(dst []byte, i uint64, base int) []byte { return strconv.AppendUint(dst, i, base) } -func Atoi(s string) (int, error) { return strconv.Atoi(s) } -func CanBackquote(s string) bool { return strconv.CanBackquote(s) } -func FormatInt(i int64, base int) string { return strconv.FormatInt(i, base) } -func FormatUint(i uint64, base int) string { return strconv.FormatUint(i, base) } -func Quote(s string) string { return strconv.Quote(s) } -func QuoteToASCII(r string) string { return strconv.QuoteToASCII(r) } diff --git a/gnovm/stdlibs/strconv/strconv_test.gno b/gnovm/stdlibs/strconv/strconv_test.gno new file mode 100644 index 00000000000..5421ae84a93 --- /dev/null +++ b/gnovm/stdlibs/strconv/strconv_test.gno @@ -0,0 +1,156 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package strconv + +import ( + "strings" + "testing" +) + +var ( + globalBuf [64]byte + nextToOne = "1.00000000000000011102230246251565404236316680908203125" + strings.Repeat("0", 10000) + "1" + oneMB = make([]byte, 1e6) + + mallocTest = []struct { + count int + desc string + fn func() + }{ + {0, `AppendInt(localBuf[:0], 123, 10)`, func() { + var localBuf [64]byte + AppendInt(localBuf[:0], 123, 10) + }}, + {0, `AppendInt(globalBuf[:0], 123, 10)`, func() { AppendInt(globalBuf[:0], 123, 10) }}, + {0, `AppendFloat(localBuf[:0], 1.23, 'g', 5, 64)`, func() { + var localBuf [64]byte + AppendFloat(localBuf[:0], 1.23, 'g', 5, 64) + }}, + {0, `AppendFloat(globalBuf[:0], 1.23, 'g', 5, 64)`, func() { AppendFloat(globalBuf[:0], 1.23, 'g', 5, 64) }}, + // In practice we see 7 for the next one, but allow some slop. + // Before pre-allocation in appendQuotedWith, we saw 39. + {10, `AppendQuoteToASCII(nil, oneMB)`, func() { AppendQuoteToASCII(nil, string(oneMB)) }}, + {0, `ParseFloat("123.45", 64)`, func() { ParseFloat("123.45", 64) }}, + {0, `ParseFloat("123.456789123456789", 64)`, func() { ParseFloat("123.456789123456789", 64) }}, + {0, `ParseFloat("1.000000000000000111022302462515654042363166809082031251", 64)`, func() { + ParseFloat("1.000000000000000111022302462515654042363166809082031251", 64) + }}, + {0, `ParseFloat("1.0000000000000001110223024625156540423631668090820312500...001", 64)`, func() { + ParseFloat(nextToOne, 64) + }}, + } +) + +// XXX: removed due to lack of AllocsPerRun +// func TestCountMallocs(t *testing.T) { +// if testing.Short() { +// t.Skip("skipping malloc count in short mode") +// } +// // Allocate a big messy buffer for AppendQuoteToASCII's test. +// oneMB = make([]byte, 1e6) +// for i := range oneMB { +// oneMB[i] = byte(i) +// } +// for _, mt := range mallocTest { +// allocs := testing.AllocsPerRun(100, mt.fn) +// if max := float64(mt.count); allocs > max { +// t.Errorf("%s: %v allocs, want <=%v", mt.desc, allocs, max) +// } +// } +// } + +// Sink makes sure the compiler cannot optimize away the benchmarks. +var Sink struct { + Bool bool + Int int + Int64 int64 + Uint64 uint64 + Float64 float64 + Error error + Bytes []byte +} + +/* XXX: removed due to lack of AllocsPerRun +func TestAllocationsFromBytes(t *testing.T) { + const runsPerTest = 100 + bytes := struct{ Bool, Number, String, Buffer []byte }{ + Bool: []byte("false"), + Number: []byte("123456789"), + String: []byte("hello, world!"), + Buffer: make([]byte, 1024), + } + + checkNoAllocs := func(f func()) func(t *testing.T) { + return func(t *testing.T) { + t.Helper() + if allocs := testing.AllocsPerRun(runsPerTest, f); allocs != 0 { + t.Errorf("got %v allocs, want 0 allocs", allocs) + } + } + } + + t.Run("Atoi", checkNoAllocs(func() { + Sink.Int, Sink.Error = Atoi(string(bytes.Number)) + })) + t.Run("ParseBool", checkNoAllocs(func() { + Sink.Bool, Sink.Error = ParseBool(string(bytes.Bool)) + })) + t.Run("ParseInt", checkNoAllocs(func() { + Sink.Int64, Sink.Error = ParseInt(string(bytes.Number), 10, 64) + })) + t.Run("ParseUint", checkNoAllocs(func() { + Sink.Uint64, Sink.Error = ParseUint(string(bytes.Number), 10, 64) + })) + t.Run("ParseFloat", checkNoAllocs(func() { + Sink.Float64, Sink.Error = ParseFloat(string(bytes.Number), 64) + })) + t.Run("ParseComplex", checkNoAllocs(func() { + Sink.Complex128, Sink.Error = ParseComplex(string(bytes.Number), 128) + })) + t.Run("CanBackquote", checkNoAllocs(func() { + Sink.Bool = CanBackquote(string(bytes.String)) + })) + t.Run("AppendQuote", checkNoAllocs(func() { + Sink.Bytes = AppendQuote(bytes.Buffer[:0], string(bytes.String)) + })) + t.Run("AppendQuoteToASCII", checkNoAllocs(func() { + Sink.Bytes = AppendQuoteToASCII(bytes.Buffer[:0], string(bytes.String)) + })) + t.Run("AppendQuoteToGraphic", checkNoAllocs(func() { + Sink.Bytes = AppendQuoteToGraphic(bytes.Buffer[:0], string(bytes.String)) + })) +} +*/ + +func TestErrorPrefixes(t *testing.T) { + _, errInt := Atoi("INVALID") + _, errBool := ParseBool("INVALID") + _, errFloat := ParseFloat("INVALID", 64) + _, errInt64 := ParseInt("INVALID", 10, 64) + _, errUint64 := ParseUint("INVALID", 10, 64) + + vectors := []struct { + err error // Input error + want string // Function name wanted + }{ + {errInt, "Atoi"}, + {errBool, "ParseBool"}, + {errFloat, "ParseFloat"}, + {errInt64, "ParseInt"}, + {errUint64, "ParseUint"}, + } + + for _, v := range vectors { + nerr, ok := v.err.(*NumError) + if !ok { + t.Errorf("test %s, error was not a *NumError", v.want) + continue + } + if got := nerr.Func; got != v.want { + t.Errorf("mismatching Func: got %s, want %s", got, v.want) + } + } + +} diff --git a/gnovm/stdlibs/unicode/example_test.gno b/gnovm/stdlibs/unicode/example_test.gno index 3ab11a4b5d2..bd2920dfb56 100644 --- a/gnovm/stdlibs/unicode/example_test.gno +++ b/gnovm/stdlibs/unicode/example_test.gno @@ -116,7 +116,7 @@ func ExampleSimpleFold() { fmt.Printf("%#U\n", unicode.SimpleFold('A')) // 'a' fmt.Printf("%#U\n", unicode.SimpleFold('a')) // 'A' fmt.Printf("%#U\n", unicode.SimpleFold('K')) // 'k' - fmt.Printf("%#U\n", unicode.SimpleFold('k')) // '\u212A' (Kelvin symbol, K) + fmt.Printf("%#U\n", unicode.SimpleFold('k')) // '\u212A' (Kelvin symbol, K) fmt.Printf("%#U\n", unicode.SimpleFold('\u212A')) // 'K' fmt.Printf("%#U\n", unicode.SimpleFold('1')) // '1' @@ -124,7 +124,7 @@ func ExampleSimpleFold() { // U+0061 'a' // U+0041 'A' // U+006B 'k' - // U+212A 'K' + // U+212A 'K' // U+004B 'K' // U+0031 '1' } @@ -194,3 +194,63 @@ func ExampleSpecialCase() { // U+0130 'İ' // U+0130 'İ' } + +func ExampleIsDigit() { + fmt.Printf("%t\n", unicode.IsDigit('৩')) + fmt.Printf("%t\n", unicode.IsDigit('A')) + // Output: + // true + // false +} + +func ExampleIsNumber() { + fmt.Printf("%t\n", unicode.IsNumber('Ⅷ')) + fmt.Printf("%t\n", unicode.IsNumber('A')) + // Output: + // true + // false +} + +func ExampleIsLetter() { + fmt.Printf("%t\n", unicode.IsLetter('A')) + fmt.Printf("%t\n", unicode.IsLetter('7')) + // Output: + // true + // false +} + +func ExampleIsLower() { + fmt.Printf("%t\n", unicode.IsLower('a')) + fmt.Printf("%t\n", unicode.IsLower('A')) + // Output: + // true + // false +} + +func ExampleIsUpper() { + fmt.Printf("%t\n", unicode.IsUpper('A')) + fmt.Printf("%t\n", unicode.IsUpper('a')) + // Output: + // true + // false +} + +func ExampleIsTitle() { + fmt.Printf("%t\n", unicode.IsTitle('Dž')) + fmt.Printf("%t\n", unicode.IsTitle('a')) + // Output: + // true + // false +} + +func ExampleIsSpace() { + fmt.Printf("%t\n", unicode.IsSpace(' ')) + fmt.Printf("%t\n", unicode.IsSpace('\n')) + fmt.Printf("%t\n", unicode.IsSpace('\t')) + fmt.Printf("%t\n", unicode.IsSpace('a')) + // Output: + // true + // true + // true + // false +} diff --git a/gnovm/stdlibs/unicode/letter.gno b/gnovm/stdlibs/unicode/letter.gno index aa1039aa38d..f3f8e529648 100644 --- a/gnovm/stdlibs/unicode/letter.gno +++ b/gnovm/stdlibs/unicode/letter.gno @@ -331,7 +331,7 @@ type foldPair struct { // SimpleFold('a') = 'A' // // SimpleFold('K') = 'k' -// SimpleFold('k') = '\u212A' (Kelvin symbol, K) +// SimpleFold('k') = '\u212A' (Kelvin symbol, K) // SimpleFold('\u212A') = 'K' // // SimpleFold('1') = '1' diff --git a/gnovm/stdlibs/unicode/tables.gno b/gnovm/stdlibs/unicode/tables.gno index a57e0ca67cb..b3d65d9d5c1 100644 --- a/gnovm/stdlibs/unicode/tables.gno +++ b/gnovm/stdlibs/unicode/tables.gno @@ -3,7 +3,7 @@ package unicode // Version is the Unicode edition from which the tables are derived. -const Version = "13.0.0" +const Version = "15.0.0" // Categories is the set of Unicode category tables. var Categories = map[string]*RangeTable{ @@ -52,7 +52,8 @@ var _C = &RangeTable{ {0x00ad, 0x0600, 1363}, {0x0601, 0x0605, 1}, {0x061c, 0x06dd, 193}, - {0x070f, 0x08e2, 467}, + {0x070f, 0x0890, 385}, + {0x0891, 0x08e2, 81}, {0x180e, 0x200b, 2045}, {0x200c, 0x200f, 1}, {0x202a, 0x202e, 1}, @@ -64,7 +65,7 @@ var _C = &RangeTable{ }, R32: []Range32{ {0x110bd, 0x110cd, 16}, - {0x13430, 0x13438, 1}, + {0x13430, 0x1343f, 1}, {0x1bca0, 0x1bca3, 1}, {0x1d173, 0x1d17a, 1}, {0xe0001, 0xe0020, 31}, @@ -88,7 +89,8 @@ var _Cf = &RangeTable{ {0x00ad, 0x0600, 1363}, {0x0601, 0x0605, 1}, {0x061c, 0x06dd, 193}, - {0x070f, 0x08e2, 467}, + {0x070f, 0x0890, 385}, + {0x0891, 0x08e2, 81}, {0x180e, 0x200b, 2045}, {0x200c, 0x200f, 1}, {0x202a, 0x202e, 1}, @@ -99,7 +101,7 @@ var _Cf = &RangeTable{ }, R32: []Range32{ {0x110bd, 0x110cd, 16}, - {0x13430, 0x13438, 1}, + {0x13430, 0x1343f, 1}, {0x1bca0, 0x1bca3, 1}, {0x1d173, 0x1d17a, 1}, {0xe0001, 0xe0020, 31}, @@ -169,8 +171,9 @@ var _L = &RangeTable{ {0x0828, 0x0840, 24}, {0x0841, 0x0858, 1}, {0x0860, 0x086a, 1}, - {0x08a0, 0x08b4, 1}, - {0x08b6, 0x08c7, 1}, + {0x0870, 0x0887, 1}, + {0x0889, 0x088e, 1}, + {0x08a0, 0x08c9, 1}, {0x0904, 0x0939, 1}, {0x093d, 0x0950, 19}, {0x0958, 0x0961, 1}, @@ -231,17 +234,18 @@ var _L = &RangeTable{ {0x0c2a, 0x0c39, 1}, {0x0c3d, 0x0c58, 27}, {0x0c59, 0x0c5a, 1}, - {0x0c60, 0x0c61, 1}, - {0x0c80, 0x0c85, 5}, - {0x0c86, 0x0c8c, 1}, + {0x0c5d, 0x0c60, 3}, + {0x0c61, 0x0c80, 31}, + {0x0c85, 0x0c8c, 1}, {0x0c8e, 0x0c90, 1}, {0x0c92, 0x0ca8, 1}, {0x0caa, 0x0cb3, 1}, {0x0cb5, 0x0cb9, 1}, - {0x0cbd, 0x0cde, 33}, - {0x0ce0, 0x0ce1, 1}, - {0x0cf1, 0x0cf2, 1}, - {0x0d04, 0x0d0c, 1}, + {0x0cbd, 0x0cdd, 32}, + {0x0cde, 0x0ce0, 2}, + {0x0ce1, 0x0cf1, 16}, + {0x0cf2, 0x0d04, 18}, + {0x0d05, 0x0d0c, 1}, {0x0d0e, 0x0d10, 1}, {0x0d12, 0x0d3a, 1}, {0x0d3d, 0x0d4e, 17}, @@ -307,9 +311,8 @@ var _L = &RangeTable{ {0x1681, 0x169a, 1}, {0x16a0, 0x16ea, 1}, {0x16f1, 0x16f8, 1}, - {0x1700, 0x170c, 1}, - {0x170e, 0x1711, 1}, - {0x1720, 0x1731, 1}, + {0x1700, 0x1711, 1}, + {0x171f, 0x1731, 1}, {0x1740, 0x1751, 1}, {0x1760, 0x176c, 1}, {0x176e, 0x1770, 1}, @@ -329,7 +332,7 @@ var _L = &RangeTable{ {0x1a20, 0x1a54, 1}, {0x1aa7, 0x1b05, 94}, {0x1b06, 0x1b33, 1}, - {0x1b45, 0x1b4b, 1}, + {0x1b45, 0x1b4c, 1}, {0x1b83, 0x1ba0, 1}, {0x1bae, 0x1baf, 1}, {0x1bba, 0x1be5, 1}, @@ -374,9 +377,7 @@ var _L = &RangeTable{ {0x2145, 0x2149, 1}, {0x214e, 0x2183, 53}, {0x2184, 0x2c00, 2684}, - {0x2c01, 0x2c2e, 1}, - {0x2c30, 0x2c5e, 1}, - {0x2c60, 0x2ce4, 1}, + {0x2c01, 0x2ce4, 1}, {0x2ceb, 0x2cee, 1}, {0x2cf2, 0x2cf3, 1}, {0x2d00, 0x2d25, 1}, @@ -405,8 +406,7 @@ var _L = &RangeTable{ {0x31a0, 0x31bf, 1}, {0x31f0, 0x31ff, 1}, {0x3400, 0x4dbf, 1}, - {0x4e00, 0x9ffc, 1}, - {0xa000, 0xa48c, 1}, + {0x4e00, 0xa48c, 1}, {0xa4d0, 0xa4fd, 1}, {0xa500, 0xa60c, 1}, {0xa610, 0xa61f, 1}, @@ -416,9 +416,11 @@ var _L = &RangeTable{ {0xa6a0, 0xa6e5, 1}, {0xa717, 0xa71f, 1}, {0xa722, 0xa788, 1}, - {0xa78b, 0xa7bf, 1}, - {0xa7c2, 0xa7ca, 1}, - {0xa7f5, 0xa801, 1}, + {0xa78b, 0xa7ca, 1}, + {0xa7d0, 0xa7d1, 1}, + {0xa7d3, 0xa7d5, 2}, + {0xa7d6, 0xa7d9, 1}, + {0xa7f2, 0xa801, 1}, {0xa803, 0xa805, 1}, {0xa807, 0xa80a, 1}, {0xa80c, 0xa822, 1}, @@ -507,9 +509,20 @@ var _L = &RangeTable{ {0x104d8, 0x104fb, 1}, {0x10500, 0x10527, 1}, {0x10530, 0x10563, 1}, + {0x10570, 0x1057a, 1}, + {0x1057c, 0x1058a, 1}, + {0x1058c, 0x10592, 1}, + {0x10594, 0x10595, 1}, + {0x10597, 0x105a1, 1}, + {0x105a3, 0x105b1, 1}, + {0x105b3, 0x105b9, 1}, + {0x105bb, 0x105bc, 1}, {0x10600, 0x10736, 1}, {0x10740, 0x10755, 1}, {0x10760, 0x10767, 1}, + {0x10780, 0x10785, 1}, + {0x10787, 0x107b0, 1}, + {0x107b2, 0x107ba, 1}, {0x10800, 0x10805, 1}, {0x10808, 0x1080a, 2}, {0x1080b, 0x10835, 1}, @@ -545,10 +558,13 @@ var _L = &RangeTable{ {0x10f00, 0x10f1c, 1}, {0x10f27, 0x10f30, 9}, {0x10f31, 0x10f45, 1}, + {0x10f70, 0x10f81, 1}, {0x10fb0, 0x10fc4, 1}, {0x10fe0, 0x10ff6, 1}, {0x11003, 0x11037, 1}, - {0x11083, 0x110af, 1}, + {0x11071, 0x11072, 1}, + {0x11075, 0x11083, 14}, + {0x11084, 0x110af, 1}, {0x110d0, 0x110e8, 1}, {0x11103, 0x11126, 1}, {0x11144, 0x11147, 3}, @@ -559,6 +575,7 @@ var _L = &RangeTable{ {0x111da, 0x111dc, 2}, {0x11200, 0x11211, 1}, {0x11213, 0x1122b, 1}, + {0x1123f, 0x11240, 1}, {0x11280, 0x11286, 1}, {0x11288, 0x1128a, 2}, {0x1128b, 0x1128d, 1}, @@ -586,6 +603,7 @@ var _L = &RangeTable{ {0x11681, 0x116aa, 1}, {0x116b8, 0x11700, 72}, {0x11701, 0x1171a, 1}, + {0x11740, 0x11746, 1}, {0x11800, 0x1182b, 1}, {0x118a0, 0x118df, 1}, {0x118ff, 0x11906, 1}, @@ -601,8 +619,8 @@ var _L = &RangeTable{ {0x11a0c, 0x11a32, 1}, {0x11a3a, 0x11a50, 22}, {0x11a5c, 0x11a89, 1}, - {0x11a9d, 0x11ac0, 35}, - {0x11ac1, 0x11af8, 1}, + {0x11a9d, 0x11ab0, 19}, + {0x11ab1, 0x11af8, 1}, {0x11c00, 0x11c08, 1}, {0x11c0a, 0x11c2e, 1}, {0x11c40, 0x11c72, 50}, @@ -616,13 +634,19 @@ var _L = &RangeTable{ {0x11d6a, 0x11d89, 1}, {0x11d98, 0x11ee0, 328}, {0x11ee1, 0x11ef2, 1}, + {0x11f02, 0x11f04, 2}, + {0x11f05, 0x11f10, 1}, + {0x11f12, 0x11f33, 1}, {0x11fb0, 0x12000, 80}, {0x12001, 0x12399, 1}, {0x12480, 0x12543, 1}, - {0x13000, 0x1342e, 1}, + {0x12f90, 0x12ff0, 1}, + {0x13000, 0x1342f, 1}, + {0x13441, 0x13446, 1}, {0x14400, 0x14646, 1}, {0x16800, 0x16a38, 1}, {0x16a40, 0x16a5e, 1}, + {0x16a70, 0x16abe, 1}, {0x16ad0, 0x16aed, 1}, {0x16b00, 0x16b2f, 1}, {0x16b40, 0x16b43, 1}, @@ -637,9 +661,14 @@ var _L = &RangeTable{ {0x17001, 0x187f7, 1}, {0x18800, 0x18cd5, 1}, {0x18d00, 0x18d08, 1}, - {0x1b000, 0x1b11e, 1}, - {0x1b150, 0x1b152, 1}, - {0x1b164, 0x1b167, 1}, + {0x1aff0, 0x1aff3, 1}, + {0x1aff5, 0x1affb, 1}, + {0x1affd, 0x1affe, 1}, + {0x1b000, 0x1b122, 1}, + {0x1b132, 0x1b150, 30}, + {0x1b151, 0x1b152, 1}, + {0x1b155, 0x1b164, 15}, + {0x1b165, 0x1b167, 1}, {0x1b170, 0x1b2fb, 1}, {0x1bc00, 0x1bc6a, 1}, {0x1bc70, 0x1bc7c, 1}, @@ -675,10 +704,19 @@ var _L = &RangeTable{ {0x1d78a, 0x1d7a8, 1}, {0x1d7aa, 0x1d7c2, 1}, {0x1d7c4, 0x1d7cb, 1}, + {0x1df00, 0x1df1e, 1}, + {0x1df25, 0x1df2a, 1}, + {0x1e030, 0x1e06d, 1}, {0x1e100, 0x1e12c, 1}, {0x1e137, 0x1e13d, 1}, - {0x1e14e, 0x1e2c0, 370}, - {0x1e2c1, 0x1e2eb, 1}, + {0x1e14e, 0x1e290, 322}, + {0x1e291, 0x1e2ad, 1}, + {0x1e2c0, 0x1e2eb, 1}, + {0x1e4d0, 0x1e4eb, 1}, + {0x1e7e0, 0x1e7e6, 1}, + {0x1e7e8, 0x1e7eb, 1}, + {0x1e7ed, 0x1e7ee, 1}, + {0x1e7f0, 0x1e7fe, 1}, {0x1e800, 0x1e8c4, 1}, {0x1e900, 0x1e943, 1}, {0x1e94b, 0x1ee00, 1205}, @@ -706,13 +744,14 @@ var _L = &RangeTable{ {0x1eea1, 0x1eea3, 1}, {0x1eea5, 0x1eea9, 1}, {0x1eeab, 0x1eebb, 1}, - {0x20000, 0x2a6dd, 1}, - {0x2a700, 0x2b734, 1}, + {0x20000, 0x2a6df, 1}, + {0x2a700, 0x2b739, 1}, {0x2b740, 0x2b81d, 1}, {0x2b820, 0x2cea1, 1}, {0x2ceb0, 0x2ebe0, 1}, {0x2f800, 0x2fa1d, 1}, {0x30000, 0x3134a, 1}, + {0x31350, 0x323af, 1}, }, LatinOffset: 6, } @@ -807,7 +846,7 @@ var _Ll = &RangeTable{ {0x213c, 0x213d, 1}, {0x2146, 0x2149, 1}, {0x214e, 0x2184, 54}, - {0x2c30, 0x2c5e, 1}, + {0x2c30, 0x2c5f, 1}, {0x2c61, 0x2c65, 4}, {0x2c66, 0x2c6c, 2}, {0x2c71, 0x2c73, 2}, @@ -831,11 +870,11 @@ var _Ll = &RangeTable{ {0xa794, 0xa795, 1}, {0xa797, 0xa7a9, 2}, {0xa7af, 0xa7b5, 6}, - {0xa7b7, 0xa7bf, 2}, - {0xa7c3, 0xa7c8, 5}, - {0xa7ca, 0xa7f6, 44}, - {0xa7fa, 0xab30, 822}, - {0xab31, 0xab5a, 1}, + {0xa7b7, 0xa7c3, 2}, + {0xa7c8, 0xa7ca, 2}, + {0xa7d1, 0xa7d9, 2}, + {0xa7f6, 0xa7fa, 4}, + {0xab30, 0xab5a, 1}, {0xab60, 0xab68, 1}, {0xab70, 0xabbf, 1}, {0xfb00, 0xfb06, 1}, @@ -845,6 +884,10 @@ var _Ll = &RangeTable{ R32: []Range32{ {0x10428, 0x1044f, 1}, {0x104d8, 0x104fb, 1}, + {0x10597, 0x105a1, 1}, + {0x105a3, 0x105b1, 1}, + {0x105b3, 0x105b9, 1}, + {0x105bb, 0x105bc, 1}, {0x10cc0, 0x10cf2, 1}, {0x118c0, 0x118df, 1}, {0x16e60, 0x16e7f, 1}, @@ -875,8 +918,11 @@ var _Ll = &RangeTable{ {0x1d78a, 0x1d78f, 1}, {0x1d7aa, 0x1d7c2, 1}, {0x1d7c4, 0x1d7c9, 1}, - {0x1d7cb, 0x1e922, 4439}, - {0x1e923, 0x1e943, 1}, + {0x1d7cb, 0x1df00, 1845}, + {0x1df01, 0x1df09, 1}, + {0x1df0b, 0x1df1e, 1}, + {0x1df25, 0x1df2a, 1}, + {0x1e922, 0x1e943, 1}, }, LatinOffset: 4, } @@ -893,11 +939,11 @@ var _Lm = &RangeTable{ {0x07f4, 0x07f5, 1}, {0x07fa, 0x081a, 32}, {0x0824, 0x0828, 4}, - {0x0971, 0x0e46, 1237}, - {0x0ec6, 0x10fc, 566}, - {0x17d7, 0x1843, 108}, - {0x1aa7, 0x1c78, 465}, - {0x1c79, 0x1c7d, 1}, + {0x08c9, 0x0971, 168}, + {0x0e46, 0x0ec6, 128}, + {0x10fc, 0x17d7, 1755}, + {0x1843, 0x1aa7, 612}, + {0x1c78, 0x1c7d, 1}, {0x1d2c, 0x1d6a, 1}, {0x1d78, 0x1d9b, 35}, {0x1d9c, 0x1dbf, 1}, @@ -916,6 +962,7 @@ var _Lm = &RangeTable{ {0xa69c, 0xa69d, 1}, {0xa717, 0xa71f, 1}, {0xa770, 0xa788, 24}, + {0xa7f2, 0xa7f4, 1}, {0xa7f8, 0xa7f9, 1}, {0xa9cf, 0xa9e6, 23}, {0xaa70, 0xaadd, 109}, @@ -925,12 +972,19 @@ var _Lm = &RangeTable{ {0xff9e, 0xff9f, 1}, }, R32: []Range32{ + {0x10780, 0x10785, 1}, + {0x10787, 0x107b0, 1}, + {0x107b2, 0x107ba, 1}, {0x16b40, 0x16b43, 1}, {0x16f93, 0x16f9f, 1}, {0x16fe0, 0x16fe1, 1}, - {0x16fe3, 0x1e137, 29012}, - {0x1e138, 0x1e13d, 1}, - {0x1e94b, 0x1e94b, 1}, + {0x16fe3, 0x1aff0, 16397}, + {0x1aff1, 0x1aff3, 1}, + {0x1aff5, 0x1affb, 1}, + {0x1affd, 0x1affe, 1}, + {0x1e030, 0x1e06d, 1}, + {0x1e137, 0x1e13d, 1}, + {0x1e4eb, 0x1e94b, 1120}, }, } @@ -957,8 +1011,9 @@ var _Lo = &RangeTable{ {0x0800, 0x0815, 1}, {0x0840, 0x0858, 1}, {0x0860, 0x086a, 1}, - {0x08a0, 0x08b4, 1}, - {0x08b6, 0x08c7, 1}, + {0x0870, 0x0887, 1}, + {0x0889, 0x088e, 1}, + {0x08a0, 0x08c8, 1}, {0x0904, 0x0939, 1}, {0x093d, 0x0950, 19}, {0x0958, 0x0961, 1}, @@ -1019,17 +1074,18 @@ var _Lo = &RangeTable{ {0x0c2a, 0x0c39, 1}, {0x0c3d, 0x0c58, 27}, {0x0c59, 0x0c5a, 1}, - {0x0c60, 0x0c61, 1}, - {0x0c80, 0x0c85, 5}, - {0x0c86, 0x0c8c, 1}, + {0x0c5d, 0x0c60, 3}, + {0x0c61, 0x0c80, 31}, + {0x0c85, 0x0c8c, 1}, {0x0c8e, 0x0c90, 1}, {0x0c92, 0x0ca8, 1}, {0x0caa, 0x0cb3, 1}, {0x0cb5, 0x0cb9, 1}, - {0x0cbd, 0x0cde, 33}, - {0x0ce0, 0x0ce1, 1}, - {0x0cf1, 0x0cf2, 1}, - {0x0d04, 0x0d0c, 1}, + {0x0cbd, 0x0cdd, 32}, + {0x0cde, 0x0ce0, 2}, + {0x0ce1, 0x0cf1, 16}, + {0x0cf2, 0x0d04, 18}, + {0x0d05, 0x0d0c, 1}, {0x0d0e, 0x0d10, 1}, {0x0d12, 0x0d3a, 1}, {0x0d3d, 0x0d4e, 17}, @@ -1089,9 +1145,8 @@ var _Lo = &RangeTable{ {0x1681, 0x169a, 1}, {0x16a0, 0x16ea, 1}, {0x16f1, 0x16f8, 1}, - {0x1700, 0x170c, 1}, - {0x170e, 0x1711, 1}, - {0x1720, 0x1731, 1}, + {0x1700, 0x1711, 1}, + {0x171f, 0x1731, 1}, {0x1740, 0x1751, 1}, {0x1760, 0x176c, 1}, {0x176e, 0x1770, 1}, @@ -1111,7 +1166,7 @@ var _Lo = &RangeTable{ {0x1a00, 0x1a16, 1}, {0x1a20, 0x1a54, 1}, {0x1b05, 0x1b33, 1}, - {0x1b45, 0x1b4b, 1}, + {0x1b45, 0x1b4c, 1}, {0x1b83, 0x1ba0, 1}, {0x1bae, 0x1baf, 1}, {0x1bba, 0x1be5, 1}, @@ -1143,8 +1198,7 @@ var _Lo = &RangeTable{ {0x31a0, 0x31bf, 1}, {0x31f0, 0x31ff, 1}, {0x3400, 0x4dbf, 1}, - {0x4e00, 0x9ffc, 1}, - {0xa000, 0xa014, 1}, + {0x4e00, 0xa014, 1}, {0xa016, 0xa48c, 1}, {0xa4d0, 0xa4f7, 1}, {0xa500, 0xa60b, 1}, @@ -1272,10 +1326,13 @@ var _Lo = &RangeTable{ {0x10f00, 0x10f1c, 1}, {0x10f27, 0x10f30, 9}, {0x10f31, 0x10f45, 1}, + {0x10f70, 0x10f81, 1}, {0x10fb0, 0x10fc4, 1}, {0x10fe0, 0x10ff6, 1}, {0x11003, 0x11037, 1}, - {0x11083, 0x110af, 1}, + {0x11071, 0x11072, 1}, + {0x11075, 0x11083, 14}, + {0x11084, 0x110af, 1}, {0x110d0, 0x110e8, 1}, {0x11103, 0x11126, 1}, {0x11144, 0x11147, 3}, @@ -1286,6 +1343,7 @@ var _Lo = &RangeTable{ {0x111da, 0x111dc, 2}, {0x11200, 0x11211, 1}, {0x11213, 0x1122b, 1}, + {0x1123f, 0x11240, 1}, {0x11280, 0x11286, 1}, {0x11288, 0x1128a, 2}, {0x1128b, 0x1128d, 1}, @@ -1313,6 +1371,7 @@ var _Lo = &RangeTable{ {0x11681, 0x116aa, 1}, {0x116b8, 0x11700, 72}, {0x11701, 0x1171a, 1}, + {0x11740, 0x11746, 1}, {0x11800, 0x1182b, 1}, {0x118ff, 0x11906, 1}, {0x11909, 0x1190c, 3}, @@ -1327,8 +1386,8 @@ var _Lo = &RangeTable{ {0x11a0c, 0x11a32, 1}, {0x11a3a, 0x11a50, 22}, {0x11a5c, 0x11a89, 1}, - {0x11a9d, 0x11ac0, 35}, - {0x11ac1, 0x11af8, 1}, + {0x11a9d, 0x11ab0, 19}, + {0x11ab1, 0x11af8, 1}, {0x11c00, 0x11c08, 1}, {0x11c0a, 0x11c2e, 1}, {0x11c40, 0x11c72, 50}, @@ -1342,13 +1401,19 @@ var _Lo = &RangeTable{ {0x11d6a, 0x11d89, 1}, {0x11d98, 0x11ee0, 328}, {0x11ee1, 0x11ef2, 1}, + {0x11f02, 0x11f04, 2}, + {0x11f05, 0x11f10, 1}, + {0x11f12, 0x11f33, 1}, {0x11fb0, 0x12000, 80}, {0x12001, 0x12399, 1}, {0x12480, 0x12543, 1}, - {0x13000, 0x1342e, 1}, + {0x12f90, 0x12ff0, 1}, + {0x13000, 0x1342f, 1}, + {0x13441, 0x13446, 1}, {0x14400, 0x14646, 1}, {0x16800, 0x16a38, 1}, {0x16a40, 0x16a5e, 1}, + {0x16a70, 0x16abe, 1}, {0x16ad0, 0x16aed, 1}, {0x16b00, 0x16b2f, 1}, {0x16b63, 0x16b77, 1}, @@ -1358,17 +1423,26 @@ var _Lo = &RangeTable{ {0x17001, 0x187f7, 1}, {0x18800, 0x18cd5, 1}, {0x18d00, 0x18d08, 1}, - {0x1b000, 0x1b11e, 1}, - {0x1b150, 0x1b152, 1}, - {0x1b164, 0x1b167, 1}, + {0x1b000, 0x1b122, 1}, + {0x1b132, 0x1b150, 30}, + {0x1b151, 0x1b152, 1}, + {0x1b155, 0x1b164, 15}, + {0x1b165, 0x1b167, 1}, {0x1b170, 0x1b2fb, 1}, {0x1bc00, 0x1bc6a, 1}, {0x1bc70, 0x1bc7c, 1}, {0x1bc80, 0x1bc88, 1}, {0x1bc90, 0x1bc99, 1}, - {0x1e100, 0x1e12c, 1}, - {0x1e14e, 0x1e2c0, 370}, - {0x1e2c1, 0x1e2eb, 1}, + {0x1df0a, 0x1e100, 502}, + {0x1e101, 0x1e12c, 1}, + {0x1e14e, 0x1e290, 322}, + {0x1e291, 0x1e2ad, 1}, + {0x1e2c0, 0x1e2eb, 1}, + {0x1e4d0, 0x1e4ea, 1}, + {0x1e7e0, 0x1e7e6, 1}, + {0x1e7e8, 0x1e7eb, 1}, + {0x1e7ed, 0x1e7ee, 1}, + {0x1e7f0, 0x1e7fe, 1}, {0x1e800, 0x1e8c4, 1}, {0x1ee00, 0x1ee03, 1}, {0x1ee05, 0x1ee1f, 1}, @@ -1394,13 +1468,14 @@ var _Lo = &RangeTable{ {0x1eea1, 0x1eea3, 1}, {0x1eea5, 0x1eea9, 1}, {0x1eeab, 0x1eebb, 1}, - {0x20000, 0x2a6dd, 1}, - {0x2a700, 0x2b734, 1}, + {0x20000, 0x2a6df, 1}, + {0x2a700, 0x2b739, 1}, {0x2b740, 0x2b81d, 1}, {0x2b820, 0x2cea1, 1}, {0x2ceb0, 0x2ebe0, 1}, {0x2f800, 0x2fa1d, 1}, {0x30000, 0x3134a, 1}, + {0x31350, 0x323af, 1}, }, LatinOffset: 1, } @@ -1501,7 +1576,7 @@ var _Lu = &RangeTable{ {0x2130, 0x2133, 1}, {0x213e, 0x213f, 1}, {0x2145, 0x2183, 62}, - {0x2c00, 0x2c2e, 1}, + {0x2c00, 0x2c2f, 1}, {0x2c60, 0x2c62, 2}, {0x2c63, 0x2c64, 1}, {0x2c67, 0x2c6d, 2}, @@ -1522,15 +1597,20 @@ var _Lu = &RangeTable{ {0xa796, 0xa7aa, 2}, {0xa7ab, 0xa7ae, 1}, {0xa7b0, 0xa7b4, 1}, - {0xa7b6, 0xa7be, 2}, - {0xa7c2, 0xa7c4, 2}, + {0xa7b6, 0xa7c4, 2}, {0xa7c5, 0xa7c7, 1}, - {0xa7c9, 0xa7f5, 44}, - {0xff21, 0xff3a, 1}, + {0xa7c9, 0xa7d0, 7}, + {0xa7d6, 0xa7d8, 2}, + {0xa7f5, 0xff21, 22316}, + {0xff22, 0xff3a, 1}, }, R32: []Range32{ {0x10400, 0x10427, 1}, {0x104b0, 0x104d3, 1}, + {0x10570, 0x1057a, 1}, + {0x1057c, 0x1058a, 1}, + {0x1058c, 0x10592, 1}, + {0x10594, 0x10595, 1}, {0x10c80, 0x10cb2, 1}, {0x118a0, 0x118bf, 1}, {0x16e40, 0x16e5f, 1}, @@ -1594,7 +1674,8 @@ var _M = &RangeTable{ {0x0825, 0x0827, 1}, {0x0829, 0x082d, 1}, {0x0859, 0x085b, 1}, - {0x08d3, 0x08e1, 1}, + {0x0898, 0x089f, 1}, + {0x08ca, 0x08e1, 1}, {0x08e3, 0x0903, 1}, {0x093a, 0x093c, 1}, {0x093e, 0x094f, 1}, @@ -1634,7 +1715,8 @@ var _M = &RangeTable{ {0x0bca, 0x0bcd, 1}, {0x0bd7, 0x0c00, 41}, {0x0c01, 0x0c04, 1}, - {0x0c3e, 0x0c44, 1}, + {0x0c3c, 0x0c3e, 2}, + {0x0c3f, 0x0c44, 1}, {0x0c46, 0x0c48, 1}, {0x0c4a, 0x0c4d, 1}, {0x0c55, 0x0c56, 1}, @@ -1646,7 +1728,8 @@ var _M = &RangeTable{ {0x0cca, 0x0ccd, 1}, {0x0cd5, 0x0cd6, 1}, {0x0ce2, 0x0ce3, 1}, - {0x0d00, 0x0d03, 1}, + {0x0cf3, 0x0d00, 13}, + {0x0d01, 0x0d03, 1}, {0x0d3b, 0x0d3c, 1}, {0x0d3e, 0x0d44, 1}, {0x0d46, 0x0d48, 1}, @@ -1664,7 +1747,7 @@ var _M = &RangeTable{ {0x0e47, 0x0e4e, 1}, {0x0eb1, 0x0eb4, 3}, {0x0eb5, 0x0ebc, 1}, - {0x0ec8, 0x0ecd, 1}, + {0x0ec8, 0x0ece, 1}, {0x0f18, 0x0f19, 1}, {0x0f35, 0x0f39, 2}, {0x0f3e, 0x0f3f, 1}, @@ -1683,22 +1766,22 @@ var _M = &RangeTable{ {0x108f, 0x109a, 11}, {0x109b, 0x109d, 1}, {0x135d, 0x135f, 1}, - {0x1712, 0x1714, 1}, + {0x1712, 0x1715, 1}, {0x1732, 0x1734, 1}, {0x1752, 0x1753, 1}, {0x1772, 0x1773, 1}, {0x17b4, 0x17d3, 1}, {0x17dd, 0x180b, 46}, {0x180c, 0x180d, 1}, - {0x1885, 0x1886, 1}, - {0x18a9, 0x1920, 119}, - {0x1921, 0x192b, 1}, + {0x180f, 0x1885, 118}, + {0x1886, 0x18a9, 35}, + {0x1920, 0x192b, 1}, {0x1930, 0x193b, 1}, {0x1a17, 0x1a1b, 1}, {0x1a55, 0x1a5e, 1}, {0x1a60, 0x1a7c, 1}, {0x1a7f, 0x1ab0, 49}, - {0x1ab1, 0x1ac0, 1}, + {0x1ab1, 0x1ace, 1}, {0x1b00, 0x1b04, 1}, {0x1b34, 0x1b44, 1}, {0x1b6b, 0x1b73, 1}, @@ -1710,8 +1793,7 @@ var _M = &RangeTable{ {0x1cd4, 0x1ce8, 1}, {0x1ced, 0x1cf4, 7}, {0x1cf7, 0x1cf9, 1}, - {0x1dc0, 0x1df9, 1}, - {0x1dfb, 0x1dff, 1}, + {0x1dc0, 0x1dff, 1}, {0x20d0, 0x20f0, 1}, {0x2cef, 0x2cf1, 1}, {0x2d7f, 0x2de0, 97}, @@ -1763,12 +1845,17 @@ var _M = &RangeTable{ {0x10ae6, 0x10d24, 574}, {0x10d25, 0x10d27, 1}, {0x10eab, 0x10eac, 1}, + {0x10efd, 0x10eff, 1}, {0x10f46, 0x10f50, 1}, + {0x10f82, 0x10f85, 1}, {0x11000, 0x11002, 1}, {0x11038, 0x11046, 1}, - {0x1107f, 0x11082, 1}, + {0x11070, 0x11073, 3}, + {0x11074, 0x1107f, 11}, + {0x11080, 0x11082, 1}, {0x110b0, 0x110ba, 1}, - {0x11100, 0x11102, 1}, + {0x110c2, 0x11100, 62}, + {0x11101, 0x11102, 1}, {0x11127, 0x11134, 1}, {0x11145, 0x11146, 1}, {0x11173, 0x11180, 13}, @@ -1777,8 +1864,8 @@ var _M = &RangeTable{ {0x111c9, 0x111cc, 1}, {0x111ce, 0x111cf, 1}, {0x1122c, 0x11237, 1}, - {0x1123e, 0x112df, 161}, - {0x112e0, 0x112ea, 1}, + {0x1123e, 0x11241, 3}, + {0x112df, 0x112ea, 1}, {0x11300, 0x11303, 1}, {0x1133b, 0x1133c, 1}, {0x1133e, 0x11344, 1}, @@ -1825,6 +1912,12 @@ var _M = &RangeTable{ {0x11d90, 0x11d91, 1}, {0x11d93, 0x11d97, 1}, {0x11ef3, 0x11ef6, 1}, + {0x11f00, 0x11f01, 1}, + {0x11f03, 0x11f34, 49}, + {0x11f35, 0x11f3a, 1}, + {0x11f3e, 0x11f42, 1}, + {0x13440, 0x13447, 7}, + {0x13448, 0x13455, 1}, {0x16af0, 0x16af4, 1}, {0x16b30, 0x16b36, 1}, {0x16f4f, 0x16f51, 2}, @@ -1832,8 +1925,10 @@ var _M = &RangeTable{ {0x16f8f, 0x16f92, 1}, {0x16fe4, 0x16ff0, 12}, {0x16ff1, 0x1bc9d, 19628}, - {0x1bc9e, 0x1d165, 5319}, - {0x1d166, 0x1d169, 1}, + {0x1bc9e, 0x1cf00, 4706}, + {0x1cf01, 0x1cf2d, 1}, + {0x1cf30, 0x1cf46, 1}, + {0x1d165, 0x1d169, 1}, {0x1d16d, 0x1d172, 1}, {0x1d17b, 0x1d182, 1}, {0x1d185, 0x1d18b, 1}, @@ -1849,8 +1944,11 @@ var _M = &RangeTable{ {0x1e01b, 0x1e021, 1}, {0x1e023, 0x1e024, 1}, {0x1e026, 0x1e02a, 1}, - {0x1e130, 0x1e136, 1}, - {0x1e2ec, 0x1e2ef, 1}, + {0x1e08f, 0x1e130, 161}, + {0x1e131, 0x1e136, 1}, + {0x1e2ae, 0x1e2ec, 62}, + {0x1e2ed, 0x1e2ef, 1}, + {0x1e4ec, 0x1e4ef, 1}, {0x1e8d0, 0x1e8d6, 1}, {0x1e944, 0x1e94a, 1}, {0xe0100, 0xe01ef, 1}, @@ -1890,8 +1988,9 @@ var _Mc = &RangeTable{ {0x0cc7, 0x0cc8, 1}, {0x0cca, 0x0ccb, 1}, {0x0cd5, 0x0cd6, 1}, - {0x0d02, 0x0d03, 1}, - {0x0d3e, 0x0d40, 1}, + {0x0cf3, 0x0d02, 15}, + {0x0d03, 0x0d3e, 59}, + {0x0d3f, 0x0d40, 1}, {0x0d46, 0x0d48, 1}, {0x0d4a, 0x0d4c, 1}, {0x0d57, 0x0d82, 43}, @@ -1911,6 +2010,7 @@ var _Mc = &RangeTable{ {0x1087, 0x108c, 1}, {0x108f, 0x109a, 11}, {0x109b, 0x109c, 1}, + {0x1715, 0x1734, 31}, {0x17b6, 0x17be, 8}, {0x17bf, 0x17c5, 1}, {0x17c7, 0x17c8, 1}, @@ -2009,7 +2109,10 @@ var _Mc = &RangeTable{ {0x11d8a, 0x11d8e, 1}, {0x11d93, 0x11d94, 1}, {0x11d96, 0x11ef5, 351}, - {0x11ef6, 0x16f51, 20571}, + {0x11ef6, 0x11f03, 13}, + {0x11f34, 0x11f35, 1}, + {0x11f3e, 0x11f3f, 1}, + {0x11f41, 0x16f51, 20496}, {0x16f52, 0x16f87, 1}, {0x16ff0, 0x16ff1, 1}, {0x1d165, 0x1d166, 1}, @@ -2052,7 +2155,8 @@ var _Mn = &RangeTable{ {0x0825, 0x0827, 1}, {0x0829, 0x082d, 1}, {0x0859, 0x085b, 1}, - {0x08d3, 0x08e1, 1}, + {0x0898, 0x089f, 1}, + {0x08ca, 0x08e1, 1}, {0x08e3, 0x0902, 1}, {0x093a, 0x093c, 2}, {0x0941, 0x0948, 1}, @@ -2085,7 +2189,8 @@ var _Mn = &RangeTable{ {0x0b63, 0x0b82, 31}, {0x0bc0, 0x0bcd, 13}, {0x0c00, 0x0c04, 4}, - {0x0c3e, 0x0c40, 1}, + {0x0c3c, 0x0c3e, 2}, + {0x0c3f, 0x0c40, 1}, {0x0c46, 0x0c48, 1}, {0x0c4a, 0x0c4d, 1}, {0x0c55, 0x0c56, 1}, @@ -2106,7 +2211,7 @@ var _Mn = &RangeTable{ {0x0e47, 0x0e4e, 1}, {0x0eb1, 0x0eb4, 3}, {0x0eb5, 0x0ebc, 1}, - {0x0ec8, 0x0ecd, 1}, + {0x0ec8, 0x0ece, 1}, {0x0f18, 0x0f19, 1}, {0x0f35, 0x0f39, 2}, {0x0f71, 0x0f7e, 1}, @@ -2127,7 +2232,7 @@ var _Mn = &RangeTable{ {0x109d, 0x135d, 704}, {0x135e, 0x135f, 1}, {0x1712, 0x1714, 1}, - {0x1732, 0x1734, 1}, + {0x1732, 0x1733, 1}, {0x1752, 0x1753, 1}, {0x1772, 0x1773, 1}, {0x17b4, 0x17b5, 1}, @@ -2136,9 +2241,9 @@ var _Mn = &RangeTable{ {0x17ca, 0x17d3, 1}, {0x17dd, 0x180b, 46}, {0x180c, 0x180d, 1}, - {0x1885, 0x1886, 1}, - {0x18a9, 0x1920, 119}, - {0x1921, 0x1922, 1}, + {0x180f, 0x1885, 118}, + {0x1886, 0x18a9, 35}, + {0x1920, 0x1922, 1}, {0x1927, 0x1928, 1}, {0x1932, 0x1939, 7}, {0x193a, 0x193b, 1}, @@ -2150,7 +2255,7 @@ var _Mn = &RangeTable{ {0x1a73, 0x1a7c, 1}, {0x1a7f, 0x1ab0, 49}, {0x1ab1, 0x1abd, 1}, - {0x1abf, 0x1ac0, 1}, + {0x1abf, 0x1ace, 1}, {0x1b00, 0x1b03, 1}, {0x1b34, 0x1b36, 2}, {0x1b37, 0x1b3a, 1}, @@ -2170,8 +2275,7 @@ var _Mn = &RangeTable{ {0x1ce2, 0x1ce8, 1}, {0x1ced, 0x1cf4, 7}, {0x1cf8, 0x1cf9, 1}, - {0x1dc0, 0x1df9, 1}, - {0x1dfb, 0x1dff, 1}, + {0x1dc0, 0x1dff, 1}, {0x20d0, 0x20dc, 1}, {0x20e1, 0x20e5, 4}, {0x20e6, 0x20f0, 1}, @@ -2223,13 +2327,18 @@ var _Mn = &RangeTable{ {0x10ae6, 0x10d24, 574}, {0x10d25, 0x10d27, 1}, {0x10eab, 0x10eac, 1}, + {0x10efd, 0x10eff, 1}, {0x10f46, 0x10f50, 1}, + {0x10f82, 0x10f85, 1}, {0x11001, 0x11038, 55}, {0x11039, 0x11046, 1}, - {0x1107f, 0x11081, 1}, + {0x11070, 0x11073, 3}, + {0x11074, 0x1107f, 11}, + {0x11080, 0x11081, 1}, {0x110b3, 0x110b6, 1}, {0x110b9, 0x110ba, 1}, - {0x11100, 0x11102, 1}, + {0x110c2, 0x11100, 62}, + {0x11101, 0x11102, 1}, {0x11127, 0x1112b, 1}, {0x1112d, 0x11134, 1}, {0x11173, 0x11180, 13}, @@ -2240,8 +2349,8 @@ var _Mn = &RangeTable{ {0x11230, 0x11231, 1}, {0x11234, 0x11236, 2}, {0x11237, 0x1123e, 7}, - {0x112df, 0x112e3, 4}, - {0x112e4, 0x112ea, 1}, + {0x11241, 0x112df, 158}, + {0x112e3, 0x112ea, 1}, {0x11300, 0x11301, 1}, {0x1133b, 0x1133c, 1}, {0x11340, 0x11366, 38}, @@ -2296,14 +2405,21 @@ var _Mn = &RangeTable{ {0x11d47, 0x11d90, 73}, {0x11d91, 0x11d95, 4}, {0x11d97, 0x11ef3, 348}, - {0x11ef4, 0x16af0, 19452}, - {0x16af1, 0x16af4, 1}, + {0x11ef4, 0x11f00, 12}, + {0x11f01, 0x11f36, 53}, + {0x11f37, 0x11f3a, 1}, + {0x11f40, 0x11f42, 2}, + {0x13440, 0x13447, 7}, + {0x13448, 0x13455, 1}, + {0x16af0, 0x16af4, 1}, {0x16b30, 0x16b36, 1}, {0x16f4f, 0x16f8f, 64}, {0x16f90, 0x16f92, 1}, {0x16fe4, 0x1bc9d, 19641}, - {0x1bc9e, 0x1d167, 5321}, - {0x1d168, 0x1d169, 1}, + {0x1bc9e, 0x1cf00, 4706}, + {0x1cf01, 0x1cf2d, 1}, + {0x1cf30, 0x1cf46, 1}, + {0x1d167, 0x1d169, 1}, {0x1d17b, 0x1d182, 1}, {0x1d185, 0x1d18b, 1}, {0x1d1aa, 0x1d1ad, 1}, @@ -2318,8 +2434,11 @@ var _Mn = &RangeTable{ {0x1e01b, 0x1e021, 1}, {0x1e023, 0x1e024, 1}, {0x1e026, 0x1e02a, 1}, - {0x1e130, 0x1e136, 1}, - {0x1e2ec, 0x1e2ef, 1}, + {0x1e08f, 0x1e130, 161}, + {0x1e131, 0x1e136, 1}, + {0x1e2ae, 0x1e2ec, 62}, + {0x1e2ed, 0x1e2ef, 1}, + {0x1e4ec, 0x1e4ef, 1}, {0x1e8d0, 0x1e8d6, 1}, {0x1e944, 0x1e94a, 1}, {0xe0100, 0xe01ef, 1}, @@ -2441,17 +2560,21 @@ var _N = &RangeTable{ {0x11c50, 0x11c6c, 1}, {0x11d50, 0x11d59, 1}, {0x11da0, 0x11da9, 1}, + {0x11f50, 0x11f59, 1}, {0x11fc0, 0x11fd4, 1}, {0x12400, 0x1246e, 1}, {0x16a60, 0x16a69, 1}, + {0x16ac0, 0x16ac9, 1}, {0x16b50, 0x16b59, 1}, {0x16b5b, 0x16b61, 1}, {0x16e80, 0x16e96, 1}, + {0x1d2c0, 0x1d2d3, 1}, {0x1d2e0, 0x1d2f3, 1}, {0x1d360, 0x1d378, 1}, {0x1d7ce, 0x1d7ff, 1}, {0x1e140, 0x1e149, 1}, {0x1e2f0, 0x1e2f9, 1}, + {0x1e4f0, 0x1e4f9, 1}, {0x1e8c7, 0x1e8cf, 1}, {0x1e950, 0x1e959, 1}, {0x1ec71, 0x1ecab, 1}, @@ -2523,11 +2646,14 @@ var _Nd = &RangeTable{ {0x11c50, 0x11c59, 1}, {0x11d50, 0x11d59, 1}, {0x11da0, 0x11da9, 1}, + {0x11f50, 0x11f59, 1}, {0x16a60, 0x16a69, 1}, + {0x16ac0, 0x16ac9, 1}, {0x16b50, 0x16b59, 1}, {0x1d7ce, 0x1d7ff, 1}, {0x1e140, 0x1e149, 1}, {0x1e2f0, 0x1e2f9, 1}, + {0x1e4f0, 0x1e4f9, 1}, {0x1e950, 0x1e959, 1}, {0x1fbf0, 0x1fbf9, 1}, }, @@ -2617,6 +2743,7 @@ var _No = &RangeTable{ {0x11fc0, 0x11fd4, 1}, {0x16b5b, 0x16b61, 1}, {0x16e80, 0x16e96, 1}, + {0x1d2c0, 0x1d2d3, 1}, {0x1d2e0, 0x1d2f3, 1}, {0x1d360, 0x1d378, 1}, {0x1e8c7, 0x1e8cf, 1}, @@ -2651,9 +2778,9 @@ var _P = &RangeTable{ {0x05f3, 0x05f4, 1}, {0x0609, 0x060a, 1}, {0x060c, 0x060d, 1}, - {0x061b, 0x061e, 3}, - {0x061f, 0x066a, 75}, - {0x066b, 0x066d, 1}, + {0x061b, 0x061d, 2}, + {0x061e, 0x061f, 1}, + {0x066a, 0x066d, 1}, {0x06d4, 0x0700, 44}, {0x0701, 0x070d, 1}, {0x07f7, 0x07f9, 1}, @@ -2686,6 +2813,7 @@ var _P = &RangeTable{ {0x1aa0, 0x1aa6, 1}, {0x1aa8, 0x1aad, 1}, {0x1b5a, 0x1b60, 1}, + {0x1b7d, 0x1b7e, 1}, {0x1bfc, 0x1bff, 1}, {0x1c3b, 0x1c3f, 1}, {0x1c7e, 0x1c7f, 1}, @@ -2710,8 +2838,8 @@ var _P = &RangeTable{ {0x2d70, 0x2e00, 144}, {0x2e01, 0x2e2e, 1}, {0x2e30, 0x2e4f, 1}, - {0x2e52, 0x3001, 431}, - {0x3002, 0x3003, 1}, + {0x2e52, 0x2e5d, 1}, + {0x3001, 0x3003, 1}, {0x3008, 0x3011, 1}, {0x3014, 0x301f, 1}, {0x3030, 0x303d, 13}, @@ -2759,6 +2887,7 @@ var _P = &RangeTable{ {0x10b99, 0x10b9c, 1}, {0x10ead, 0x10f55, 168}, {0x10f56, 0x10f59, 1}, + {0x10f86, 0x10f89, 1}, {0x11047, 0x1104d, 1}, {0x110bb, 0x110bc, 1}, {0x110be, 0x110c1, 1}, @@ -2775,18 +2904,22 @@ var _P = &RangeTable{ {0x115c1, 0x115d7, 1}, {0x11641, 0x11643, 1}, {0x11660, 0x1166c, 1}, - {0x1173c, 0x1173e, 1}, + {0x116b9, 0x1173c, 131}, + {0x1173d, 0x1173e, 1}, {0x1183b, 0x11944, 265}, {0x11945, 0x11946, 1}, {0x119e2, 0x11a3f, 93}, {0x11a40, 0x11a46, 1}, {0x11a9a, 0x11a9c, 1}, {0x11a9e, 0x11aa2, 1}, + {0x11b00, 0x11b09, 1}, {0x11c41, 0x11c45, 1}, {0x11c70, 0x11c71, 1}, {0x11ef7, 0x11ef8, 1}, + {0x11f43, 0x11f4f, 1}, {0x11fff, 0x12470, 1137}, {0x12471, 0x12474, 1}, + {0x12ff1, 0x12ff2, 1}, {0x16a6e, 0x16a6f, 1}, {0x16af5, 0x16b37, 66}, {0x16b38, 0x16b3b, 1}, @@ -2817,11 +2950,11 @@ var _Pd = &RangeTable{ {0x2011, 0x2015, 1}, {0x2e17, 0x2e1a, 3}, {0x2e3a, 0x2e3b, 1}, - {0x2e40, 0x301c, 476}, - {0x3030, 0x30a0, 112}, - {0xfe31, 0xfe32, 1}, - {0xfe58, 0xfe63, 11}, - {0xff0d, 0xff0d, 1}, + {0x2e40, 0x2e5d, 29}, + {0x301c, 0x3030, 20}, + {0x30a0, 0xfe31, 52625}, + {0xfe32, 0xfe58, 38}, + {0xfe63, 0xff0d, 170}, }, R32: []Range32{ {0x10ead, 0x10ead, 1}, @@ -2843,6 +2976,7 @@ var _Pe = &RangeTable{ {0x29d9, 0x29db, 2}, {0x29fd, 0x2e23, 1062}, {0x2e25, 0x2e29, 2}, + {0x2e56, 0x2e5c, 2}, {0x3009, 0x3011, 2}, {0x3015, 0x301b, 2}, {0x301e, 0x301f, 1}, @@ -2895,9 +3029,9 @@ var _Po = &RangeTable{ {0x05f3, 0x05f4, 1}, {0x0609, 0x060a, 1}, {0x060c, 0x060d, 1}, - {0x061b, 0x061e, 3}, - {0x061f, 0x066a, 75}, - {0x066b, 0x066d, 1}, + {0x061b, 0x061d, 2}, + {0x061e, 0x061f, 1}, + {0x066a, 0x066d, 1}, {0x06d4, 0x0700, 44}, {0x0701, 0x070d, 1}, {0x07f7, 0x07f9, 1}, @@ -2928,6 +3062,7 @@ var _Po = &RangeTable{ {0x1aa0, 0x1aa6, 1}, {0x1aa8, 0x1aad, 1}, {0x1b5a, 0x1b60, 1}, + {0x1b7d, 0x1b7e, 1}, {0x1bfc, 0x1bff, 1}, {0x1c3b, 0x1c3f, 1}, {0x1c7e, 0x1c7f, 1}, @@ -2956,8 +3091,8 @@ var _Po = &RangeTable{ {0x2e3c, 0x2e3f, 1}, {0x2e41, 0x2e43, 2}, {0x2e44, 0x2e4f, 1}, - {0x2e52, 0x3001, 431}, - {0x3002, 0x3003, 1}, + {0x2e52, 0x2e54, 1}, + {0x3001, 0x3003, 1}, {0x303d, 0x30fb, 190}, {0xa4fe, 0xa4ff, 1}, {0xa60d, 0xa60f, 1}, @@ -3003,6 +3138,7 @@ var _Po = &RangeTable{ {0x10b39, 0x10b3f, 1}, {0x10b99, 0x10b9c, 1}, {0x10f55, 0x10f59, 1}, + {0x10f86, 0x10f89, 1}, {0x11047, 0x1104d, 1}, {0x110bb, 0x110bc, 1}, {0x110be, 0x110c1, 1}, @@ -3019,18 +3155,22 @@ var _Po = &RangeTable{ {0x115c1, 0x115d7, 1}, {0x11641, 0x11643, 1}, {0x11660, 0x1166c, 1}, - {0x1173c, 0x1173e, 1}, + {0x116b9, 0x1173c, 131}, + {0x1173d, 0x1173e, 1}, {0x1183b, 0x11944, 265}, {0x11945, 0x11946, 1}, {0x119e2, 0x11a3f, 93}, {0x11a40, 0x11a46, 1}, {0x11a9a, 0x11a9c, 1}, {0x11a9e, 0x11aa2, 1}, + {0x11b00, 0x11b09, 1}, {0x11c41, 0x11c45, 1}, {0x11c70, 0x11c71, 1}, {0x11ef7, 0x11ef8, 1}, + {0x11f43, 0x11f4f, 1}, {0x11fff, 0x12470, 1137}, {0x12471, 0x12474, 1}, + {0x12ff1, 0x12ff2, 1}, {0x16a6e, 0x16a6f, 1}, {0x16af5, 0x16b37, 66}, {0x16b38, 0x16b3b, 1}, @@ -3059,8 +3199,9 @@ var _Ps = &RangeTable{ {0x29d8, 0x29da, 2}, {0x29fc, 0x2e22, 1062}, {0x2e24, 0x2e28, 2}, - {0x2e42, 0x3008, 454}, - {0x300a, 0x3010, 2}, + {0x2e42, 0x2e55, 19}, + {0x2e57, 0x2e5b, 2}, + {0x3008, 0x3010, 2}, {0x3014, 0x301a, 2}, {0x301d, 0xfd3f, 52514}, {0xfe17, 0xfe35, 30}, @@ -3101,10 +3242,11 @@ var _S = &RangeTable{ {0x06e9, 0x06fd, 20}, {0x06fe, 0x07f6, 248}, {0x07fe, 0x07ff, 1}, - {0x09f2, 0x09f3, 1}, - {0x09fa, 0x09fb, 1}, - {0x0af1, 0x0b70, 127}, - {0x0bf3, 0x0bfa, 1}, + {0x0888, 0x09f2, 362}, + {0x09f3, 0x09fa, 7}, + {0x09fb, 0x0af1, 246}, + {0x0b70, 0x0bf3, 131}, + {0x0bf4, 0x0bfa, 1}, {0x0c7f, 0x0d4f, 208}, {0x0d79, 0x0e3f, 198}, {0x0f01, 0x0f03, 1}, @@ -3132,7 +3274,7 @@ var _S = &RangeTable{ {0x2044, 0x2052, 14}, {0x207a, 0x207c, 1}, {0x208a, 0x208c, 1}, - {0x20a0, 0x20bf, 1}, + {0x20a0, 0x20c0, 1}, {0x2100, 0x2101, 1}, {0x2103, 0x2106, 1}, {0x2108, 0x2109, 1}, @@ -3190,8 +3332,10 @@ var _S = &RangeTable{ {0xaa77, 0xaa79, 1}, {0xab5b, 0xab6a, 15}, {0xab6b, 0xfb29, 20414}, - {0xfbb2, 0xfbc1, 1}, - {0xfdfc, 0xfdfd, 1}, + {0xfbb2, 0xfbc2, 1}, + {0xfd40, 0xfd4f, 1}, + {0xfdcf, 0xfdfc, 45}, + {0xfdfd, 0xfdff, 1}, {0xfe62, 0xfe64, 2}, {0xfe65, 0xfe66, 1}, {0xfe69, 0xff04, 155}, @@ -3215,13 +3359,14 @@ var _S = &RangeTable{ {0x11fd5, 0x11ff1, 1}, {0x16b3c, 0x16b3f, 1}, {0x16b45, 0x1bc9c, 20823}, + {0x1cf50, 0x1cfc3, 1}, {0x1d000, 0x1d0f5, 1}, {0x1d100, 0x1d126, 1}, {0x1d129, 0x1d164, 1}, {0x1d16a, 0x1d16c, 1}, {0x1d183, 0x1d184, 1}, {0x1d18c, 0x1d1a9, 1}, - {0x1d1ae, 0x1d1e8, 1}, + {0x1d1ae, 0x1d1ea, 1}, {0x1d200, 0x1d241, 1}, {0x1d245, 0x1d300, 187}, {0x1d301, 0x1d356, 1}, @@ -3252,28 +3397,27 @@ var _S = &RangeTable{ {0x1f250, 0x1f251, 1}, {0x1f260, 0x1f265, 1}, {0x1f300, 0x1f6d7, 1}, - {0x1f6e0, 0x1f6ec, 1}, + {0x1f6dc, 0x1f6ec, 1}, {0x1f6f0, 0x1f6fc, 1}, - {0x1f700, 0x1f773, 1}, - {0x1f780, 0x1f7d8, 1}, + {0x1f700, 0x1f776, 1}, + {0x1f77b, 0x1f7d9, 1}, {0x1f7e0, 0x1f7eb, 1}, - {0x1f800, 0x1f80b, 1}, + {0x1f7f0, 0x1f800, 16}, + {0x1f801, 0x1f80b, 1}, {0x1f810, 0x1f847, 1}, {0x1f850, 0x1f859, 1}, {0x1f860, 0x1f887, 1}, {0x1f890, 0x1f8ad, 1}, {0x1f8b0, 0x1f8b1, 1}, - {0x1f900, 0x1f978, 1}, - {0x1f97a, 0x1f9cb, 1}, - {0x1f9cd, 0x1fa53, 1}, + {0x1f900, 0x1fa53, 1}, {0x1fa60, 0x1fa6d, 1}, - {0x1fa70, 0x1fa74, 1}, - {0x1fa78, 0x1fa7a, 1}, - {0x1fa80, 0x1fa86, 1}, - {0x1fa90, 0x1faa8, 1}, - {0x1fab0, 0x1fab6, 1}, - {0x1fac0, 0x1fac2, 1}, - {0x1fad0, 0x1fad6, 1}, + {0x1fa70, 0x1fa7c, 1}, + {0x1fa80, 0x1fa88, 1}, + {0x1fa90, 0x1fabd, 1}, + {0x1fabf, 0x1fac5, 1}, + {0x1face, 0x1fadb, 1}, + {0x1fae0, 0x1fae8, 1}, + {0x1faf0, 0x1faf8, 1}, {0x1fb00, 0x1fb92, 1}, {0x1fb94, 0x1fbca, 1}, }, @@ -3290,7 +3434,7 @@ var _Sc = &RangeTable{ {0x09fb, 0x0af1, 246}, {0x0bf9, 0x0e3f, 582}, {0x17db, 0x20a0, 2245}, - {0x20a1, 0x20bf, 1}, + {0x20a1, 0x20c0, 1}, {0xa838, 0xfdfc, 21956}, {0xfe69, 0xff04, 155}, {0xffe0, 0xffe1, 1}, @@ -3314,8 +3458,9 @@ var _Sk = &RangeTable{ {0x02ed, 0x02ef, 2}, {0x02f0, 0x02ff, 1}, {0x0375, 0x0384, 15}, - {0x0385, 0x1fbd, 7224}, - {0x1fbf, 0x1fc1, 1}, + {0x0385, 0x0888, 1283}, + {0x1fbd, 0x1fbf, 2}, + {0x1fc0, 0x1fc1, 1}, {0x1fcd, 0x1fcf, 1}, {0x1fdd, 0x1fdf, 1}, {0x1fed, 0x1fef, 1}, @@ -3326,7 +3471,7 @@ var _Sk = &RangeTable{ {0xa789, 0xa78a, 1}, {0xab5b, 0xab6a, 15}, {0xab6b, 0xfbb2, 20551}, - {0xfbb3, 0xfbc1, 1}, + {0xfbb3, 0xfbc2, 1}, {0xff3e, 0xff40, 2}, {0xffe3, 0xffe3, 1}, }, @@ -3488,10 +3633,12 @@ var _So = &RangeTable{ {0xa836, 0xa837, 1}, {0xa839, 0xaa77, 574}, {0xaa78, 0xaa79, 1}, - {0xfdfd, 0xffe4, 487}, - {0xffe8, 0xffed, 5}, - {0xffee, 0xfffc, 14}, - {0xfffd, 0xfffd, 1}, + {0xfd40, 0xfd4f, 1}, + {0xfdcf, 0xfdfd, 46}, + {0xfdfe, 0xfdff, 1}, + {0xffe4, 0xffe8, 4}, + {0xffed, 0xffee, 1}, + {0xfffc, 0xfffd, 1}, }, R32: []Range32{ {0x10137, 0x1013f, 1}, @@ -3506,13 +3653,14 @@ var _So = &RangeTable{ {0x11fe1, 0x11ff1, 1}, {0x16b3c, 0x16b3f, 1}, {0x16b45, 0x1bc9c, 20823}, + {0x1cf50, 0x1cfc3, 1}, {0x1d000, 0x1d0f5, 1}, {0x1d100, 0x1d126, 1}, {0x1d129, 0x1d164, 1}, {0x1d16a, 0x1d16c, 1}, {0x1d183, 0x1d184, 1}, {0x1d18c, 0x1d1a9, 1}, - {0x1d1ae, 0x1d1e8, 1}, + {0x1d1ae, 0x1d1ea, 1}, {0x1d200, 0x1d241, 1}, {0x1d245, 0x1d300, 187}, {0x1d301, 0x1d356, 1}, @@ -3537,28 +3685,27 @@ var _So = &RangeTable{ {0x1f260, 0x1f265, 1}, {0x1f300, 0x1f3fa, 1}, {0x1f400, 0x1f6d7, 1}, - {0x1f6e0, 0x1f6ec, 1}, + {0x1f6dc, 0x1f6ec, 1}, {0x1f6f0, 0x1f6fc, 1}, - {0x1f700, 0x1f773, 1}, - {0x1f780, 0x1f7d8, 1}, + {0x1f700, 0x1f776, 1}, + {0x1f77b, 0x1f7d9, 1}, {0x1f7e0, 0x1f7eb, 1}, - {0x1f800, 0x1f80b, 1}, + {0x1f7f0, 0x1f800, 16}, + {0x1f801, 0x1f80b, 1}, {0x1f810, 0x1f847, 1}, {0x1f850, 0x1f859, 1}, {0x1f860, 0x1f887, 1}, {0x1f890, 0x1f8ad, 1}, {0x1f8b0, 0x1f8b1, 1}, - {0x1f900, 0x1f978, 1}, - {0x1f97a, 0x1f9cb, 1}, - {0x1f9cd, 0x1fa53, 1}, + {0x1f900, 0x1fa53, 1}, {0x1fa60, 0x1fa6d, 1}, - {0x1fa70, 0x1fa74, 1}, - {0x1fa78, 0x1fa7a, 1}, - {0x1fa80, 0x1fa86, 1}, - {0x1fa90, 0x1faa8, 1}, - {0x1fab0, 0x1fab6, 1}, - {0x1fac0, 0x1fac2, 1}, - {0x1fad0, 0x1fad6, 1}, + {0x1fa70, 0x1fa7c, 1}, + {0x1fa80, 0x1fa88, 1}, + {0x1fa90, 0x1fabd, 1}, + {0x1fabf, 0x1fac5, 1}, + {0x1face, 0x1fadb, 1}, + {0x1fae0, 0x1fae8, 1}, + {0x1faf0, 0x1faf8, 1}, {0x1fb00, 0x1fb92, 1}, {0x1fb94, 0x1fbca, 1}, }, @@ -3681,6 +3828,7 @@ var Scripts = map[string]*RangeTable{ "Coptic": Coptic, "Cuneiform": Cuneiform, "Cypriot": Cypriot, + "Cypro_Minoan": Cypro_Minoan, "Cyrillic": Cyrillic, "Deseret": Deseret, "Devanagari": Devanagari, @@ -3714,6 +3862,7 @@ var Scripts = map[string]*RangeTable{ "Kaithi": Kaithi, "Kannada": Kannada, "Katakana": Katakana, + "Kawi": Kawi, "Kayah_Li": Kayah_Li, "Kharoshthi": Kharoshthi, "Khitan_Small_Script": Khitan_Small_Script, @@ -3748,6 +3897,7 @@ var Scripts = map[string]*RangeTable{ "Multani": Multani, "Myanmar": Myanmar, "Nabataean": Nabataean, + "Nag_Mundari": Nag_Mundari, "Nandinagari": Nandinagari, "New_Tai_Lue": New_Tai_Lue, "Newa": Newa, @@ -3764,6 +3914,7 @@ var Scripts = map[string]*RangeTable{ "Old_Sogdian": Old_Sogdian, "Old_South_Arabian": Old_South_Arabian, "Old_Turkic": Old_Turkic, + "Old_Uyghur": Old_Uyghur, "Oriya": Oriya, "Osage": Osage, "Osmanya": Osmanya, @@ -3795,6 +3946,7 @@ var Scripts = map[string]*RangeTable{ "Tai_Viet": Tai_Viet, "Takri": Takri, "Tamil": Tamil, + "Tangsa": Tangsa, "Tangut": Tangut, "Telugu": Telugu, "Thaana": Thaana, @@ -3802,8 +3954,10 @@ var Scripts = map[string]*RangeTable{ "Tibetan": Tibetan, "Tifinagh": Tifinagh, "Tirhuta": Tirhuta, + "Toto": Toto, "Ugaritic": Ugaritic, "Vai": Vai, + "Vithkuqi": Vithkuqi, "Wancho": Wancho, "Warang_Citi": Warang_Citi, "Yezidi": Yezidi, @@ -3825,7 +3979,7 @@ var _Ahom = &RangeTable{ R32: []Range32{ {0x11700, 0x1171a, 1}, {0x1171d, 0x1172b, 1}, - {0x11730, 0x1173f, 1}, + {0x11730, 0x11746, 1}, }, } @@ -3841,27 +3995,29 @@ var _Arabic = &RangeTable{ {0x0600, 0x0604, 1}, {0x0606, 0x060b, 1}, {0x060d, 0x061a, 1}, - {0x061c, 0x0620, 2}, - {0x0621, 0x063f, 1}, + {0x061c, 0x061e, 1}, + {0x0620, 0x063f, 1}, {0x0641, 0x064a, 1}, {0x0656, 0x066f, 1}, {0x0671, 0x06dc, 1}, {0x06de, 0x06ff, 1}, {0x0750, 0x077f, 1}, - {0x08a0, 0x08b4, 1}, - {0x08b6, 0x08c7, 1}, - {0x08d3, 0x08e1, 1}, + {0x0870, 0x088e, 1}, + {0x0890, 0x0891, 1}, + {0x0898, 0x08e1, 1}, {0x08e3, 0x08ff, 1}, - {0xfb50, 0xfbc1, 1}, + {0xfb50, 0xfbc2, 1}, {0xfbd3, 0xfd3d, 1}, - {0xfd50, 0xfd8f, 1}, + {0xfd40, 0xfd8f, 1}, {0xfd92, 0xfdc7, 1}, - {0xfdf0, 0xfdfd, 1}, + {0xfdcf, 0xfdf0, 33}, + {0xfdf1, 0xfdff, 1}, {0xfe70, 0xfe74, 1}, {0xfe76, 0xfefc, 1}, }, R32: []Range32{ {0x10e60, 0x10e7e, 1}, + {0x10efd, 0x10eff, 1}, {0x1ee00, 0x1ee03, 1}, {0x1ee05, 0x1ee1f, 1}, {0x1ee21, 0x1ee22, 1}, @@ -3909,8 +4065,8 @@ var _Avestan = &RangeTable{ var _Balinese = &RangeTable{ R16: []Range16{ - {0x1b00, 0x1b4b, 1}, - {0x1b50, 0x1b7c, 1}, + {0x1b00, 0x1b4c, 1}, + {0x1b50, 0x1b7e, 1}, }, } @@ -3979,7 +4135,7 @@ var _Brahmi = &RangeTable{ R16: []Range16{}, R32: []Range32{ {0x11000, 0x1104d, 1}, - {0x11052, 0x1106f, 1}, + {0x11052, 0x11075, 1}, {0x1107f, 0x1107f, 1}, }, } @@ -4008,6 +4164,9 @@ var _Canadian_Aboriginal = &RangeTable{ {0x1400, 0x167f, 1}, {0x18b0, 0x18f5, 1}, }, + R32: []Range32{ + {0x11ab0, 0x11abf, 1}, + }, } var _Carian = &RangeTable{ @@ -4091,7 +4250,7 @@ var _Common = &RangeTable{ {0x2066, 0x2070, 1}, {0x2074, 0x207e, 1}, {0x2080, 0x208e, 1}, - {0x20a0, 0x20bf, 1}, + {0x20a0, 0x20c0, 1}, {0x2100, 0x2125, 1}, {0x2127, 0x2129, 1}, {0x212c, 0x2131, 1}, @@ -4104,7 +4263,7 @@ var _Common = &RangeTable{ {0x2900, 0x2b73, 1}, {0x2b76, 0x2b95, 1}, {0x2b97, 0x2bff, 1}, - {0x2e00, 0x2e52, 1}, + {0x2e00, 0x2e5d, 1}, {0x2ff0, 0x2ffb, 1}, {0x3000, 0x3004, 1}, {0x3006, 0x3008, 2}, @@ -4149,15 +4308,16 @@ var _Common = &RangeTable{ {0x10190, 0x1019c, 1}, {0x101d0, 0x101fc, 1}, {0x102e1, 0x102fb, 1}, - {0x16fe2, 0x16fe3, 1}, {0x1bca0, 0x1bca3, 1}, + {0x1cf50, 0x1cfc3, 1}, {0x1d000, 0x1d0f5, 1}, {0x1d100, 0x1d126, 1}, {0x1d129, 0x1d166, 1}, {0x1d16a, 0x1d17a, 1}, {0x1d183, 0x1d184, 1}, {0x1d18c, 0x1d1a9, 1}, - {0x1d1ae, 0x1d1e8, 1}, + {0x1d1ae, 0x1d1ea, 1}, + {0x1d2c0, 0x1d2d3, 1}, {0x1d2e0, 0x1d2f3, 1}, {0x1d300, 0x1d356, 1}, {0x1d360, 0x1d378, 1}, @@ -4198,28 +4358,27 @@ var _Common = &RangeTable{ {0x1f250, 0x1f251, 1}, {0x1f260, 0x1f265, 1}, {0x1f300, 0x1f6d7, 1}, - {0x1f6e0, 0x1f6ec, 1}, + {0x1f6dc, 0x1f6ec, 1}, {0x1f6f0, 0x1f6fc, 1}, - {0x1f700, 0x1f773, 1}, - {0x1f780, 0x1f7d8, 1}, + {0x1f700, 0x1f776, 1}, + {0x1f77b, 0x1f7d9, 1}, {0x1f7e0, 0x1f7eb, 1}, - {0x1f800, 0x1f80b, 1}, + {0x1f7f0, 0x1f800, 16}, + {0x1f801, 0x1f80b, 1}, {0x1f810, 0x1f847, 1}, {0x1f850, 0x1f859, 1}, {0x1f860, 0x1f887, 1}, {0x1f890, 0x1f8ad, 1}, {0x1f8b0, 0x1f8b1, 1}, - {0x1f900, 0x1f978, 1}, - {0x1f97a, 0x1f9cb, 1}, - {0x1f9cd, 0x1fa53, 1}, + {0x1f900, 0x1fa53, 1}, {0x1fa60, 0x1fa6d, 1}, - {0x1fa70, 0x1fa74, 1}, - {0x1fa78, 0x1fa7a, 1}, - {0x1fa80, 0x1fa86, 1}, - {0x1fa90, 0x1faa8, 1}, - {0x1fab0, 0x1fab6, 1}, - {0x1fac0, 0x1fac2, 1}, - {0x1fad0, 0x1fad6, 1}, + {0x1fa70, 0x1fa7c, 1}, + {0x1fa80, 0x1fa88, 1}, + {0x1fa90, 0x1fabd, 1}, + {0x1fabf, 0x1fac5, 1}, + {0x1face, 0x1fadb, 1}, + {0x1fae0, 0x1fae8, 1}, + {0x1faf0, 0x1faf8, 1}, {0x1fb00, 0x1fb92, 1}, {0x1fb94, 0x1fbca, 1}, {0x1fbf0, 0x1fbf9, 1}, @@ -4258,6 +4417,13 @@ var _Cypriot = &RangeTable{ }, } +var _Cypro_Minoan = &RangeTable{ + R16: []Range16{}, + R32: []Range32{ + {0x12f90, 0x12ff2, 1}, + }, +} + var _Cyrillic = &RangeTable{ R16: []Range16{ {0x0400, 0x0484, 1}, @@ -4268,6 +4434,10 @@ var _Cyrillic = &RangeTable{ {0xa640, 0xa69f, 1}, {0xfe2e, 0xfe2f, 1}, }, + R32: []Range32{ + {0x1e030, 0x1e06d, 1}, + {0x1e08f, 0x1e08f, 1}, + }, } var _Deseret = &RangeTable{ @@ -4284,6 +4454,9 @@ var _Devanagari = &RangeTable{ {0x0966, 0x097f, 1}, {0xa8e0, 0xa8ff, 1}, }, + R32: []Range32{ + {0x11b00, 0x11b09, 1}, + }, } var _Dives_Akuru = &RangeTable{ @@ -4321,8 +4494,7 @@ var _Duployan = &RangeTable{ var _Egyptian_Hieroglyphs = &RangeTable{ R16: []Range16{}, R32: []Range32{ - {0x13000, 0x1342e, 1}, - {0x13430, 0x13438, 1}, + {0x13000, 0x13455, 1}, }, } @@ -4375,6 +4547,12 @@ var _Ethiopic = &RangeTable{ {0xab20, 0xab26, 1}, {0xab28, 0xab2e, 1}, }, + R32: []Range32{ + {0x1e7e0, 0x1e7e6, 1}, + {0x1e7e8, 0x1e7eb, 1}, + {0x1e7ed, 0x1e7ee, 1}, + {0x1e7f0, 0x1e7fe, 1}, + }, } var _Georgian = &RangeTable{ @@ -4392,8 +4570,7 @@ var _Georgian = &RangeTable{ var _Glagolitic = &RangeTable{ R16: []Range16{ - {0x2c00, 0x2c2e, 1}, - {0x2c30, 0x2c5e, 1}, + {0x2c00, 0x2c5f, 1}, }, R32: []Range32{ {0x1e000, 0x1e006, 1}, @@ -4531,19 +4708,21 @@ var _Han = &RangeTable{ {0x3021, 0x3029, 1}, {0x3038, 0x303b, 1}, {0x3400, 0x4dbf, 1}, - {0x4e00, 0x9ffc, 1}, + {0x4e00, 0x9fff, 1}, {0xf900, 0xfa6d, 1}, {0xfa70, 0xfad9, 1}, }, R32: []Range32{ + {0x16fe2, 0x16fe3, 1}, {0x16ff0, 0x16ff1, 1}, - {0x20000, 0x2a6dd, 1}, - {0x2a700, 0x2b734, 1}, + {0x20000, 0x2a6df, 1}, + {0x2a700, 0x2b739, 1}, {0x2b740, 0x2b81d, 1}, {0x2b820, 0x2cea1, 1}, {0x2ceb0, 0x2ebe0, 1}, {0x2f800, 0x2fa1d, 1}, {0x30000, 0x3134a, 1}, + {0x31350, 0x323af, 1}, }, } @@ -4609,8 +4788,9 @@ var _Hiragana = &RangeTable{ {0x309d, 0x309f, 1}, }, R32: []Range32{ - {0x1b001, 0x1b11e, 1}, - {0x1b150, 0x1b152, 1}, + {0x1b001, 0x1b11f, 1}, + {0x1b132, 0x1b150, 30}, + {0x1b151, 0x1b152, 1}, {0x1f200, 0x1f200, 1}, }, } @@ -4630,14 +4810,13 @@ var _Inherited = &RangeTable{ {0x064b, 0x0655, 1}, {0x0670, 0x0951, 737}, {0x0952, 0x0954, 1}, - {0x1ab0, 0x1ac0, 1}, + {0x1ab0, 0x1ace, 1}, {0x1cd0, 0x1cd2, 1}, {0x1cd4, 0x1ce0, 1}, {0x1ce2, 0x1ce8, 1}, {0x1ced, 0x1cf4, 7}, {0x1cf8, 0x1cf9, 1}, - {0x1dc0, 0x1df9, 1}, - {0x1dfb, 0x1dff, 1}, + {0x1dc0, 0x1dff, 1}, {0x200c, 0x200d, 1}, {0x20d0, 0x20f0, 1}, {0x302a, 0x302d, 1}, @@ -4647,8 +4826,10 @@ var _Inherited = &RangeTable{ }, R32: []Range32{ {0x101fd, 0x102e0, 227}, - {0x1133b, 0x1d167, 48684}, - {0x1d168, 0x1d169, 1}, + {0x1133b, 0x1cf00, 48069}, + {0x1cf01, 0x1cf2d, 1}, + {0x1cf30, 0x1cf46, 1}, + {0x1d167, 0x1d169, 1}, {0x1d17b, 0x1d182, 1}, {0x1d185, 0x1d18b, 1}, {0x1d1aa, 0x1d1ad, 1}, @@ -4683,7 +4864,7 @@ var _Javanese = &RangeTable{ var _Kaithi = &RangeTable{ R16: []Range16{}, R32: []Range32{ - {0x11080, 0x110c1, 1}, + {0x11080, 0x110c2, 1}, {0x110cd, 0x110cd, 1}, }, } @@ -4699,10 +4880,10 @@ var _Kannada = &RangeTable{ {0x0cc6, 0x0cc8, 1}, {0x0cca, 0x0ccd, 1}, {0x0cd5, 0x0cd6, 1}, - {0x0cde, 0x0ce0, 2}, - {0x0ce1, 0x0ce3, 1}, + {0x0cdd, 0x0cde, 1}, + {0x0ce0, 0x0ce3, 1}, {0x0ce6, 0x0cef, 1}, - {0x0cf1, 0x0cf2, 1}, + {0x0cf1, 0x0cf3, 1}, }, } @@ -4717,11 +4898,25 @@ var _Katakana = &RangeTable{ {0xff71, 0xff9d, 1}, }, R32: []Range32{ - {0x1b000, 0x1b164, 356}, + {0x1aff0, 0x1aff3, 1}, + {0x1aff5, 0x1affb, 1}, + {0x1affd, 0x1affe, 1}, + {0x1b000, 0x1b120, 288}, + {0x1b121, 0x1b122, 1}, + {0x1b155, 0x1b164, 15}, {0x1b165, 0x1b167, 1}, }, } +var _Kawi = &RangeTable{ + R16: []Range16{}, + R32: []Range32{ + {0x11f00, 0x11f10, 1}, + {0x11f12, 0x11f3a, 1}, + {0x11f3e, 0x11f59, 1}, + }, +} + var _Kayah_Li = &RangeTable{ R16: []Range16{ {0xa900, 0xa92d, 1}, @@ -4764,7 +4959,7 @@ var _Khojki = &RangeTable{ R16: []Range16{}, R32: []Range32{ {0x11200, 0x11211, 1}, - {0x11213, 0x1123e, 1}, + {0x11213, 0x11241, 1}, }, } @@ -4786,7 +4981,7 @@ var _Lao = &RangeTable{ {0x0ea8, 0x0ebd, 1}, {0x0ec0, 0x0ec4, 1}, {0x0ec6, 0x0ec8, 2}, - {0x0ec9, 0x0ecd, 1}, + {0x0ec9, 0x0ece, 1}, {0x0ed0, 0x0ed9, 1}, {0x0edc, 0x0edf, 1}, }, @@ -4814,9 +5009,11 @@ var _Latin = &RangeTable{ {0x2160, 0x2188, 1}, {0x2c60, 0x2c7f, 1}, {0xa722, 0xa787, 1}, - {0xa78b, 0xa7bf, 1}, - {0xa7c2, 0xa7ca, 1}, - {0xa7f5, 0xa7ff, 1}, + {0xa78b, 0xa7ca, 1}, + {0xa7d0, 0xa7d1, 1}, + {0xa7d3, 0xa7d5, 2}, + {0xa7d6, 0xa7d9, 1}, + {0xa7f2, 0xa7ff, 1}, {0xab30, 0xab5a, 1}, {0xab5c, 0xab64, 1}, {0xab66, 0xab69, 1}, @@ -4824,6 +5021,13 @@ var _Latin = &RangeTable{ {0xff21, 0xff3a, 1}, {0xff41, 0xff5a, 1}, }, + R32: []Range32{ + {0x10780, 0x10785, 1}, + {0x10787, 0x107b0, 1}, + {0x107b2, 0x107ba, 1}, + {0x1df00, 0x1df1e, 1}, + {0x1df25, 0x1df2a, 1}, + }, LatinOffset: 5, } @@ -5014,8 +5218,7 @@ var _Mongolian = &RangeTable{ R16: []Range16{ {0x1800, 0x1801, 1}, {0x1804, 0x1806, 2}, - {0x1807, 0x180e, 1}, - {0x1810, 0x1819, 1}, + {0x1807, 0x1819, 1}, {0x1820, 0x1878, 1}, {0x1880, 0x18aa, 1}, }, @@ -5060,6 +5263,13 @@ var _Nabataean = &RangeTable{ }, } +var _Nag_Mundari = &RangeTable{ + R16: []Range16{}, + R32: []Range32{ + {0x1e4d0, 0x1e4f9, 1}, + }, +} + var _Nandinagari = &RangeTable{ R16: []Range16{}, R32: []Range32{ @@ -5183,6 +5393,13 @@ var _Old_Turkic = &RangeTable{ }, } +var _Old_Uyghur = &RangeTable{ + R16: []Range16{}, + R32: []Range32{ + {0x10f70, 0x10f89, 1}, + }, +} + var _Oriya = &RangeTable{ R16: []Range16{ {0x0b01, 0x0b03, 1}, @@ -5391,8 +5608,8 @@ var _Syriac = &RangeTable{ var _Tagalog = &RangeTable{ R16: []Range16{ - {0x1700, 0x170c, 1}, - {0x170e, 0x1714, 1}, + {0x1700, 0x1715, 1}, + {0x171f, 0x171f, 1}, }, } @@ -5431,7 +5648,7 @@ var _Tai_Viet = &RangeTable{ var _Takri = &RangeTable{ R16: []Range16{}, R32: []Range32{ - {0x11680, 0x116b8, 1}, + {0x11680, 0x116b9, 1}, {0x116c0, 0x116c9, 1}, }, } @@ -5460,6 +5677,14 @@ var _Tamil = &RangeTable{ }, } +var _Tangsa = &RangeTable{ + R16: []Range16{}, + R32: []Range32{ + {0x16a70, 0x16abe, 1}, + {0x16ac0, 0x16ac9, 1}, + }, +} + var _Tangut = &RangeTable{ R16: []Range16{}, R32: []Range32{ @@ -5476,12 +5701,13 @@ var _Telugu = &RangeTable{ {0x0c0e, 0x0c10, 1}, {0x0c12, 0x0c28, 1}, {0x0c2a, 0x0c39, 1}, - {0x0c3d, 0x0c44, 1}, + {0x0c3c, 0x0c44, 1}, {0x0c46, 0x0c48, 1}, {0x0c4a, 0x0c4d, 1}, {0x0c55, 0x0c56, 1}, {0x0c58, 0x0c5a, 1}, - {0x0c60, 0x0c63, 1}, + {0x0c5d, 0x0c60, 3}, + {0x0c61, 0x0c63, 1}, {0x0c66, 0x0c6f, 1}, {0x0c77, 0x0c7f, 1}, }, @@ -5528,6 +5754,13 @@ var _Tirhuta = &RangeTable{ }, } +var _Toto = &RangeTable{ + R16: []Range16{}, + R32: []Range32{ + {0x1e290, 0x1e2ae, 1}, + }, +} + var _Ugaritic = &RangeTable{ R16: []Range16{}, R32: []Range32{ @@ -5542,6 +5775,20 @@ var _Vai = &RangeTable{ }, } +var _Vithkuqi = &RangeTable{ + R16: []Range16{}, + R32: []Range32{ + {0x10570, 0x1057a, 1}, + {0x1057c, 0x1058a, 1}, + {0x1058c, 0x10592, 1}, + {0x10594, 0x10595, 1}, + {0x10597, 0x105a1, 1}, + {0x105a3, 0x105b1, 1}, + {0x105b3, 0x105b9, 1}, + {0x105bb, 0x105bc, 1}, + }, +} + var _Wancho = &RangeTable{ R16: []Range16{}, R32: []Range32{ @@ -5611,6 +5858,7 @@ var ( Coptic = _Coptic // Coptic is the set of Unicode characters in script Coptic. Cuneiform = _Cuneiform // Cuneiform is the set of Unicode characters in script Cuneiform. Cypriot = _Cypriot // Cypriot is the set of Unicode characters in script Cypriot. + Cypro_Minoan = _Cypro_Minoan // Cypro_Minoan is the set of Unicode characters in script Cypro_Minoan. Cyrillic = _Cyrillic // Cyrillic is the set of Unicode characters in script Cyrillic. Deseret = _Deseret // Deseret is the set of Unicode characters in script Deseret. Devanagari = _Devanagari // Devanagari is the set of Unicode characters in script Devanagari. @@ -5644,6 +5892,7 @@ var ( Kaithi = _Kaithi // Kaithi is the set of Unicode characters in script Kaithi. Kannada = _Kannada // Kannada is the set of Unicode characters in script Kannada. Katakana = _Katakana // Katakana is the set of Unicode characters in script Katakana. + Kawi = _Kawi // Kawi is the set of Unicode characters in script Kawi. Kayah_Li = _Kayah_Li // Kayah_Li is the set of Unicode characters in script Kayah_Li. Kharoshthi = _Kharoshthi // Kharoshthi is the set of Unicode characters in script Kharoshthi. Khitan_Small_Script = _Khitan_Small_Script // Khitan_Small_Script is the set of Unicode characters in script Khitan_Small_Script. @@ -5678,6 +5927,7 @@ var ( Multani = _Multani // Multani is the set of Unicode characters in script Multani. Myanmar = _Myanmar // Myanmar is the set of Unicode characters in script Myanmar. Nabataean = _Nabataean // Nabataean is the set of Unicode characters in script Nabataean. + Nag_Mundari = _Nag_Mundari // Nag_Mundari is the set of Unicode characters in script Nag_Mundari. Nandinagari = _Nandinagari // Nandinagari is the set of Unicode characters in script Nandinagari. New_Tai_Lue = _New_Tai_Lue // New_Tai_Lue is the set of Unicode characters in script New_Tai_Lue. Newa = _Newa // Newa is the set of Unicode characters in script Newa. @@ -5694,6 +5944,7 @@ var ( Old_Sogdian = _Old_Sogdian // Old_Sogdian is the set of Unicode characters in script Old_Sogdian. Old_South_Arabian = _Old_South_Arabian // Old_South_Arabian is the set of Unicode characters in script Old_South_Arabian. Old_Turkic = _Old_Turkic // Old_Turkic is the set of Unicode characters in script Old_Turkic. + Old_Uyghur = _Old_Uyghur // Old_Uyghur is the set of Unicode characters in script Old_Uyghur. Oriya = _Oriya // Oriya is the set of Unicode characters in script Oriya. Osage = _Osage // Osage is the set of Unicode characters in script Osage. Osmanya = _Osmanya // Osmanya is the set of Unicode characters in script Osmanya. @@ -5725,6 +5976,7 @@ var ( Tai_Viet = _Tai_Viet // Tai_Viet is the set of Unicode characters in script Tai_Viet. Takri = _Takri // Takri is the set of Unicode characters in script Takri. Tamil = _Tamil // Tamil is the set of Unicode characters in script Tamil. + Tangsa = _Tangsa // Tangsa is the set of Unicode characters in script Tangsa. Tangut = _Tangut // Tangut is the set of Unicode characters in script Tangut. Telugu = _Telugu // Telugu is the set of Unicode characters in script Telugu. Thaana = _Thaana // Thaana is the set of Unicode characters in script Thaana. @@ -5732,8 +5984,10 @@ var ( Tibetan = _Tibetan // Tibetan is the set of Unicode characters in script Tibetan. Tifinagh = _Tifinagh // Tifinagh is the set of Unicode characters in script Tifinagh. Tirhuta = _Tirhuta // Tirhuta is the set of Unicode characters in script Tirhuta. + Toto = _Toto // Toto is the set of Unicode characters in script Toto. Ugaritic = _Ugaritic // Ugaritic is the set of Unicode characters in script Ugaritic. Vai = _Vai // Vai is the set of Unicode characters in script Vai. + Vithkuqi = _Vithkuqi // Vithkuqi is the set of Unicode characters in script Vithkuqi. Wancho = _Wancho // Wancho is the set of Unicode characters in script Wancho. Warang_Citi = _Warang_Citi // Warang_Citi is the set of Unicode characters in script Warang_Citi. Yezidi = _Yezidi // Yezidi is the set of Unicode characters in script Yezidi. @@ -5808,11 +6062,11 @@ var _Dash = &RangeTable{ {0x208b, 0x2212, 391}, {0x2e17, 0x2e1a, 3}, {0x2e3a, 0x2e3b, 1}, - {0x2e40, 0x301c, 476}, - {0x3030, 0x30a0, 112}, - {0xfe31, 0xfe32, 1}, - {0xfe58, 0xfe63, 11}, - {0xff0d, 0xff0d, 1}, + {0x2e40, 0x2e5d, 29}, + {0x301c, 0x3030, 20}, + {0x30a0, 0xfe31, 52625}, + {0xfe32, 0xfe58, 38}, + {0xfe63, 0xff0d, 170}, }, R32: []Range32{ {0x10ead, 0x10ead, 1}, @@ -5859,6 +6113,8 @@ var _Diacritic = &RangeTable{ {0x07a6, 0x07b0, 1}, {0x07eb, 0x07f5, 1}, {0x0818, 0x0819, 1}, + {0x0898, 0x089f, 1}, + {0x08c9, 0x08d2, 1}, {0x08e3, 0x08fe, 1}, {0x093c, 0x094d, 17}, {0x0951, 0x0954, 1}, @@ -5869,10 +6125,10 @@ var _Diacritic = &RangeTable{ {0x0afe, 0x0aff, 1}, {0x0b3c, 0x0b4d, 17}, {0x0b55, 0x0bcd, 120}, - {0x0c4d, 0x0cbc, 111}, - {0x0ccd, 0x0d3b, 110}, - {0x0d3c, 0x0d4d, 17}, - {0x0dca, 0x0e47, 125}, + {0x0c3c, 0x0c4d, 17}, + {0x0cbc, 0x0ccd, 17}, + {0x0d3b, 0x0d3c, 1}, + {0x0d4d, 0x0e47, 125}, {0x0e48, 0x0e4c, 1}, {0x0e4e, 0x0eba, 108}, {0x0ec8, 0x0ecc, 1}, @@ -5889,12 +6145,14 @@ var _Diacritic = &RangeTable{ {0x108f, 0x109a, 11}, {0x109b, 0x135d, 706}, {0x135e, 0x135f, 1}, + {0x1714, 0x1715, 1}, {0x17c9, 0x17d3, 1}, {0x17dd, 0x1939, 348}, {0x193a, 0x193b, 1}, {0x1a75, 0x1a7c, 1}, {0x1a7f, 0x1ab0, 49}, - {0x1ab1, 0x1abd, 1}, + {0x1ab1, 0x1abe, 1}, + {0x1ac1, 0x1acb, 1}, {0x1b34, 0x1b44, 16}, {0x1b6b, 0x1b73, 1}, {0x1baa, 0x1bab, 1}, @@ -5905,8 +6163,7 @@ var _Diacritic = &RangeTable{ {0x1cf7, 0x1cf9, 1}, {0x1d2c, 0x1d6a, 1}, {0x1dc4, 0x1dcf, 1}, - {0x1df5, 0x1df9, 1}, - {0x1dfd, 0x1dff, 1}, + {0x1df5, 0x1dff, 1}, {0x1fbd, 0x1fbf, 2}, {0x1fc0, 0x1fc1, 1}, {0x1fcd, 0x1fcf, 1}, @@ -5943,10 +6200,16 @@ var _Diacritic = &RangeTable{ {0xff9f, 0xffe3, 68}, }, R32: []Range32{ - {0x102e0, 0x10ae5, 2053}, - {0x10ae6, 0x10d22, 572}, - {0x10d23, 0x10d27, 1}, + {0x102e0, 0x10780, 1184}, + {0x10781, 0x10785, 1}, + {0x10787, 0x107b0, 1}, + {0x107b2, 0x107ba, 1}, + {0x10ae5, 0x10ae6, 1}, + {0x10d22, 0x10d27, 1}, + {0x10efd, 0x10eff, 1}, {0x10f46, 0x10f50, 1}, + {0x10f82, 0x10f85, 1}, + {0x11046, 0x11070, 42}, {0x110b9, 0x110ba, 1}, {0x11133, 0x11134, 1}, {0x11173, 0x111c0, 77}, @@ -5968,17 +6231,25 @@ var _Diacritic = &RangeTable{ {0x11a99, 0x11c3f, 422}, {0x11d42, 0x11d44, 2}, {0x11d45, 0x11d97, 82}, + {0x13447, 0x13455, 1}, {0x16af0, 0x16af4, 1}, {0x16b30, 0x16b36, 1}, {0x16f8f, 0x16f9f, 1}, {0x16ff0, 0x16ff1, 1}, + {0x1aff0, 0x1aff3, 1}, + {0x1aff5, 0x1affb, 1}, + {0x1affd, 0x1affe, 1}, + {0x1cf00, 0x1cf2d, 1}, + {0x1cf30, 0x1cf46, 1}, {0x1d167, 0x1d169, 1}, {0x1d16d, 0x1d172, 1}, {0x1d17b, 0x1d182, 1}, {0x1d185, 0x1d18b, 1}, {0x1d1aa, 0x1d1ad, 1}, + {0x1e030, 0x1e06d, 1}, {0x1e130, 0x1e136, 1}, - {0x1e2ec, 0x1e2ef, 1}, + {0x1e2ae, 0x1e2ec, 62}, + {0x1e2ed, 0x1e2ef, 1}, {0x1e8d0, 0x1e8d6, 1}, {0x1e944, 0x1e946, 1}, {0x1e948, 0x1e94a, 1}, @@ -6005,6 +6276,7 @@ var _Extender = &RangeTable{ {0xff70, 0xff70, 1}, }, R32: []Range32{ + {0x10781, 0x10782, 1}, {0x1135d, 0x115c6, 617}, {0x115c7, 0x115c8, 1}, {0x11a98, 0x16b42, 20650}, @@ -6058,7 +6330,7 @@ var _Ideographic = &RangeTable{ {0x3021, 0x3029, 1}, {0x3038, 0x303a, 1}, {0x3400, 0x4dbf, 1}, - {0x4e00, 0x9ffc, 1}, + {0x4e00, 0x9fff, 1}, {0xf900, 0xfa6d, 1}, {0xfa70, 0xfad9, 1}, }, @@ -6068,13 +6340,14 @@ var _Ideographic = &RangeTable{ {0x18800, 0x18cd5, 1}, {0x18d00, 0x18d08, 1}, {0x1b170, 0x1b2fb, 1}, - {0x20000, 0x2a6dd, 1}, - {0x2a700, 0x2b734, 1}, + {0x20000, 0x2a6df, 1}, + {0x2a700, 0x2b739, 1}, {0x2b740, 0x2b81d, 1}, {0x2b820, 0x2cea1, 1}, {0x2ceb0, 0x2ebe0, 1}, {0x2f800, 0x2fa1d, 1}, {0x30000, 0x3134a, 1}, + {0x31350, 0x323af, 1}, }, } @@ -6178,7 +6451,7 @@ var _Other_Alphabetic = &RangeTable{ {0x0bc6, 0x0bc8, 1}, {0x0bca, 0x0bcc, 1}, {0x0bd7, 0x0c00, 41}, - {0x0c01, 0x0c03, 1}, + {0x0c01, 0x0c04, 1}, {0x0c3e, 0x0c44, 1}, {0x0c46, 0x0c48, 1}, {0x0c4a, 0x0c4c, 1}, @@ -6190,7 +6463,8 @@ var _Other_Alphabetic = &RangeTable{ {0x0cca, 0x0ccc, 1}, {0x0cd5, 0x0cd6, 1}, {0x0ce2, 0x0ce3, 1}, - {0x0d00, 0x0d03, 1}, + {0x0cf3, 0x0d00, 13}, + {0x0d01, 0x0d03, 1}, {0x0d3e, 0x0d44, 1}, {0x0d46, 0x0d48, 1}, {0x0d4a, 0x0d4c, 1}, @@ -6207,7 +6481,7 @@ var _Other_Alphabetic = &RangeTable{ {0x0eb4, 0x0eb9, 1}, {0x0ebb, 0x0ebc, 1}, {0x0ecd, 0x0f71, 164}, - {0x0f72, 0x0f81, 1}, + {0x0f72, 0x0f83, 1}, {0x0f8d, 0x0f97, 1}, {0x0f99, 0x0fbc, 1}, {0x102b, 0x1036, 1}, @@ -6234,6 +6508,7 @@ var _Other_Alphabetic = &RangeTable{ {0x1a55, 0x1a5e, 1}, {0x1a61, 0x1a74, 1}, {0x1abf, 0x1ac0, 1}, + {0x1acc, 0x1ace, 1}, {0x1b00, 0x1b04, 1}, {0x1b35, 0x1b43, 1}, {0x1b80, 0x1b82, 1}, @@ -6278,9 +6553,11 @@ var _Other_Alphabetic = &RangeTable{ {0x10eab, 0x10eac, 1}, {0x11000, 0x11002, 1}, {0x11038, 0x11045, 1}, - {0x11082, 0x110b0, 46}, - {0x110b1, 0x110b8, 1}, - {0x11100, 0x11102, 1}, + {0x11073, 0x11074, 1}, + {0x11080, 0x11082, 1}, + {0x110b0, 0x110b8, 1}, + {0x110c2, 0x11100, 62}, + {0x11101, 0x11102, 1}, {0x11127, 0x11132, 1}, {0x11145, 0x11146, 1}, {0x11180, 0x11182, 1}, @@ -6288,7 +6565,8 @@ var _Other_Alphabetic = &RangeTable{ {0x111ce, 0x111cf, 1}, {0x1122c, 0x11234, 1}, {0x11237, 0x1123e, 7}, - {0x112df, 0x112e8, 1}, + {0x11241, 0x112df, 158}, + {0x112e0, 0x112e8, 1}, {0x11300, 0x11303, 1}, {0x1133e, 0x11344, 1}, {0x11347, 0x11348, 1}, @@ -6331,6 +6609,10 @@ var _Other_Alphabetic = &RangeTable{ {0x11d90, 0x11d91, 1}, {0x11d93, 0x11d96, 1}, {0x11ef3, 0x11ef6, 1}, + {0x11f00, 0x11f01, 1}, + {0x11f03, 0x11f34, 49}, + {0x11f35, 0x11f3a, 1}, + {0x11f3e, 0x11f40, 1}, {0x16f4f, 0x16f51, 2}, {0x16f52, 0x16f87, 1}, {0x16f8f, 0x16f92, 1}, @@ -6341,8 +6623,8 @@ var _Other_Alphabetic = &RangeTable{ {0x1e01b, 0x1e021, 1}, {0x1e023, 0x1e024, 1}, {0x1e026, 0x1e02a, 1}, - {0x1e947, 0x1f130, 2025}, - {0x1f131, 0x1f149, 1}, + {0x1e08f, 0x1e947, 2232}, + {0x1f130, 0x1f149, 1}, {0x1f150, 0x1f169, 1}, {0x1f170, 0x1f189, 1}, }, @@ -6410,7 +6692,8 @@ var _Other_Lowercase = &RangeTable{ {0x02c0, 0x02c1, 1}, {0x02e0, 0x02e4, 1}, {0x0345, 0x037a, 53}, - {0x1d2c, 0x1d6a, 1}, + {0x10fc, 0x1d2c, 3120}, + {0x1d2d, 0x1d6a, 1}, {0x1d78, 0x1d9b, 35}, {0x1d9c, 0x1dbf, 1}, {0x2071, 0x207f, 14}, @@ -6419,9 +6702,18 @@ var _Other_Lowercase = &RangeTable{ {0x24d0, 0x24e9, 1}, {0x2c7c, 0x2c7d, 1}, {0xa69c, 0xa69d, 1}, - {0xa770, 0xa7f8, 136}, - {0xa7f9, 0xab5c, 867}, - {0xab5d, 0xab5f, 1}, + {0xa770, 0xa7f2, 130}, + {0xa7f3, 0xa7f4, 1}, + {0xa7f8, 0xa7f9, 1}, + {0xab5c, 0xab5f, 1}, + {0xab69, 0xab69, 1}, + }, + R32: []Range32{ + {0x10780, 0x10783, 3}, + {0x10784, 0x10785, 1}, + {0x10787, 0x107b0, 1}, + {0x107b2, 0x107ba, 1}, + {0x1e030, 0x1e06d, 1}, }, LatinOffset: 1, } @@ -6607,6 +6899,7 @@ var _Prepended_Concatenation_Mark = &RangeTable{ R16: []Range16{ {0x0600, 0x0605, 1}, {0x06dd, 0x070f, 50}, + {0x0890, 0x0891, 1}, {0x08e2, 0x08e2, 1}, }, R32: []Range32{ @@ -6649,7 +6942,7 @@ var _Sentence_Terminal = &RangeTable{ R16: []Range16{ {0x0021, 0x002e, 13}, {0x003f, 0x0589, 1354}, - {0x061e, 0x061f, 1}, + {0x061d, 0x061f, 1}, {0x06d4, 0x0700, 44}, {0x0701, 0x0702, 1}, {0x07f9, 0x0837, 62}, @@ -6665,11 +6958,13 @@ var _Sentence_Terminal = &RangeTable{ {0x1aa9, 0x1aab, 1}, {0x1b5a, 0x1b5b, 1}, {0x1b5e, 0x1b5f, 1}, + {0x1b7d, 0x1b7e, 1}, {0x1c3b, 0x1c3c, 1}, {0x1c7e, 0x1c7f, 1}, {0x203c, 0x203d, 1}, {0x2047, 0x2049, 1}, {0x2e2e, 0x2e3c, 14}, + {0x2e53, 0x2e54, 1}, {0x3002, 0xa4ff, 29949}, {0xa60e, 0xa60f, 1}, {0xa6f3, 0xa6f7, 4}, @@ -6687,6 +6982,7 @@ var _Sentence_Terminal = &RangeTable{ R32: []Range32{ {0x10a56, 0x10a57, 1}, {0x10f55, 0x10f59, 1}, + {0x10f86, 0x10f89, 1}, {0x11047, 0x11048, 1}, {0x110be, 0x110c1, 1}, {0x11141, 0x11143, 1}, @@ -6705,6 +7001,7 @@ var _Sentence_Terminal = &RangeTable{ {0x11a9b, 0x11a9c, 1}, {0x11c41, 0x11c42, 1}, {0x11ef7, 0x11ef8, 1}, + {0x11f43, 0x11f44, 1}, {0x16a6e, 0x16a6f, 1}, {0x16af5, 0x16b37, 66}, {0x16b38, 0x16b44, 12}, @@ -6741,6 +7038,8 @@ var _Soft_Dotted = &RangeTable{ {0x1d62a, 0x1d62b, 1}, {0x1d65e, 0x1d65f, 1}, {0x1d692, 0x1d693, 1}, + {0x1df1a, 0x1e04c, 306}, + {0x1e04d, 0x1e068, 27}, }, LatinOffset: 1, } @@ -6753,7 +7052,7 @@ var _Terminal_Punctuation = &RangeTable{ {0x037e, 0x0387, 9}, {0x0589, 0x05c3, 58}, {0x060c, 0x061b, 15}, - {0x061e, 0x061f, 1}, + {0x061d, 0x061f, 1}, {0x06d4, 0x0700, 44}, {0x0701, 0x070a, 1}, {0x070c, 0x07f8, 236}, @@ -6776,6 +7075,7 @@ var _Terminal_Punctuation = &RangeTable{ {0x1aa8, 0x1aab, 1}, {0x1b5a, 0x1b5b, 1}, {0x1b5d, 0x1b5f, 1}, + {0x1b7d, 0x1b7e, 1}, {0x1c3b, 0x1c3f, 1}, {0x1c7e, 0x1c7f, 1}, {0x203c, 0x203d, 1}, @@ -6783,6 +7083,7 @@ var _Terminal_Punctuation = &RangeTable{ {0x2e2e, 0x2e3c, 14}, {0x2e41, 0x2e4c, 11}, {0x2e4e, 0x2e4f, 1}, + {0x2e53, 0x2e54, 1}, {0x3001, 0x3002, 1}, {0xa4fe, 0xa4ff, 1}, {0xa60d, 0xa60f, 1}, @@ -6809,6 +7110,7 @@ var _Terminal_Punctuation = &RangeTable{ {0x10b3a, 0x10b3f, 1}, {0x10b99, 0x10b9c, 1}, {0x10f55, 0x10f59, 1}, + {0x10f86, 0x10f89, 1}, {0x11047, 0x1104d, 1}, {0x110be, 0x110c1, 1}, {0x11141, 0x11143, 1}, @@ -6829,7 +7131,8 @@ var _Terminal_Punctuation = &RangeTable{ {0x11aa1, 0x11aa2, 1}, {0x11c41, 0x11c43, 1}, {0x11c71, 0x11ef7, 646}, - {0x11ef8, 0x12470, 1400}, + {0x11ef8, 0x11f43, 75}, + {0x11f44, 0x12470, 1324}, {0x12471, 0x12474, 1}, {0x16a6e, 0x16a6f, 1}, {0x16af5, 0x16b37, 66}, @@ -6844,7 +7147,7 @@ var _Terminal_Punctuation = &RangeTable{ var _Unified_Ideograph = &RangeTable{ R16: []Range16{ {0x3400, 0x4dbf, 1}, - {0x4e00, 0x9ffc, 1}, + {0x4e00, 0x9fff, 1}, {0xfa0e, 0xfa0f, 1}, {0xfa11, 0xfa13, 2}, {0xfa14, 0xfa1f, 11}, @@ -6853,19 +7156,21 @@ var _Unified_Ideograph = &RangeTable{ {0xfa28, 0xfa29, 1}, }, R32: []Range32{ - {0x20000, 0x2a6dd, 1}, - {0x2a700, 0x2b734, 1}, + {0x20000, 0x2a6df, 1}, + {0x2a700, 0x2b739, 1}, {0x2b740, 0x2b81d, 1}, {0x2b820, 0x2cea1, 1}, {0x2ceb0, 0x2ebe0, 1}, {0x30000, 0x3134a, 1}, + {0x31350, 0x323af, 1}, }, } var _Variation_Selector = &RangeTable{ R16: []Range16{ {0x180b, 0x180d, 1}, - {0xfe00, 0xfe0f, 1}, + {0x180f, 0xfe00, 58865}, + {0xfe01, 0xfe0f, 1}, }, R32: []Range32{ {0xe0100, 0xe01ef, 1}, @@ -7182,8 +7487,8 @@ var _CaseRanges = []CaseRange{ {0x2183, 0x2184, d{UpperLower, UpperLower, UpperLower}}, {0x24B6, 0x24CF, d{0, 26, 0}}, {0x24D0, 0x24E9, d{-26, 0, -26}}, - {0x2C00, 0x2C2E, d{0, 48, 0}}, - {0x2C30, 0x2C5E, d{-48, 0, -48}}, + {0x2C00, 0x2C2F, d{0, 48, 0}}, + {0x2C30, 0x2C5F, d{-48, 0, -48}}, {0x2C60, 0x2C61, d{UpperLower, UpperLower, UpperLower}}, {0x2C62, 0x2C62, d{0, -10743, 0}}, {0x2C63, 0x2C63, d{0, -3814, 0}}, @@ -7225,12 +7530,13 @@ var _CaseRanges = []CaseRange{ {0xA7B1, 0xA7B1, d{0, -42282, 0}}, {0xA7B2, 0xA7B2, d{0, -42261, 0}}, {0xA7B3, 0xA7B3, d{0, 928, 0}}, - {0xA7B4, 0xA7BF, d{UpperLower, UpperLower, UpperLower}}, - {0xA7C2, 0xA7C3, d{UpperLower, UpperLower, UpperLower}}, + {0xA7B4, 0xA7C3, d{UpperLower, UpperLower, UpperLower}}, {0xA7C4, 0xA7C4, d{0, -48, 0}}, {0xA7C5, 0xA7C5, d{0, -42307, 0}}, {0xA7C6, 0xA7C6, d{0, -35384, 0}}, {0xA7C7, 0xA7CA, d{UpperLower, UpperLower, UpperLower}}, + {0xA7D0, 0xA7D1, d{UpperLower, UpperLower, UpperLower}}, + {0xA7D6, 0xA7D9, d{UpperLower, UpperLower, UpperLower}}, {0xA7F5, 0xA7F6, d{UpperLower, UpperLower, UpperLower}}, {0xAB53, 0xAB53, d{-928, 0, -928}}, {0xAB70, 0xABBF, d{-38864, 0, -38864}}, @@ -7240,6 +7546,14 @@ var _CaseRanges = []CaseRange{ {0x10428, 0x1044F, d{-40, 0, -40}}, {0x104B0, 0x104D3, d{0, 40, 0}}, {0x104D8, 0x104FB, d{-40, 0, -40}}, + {0x10570, 0x1057A, d{0, 39, 0}}, + {0x1057C, 0x1058A, d{0, 39, 0}}, + {0x1058C, 0x10592, d{0, 39, 0}}, + {0x10594, 0x10595, d{0, 39, 0}}, + {0x10597, 0x105A1, d{-39, 0, -39}}, + {0x105A3, 0x105B1, d{-39, 0, -39}}, + {0x105B3, 0x105B9, d{-39, 0, -39}}, + {0x105BB, 0x105BC, d{-39, 0, -39}}, {0x10C80, 0x10CB2, d{0, 64, 0}}, {0x10CC0, 0x10CF2, d{-64, 0, -64}}, {0x118A0, 0x118BF, d{0, 32, 0}}, @@ -7378,7 +7692,7 @@ var properties = [MaxLatin1 + 1]uint8{ 0x7C: pS | pp, // '|' 0x7D: pP | pp, // '}' 0x7E: pS | pp, // '~' - 0x7F: pC, // '\u007f' + 0x7F: pC, // '\x7f' 0x80: pC, // '\u0080' 0x81: pC, // '\u0081' 0x82: pC, // '\u0082' @@ -7833,7 +8147,7 @@ var foldLl = &RangeTable{ {0x2126, 0x212a, 4}, {0x212b, 0x2132, 7}, {0x2183, 0x2c00, 2685}, - {0x2c01, 0x2c2e, 1}, + {0x2c01, 0x2c2f, 1}, {0x2c60, 0x2c62, 2}, {0x2c63, 0x2c64, 1}, {0x2c67, 0x2c6d, 2}, @@ -7854,15 +8168,20 @@ var foldLl = &RangeTable{ {0xa796, 0xa7aa, 2}, {0xa7ab, 0xa7ae, 1}, {0xa7b0, 0xa7b4, 1}, - {0xa7b6, 0xa7be, 2}, - {0xa7c2, 0xa7c4, 2}, + {0xa7b6, 0xa7c4, 2}, {0xa7c5, 0xa7c7, 1}, - {0xa7c9, 0xa7f5, 44}, - {0xff21, 0xff3a, 1}, + {0xa7c9, 0xa7d0, 7}, + {0xa7d6, 0xa7d8, 2}, + {0xa7f5, 0xff21, 22316}, + {0xff22, 0xff3a, 1}, }, R32: []Range32{ {0x10400, 0x10427, 1}, {0x104b0, 0x104d3, 1}, + {0x10570, 0x1057a, 1}, + {0x1057c, 0x1058a, 1}, + {0x1058c, 0x10592, 1}, + {0x10594, 0x10595, 1}, {0x10c80, 0x10cb2, 1}, {0x118a0, 0x118bf, 1}, {0x16e40, 0x16e5f, 1}, @@ -7971,7 +8290,7 @@ var foldLu = &RangeTable{ {0x1fd1, 0x1fe0, 15}, {0x1fe1, 0x1fe5, 4}, {0x214e, 0x2184, 54}, - {0x2c30, 0x2c5e, 1}, + {0x2c30, 0x2c5f, 1}, {0x2c61, 0x2c65, 4}, {0x2c66, 0x2c6c, 2}, {0x2c73, 0x2c76, 3}, @@ -7989,9 +8308,10 @@ var foldLu = &RangeTable{ {0xa78c, 0xa791, 5}, {0xa793, 0xa794, 1}, {0xa797, 0xa7a9, 2}, - {0xa7b5, 0xa7bf, 2}, - {0xa7c3, 0xa7c8, 5}, - {0xa7ca, 0xa7f6, 44}, + {0xa7b5, 0xa7c3, 2}, + {0xa7c8, 0xa7ca, 2}, + {0xa7d1, 0xa7d7, 6}, + {0xa7d9, 0xa7f6, 29}, {0xab53, 0xab70, 29}, {0xab71, 0xabbf, 1}, {0xff41, 0xff5a, 1}, @@ -7999,6 +8319,10 @@ var foldLu = &RangeTable{ R32: []Range32{ {0x10428, 0x1044f, 1}, {0x104d8, 0x104fb, 1}, + {0x10597, 0x105a1, 1}, + {0x105a3, 0x105b1, 1}, + {0x105b3, 0x105b9, 1}, + {0x105bb, 0x105bc, 1}, {0x10cc0, 0x10cf2, 1}, {0x118c0, 0x118df, 1}, {0x16e60, 0x16e7f, 1}, @@ -8050,7 +8374,7 @@ var foldInherited = &RangeTable{ }, } -// Range entries: 3499 16-bit, 1820 32-bit, 5319 total. -// Range bytes: 20994 16-bit, 21840 32-bit, 42834 total. +// Range entries: 3535 16-bit, 2031 32-bit, 5566 total. +// Range bytes: 21210 16-bit, 24372 32-bit, 45582 total. // Fold orbit bytes: 88 pairs, 352 bytes diff --git a/gnovm/stdlibs/unicode/utf8/example_test.gno b/gnovm/stdlibs/unicode/utf8/example_test.gno index 17d6e8d2114..fe434c94767 100644 --- a/gnovm/stdlibs/unicode/utf8/example_test.gno +++ b/gnovm/stdlibs/unicode/utf8/example_test.gno @@ -49,6 +49,7 @@ func ExampleDecodeLastRuneInString() { // l 1 // e 1 // H 1 + } func ExampleDecodeRune() { @@ -213,3 +214,13 @@ func ExampleValidString() { // true // false } + +func ExampleAppendRune() { + buf1 := utf8.AppendRune(nil, 0x10000) + buf2 := utf8.AppendRune([]byte("init"), 0x10000) + fmt.Println(string(buf1)) + fmt.Println(string(buf2)) + // Output: + // 𐀀 + // init𐀀 +} diff --git a/gnovm/stdlibs/unicode/utf8/utf8.gno b/gnovm/stdlibs/unicode/utf8/utf8.gno index 9c70281488d..71d6bf18d01 100644 --- a/gnovm/stdlibs/unicode/utf8/utf8.gno +++ b/gnovm/stdlibs/unicode/utf8/utf8.gno @@ -141,7 +141,7 @@ func FullRuneInString(s string) bool { } // DecodeRune unpacks the first UTF-8 encoding in p and returns the rune and -// its width in bytes. If p is empty it returns (RuneError, 0). Otherwise, if +// its width in bytes. If p is empty it returns ([RuneError], 0). Otherwise, if // the encoding is invalid, it returns (RuneError, 1). Both are impossible // results for correct, non-empty UTF-8. // @@ -188,8 +188,8 @@ func DecodeRune(p []byte) (r rune, size int) { return rune(p0&mask4)<<18 | rune(b1&maskx)<<12 | rune(b2&maskx)<<6 | rune(b3&maskx), 4 } -// DecodeRuneInString is like DecodeRune but its input is a string. If s is -// empty it returns (RuneError, 0). Otherwise, if the encoding is invalid, it +// DecodeRuneInString is like [DecodeRune] but its input is a string. If s is +// empty it returns ([RuneError], 0). Otherwise, if the encoding is invalid, it // returns (RuneError, 1). Both are impossible results for correct, non-empty // UTF-8. // @@ -237,7 +237,7 @@ func DecodeRuneInString(s string) (r rune, size int) { } // DecodeLastRune unpacks the last UTF-8 encoding in p and returns the rune and -// its width in bytes. If p is empty it returns (RuneError, 0). Otherwise, if +// its width in bytes. If p is empty it returns ([RuneError], 0). Otherwise, if // the encoding is invalid, it returns (RuneError, 1). Both are impossible // results for correct, non-empty UTF-8. // @@ -276,8 +276,8 @@ func DecodeLastRune(p []byte) (r rune, size int) { return r, size } -// DecodeLastRuneInString is like DecodeLastRune but its input is a string. If -// s is empty it returns (RuneError, 0). Otherwise, if the encoding is invalid, +// DecodeLastRuneInString is like [DecodeLastRune] but its input is a string. If +// s is empty it returns ([RuneError], 0). Otherwise, if the encoding is invalid, // it returns (RuneError, 1). Both are impossible results for correct, // non-empty UTF-8. // @@ -337,7 +337,7 @@ func RuneLen(r rune) int { } // EncodeRune writes into p (which must be large enough) the UTF-8 encoding of the rune. -// If the rune is out of range, it writes the encoding of RuneError. +// If the rune is out of range, it writes the encoding of [RuneError]. // It returns the number of bytes written. func EncodeRune(p []byte, r rune) int { // Negative values are erroneous. Making it unsigned addresses the problem. @@ -352,13 +352,7 @@ func EncodeRune(p []byte, r rune) int { return 2 case i > MaxRune, surrogateMin <= i && i <= surrogateMax: r = RuneError - // XXX fallthrough not implemented - // fallthrough - _ = p[2] // eliminate bounds checks - p[0] = t3 | byte(r>>12) - p[1] = tx | byte(r>>6)&maskx - p[2] = tx | byte(r)&maskx - return 3 + fallthrough case i <= rune3Max: _ = p[2] // eliminate bounds checks p[0] = t3 | byte(r>>12) @@ -375,6 +369,32 @@ func EncodeRune(p []byte, r rune) int { } } +// AppendRune appends the UTF-8 encoding of r to the end of p and +// returns the extended buffer. If the rune is out of range, +// it appends the encoding of [RuneError]. +func AppendRune(p []byte, r rune) []byte { + // This function is inlineable for fast handling of ASCII. + if uint32(r) <= rune1Max { + return append(p, byte(r)) + } + return appendRuneNonASCII(p, r) +} + +func appendRuneNonASCII(p []byte, r rune) []byte { + // Negative values are erroneous. Making it unsigned addresses the problem. + switch i := uint32(r); { + case i <= rune2Max: + return append(p, t2|byte(r>>6), tx|byte(r)&maskx) + case i > MaxRune, surrogateMin <= i && i <= surrogateMax: + r = RuneError + fallthrough + case i <= rune3Max: + return append(p, t3|byte(r>>12), tx|byte(r>>6)&maskx, tx|byte(r)&maskx) + default: + return append(p, t4|byte(r>>18), tx|byte(r>>12)&maskx, tx|byte(r>>6)&maskx, tx|byte(r)&maskx) + } +} + // RuneCount returns the number of runes in p. Erroneous and short // encodings are treated as single runes of width 1 byte. func RuneCount(p []byte) int { @@ -413,7 +433,7 @@ func RuneCount(p []byte) int { return n } -// RuneCountInString is like RuneCount but its input is a string. +// RuneCountInString is like [RuneCount] but its input is a string. func RuneCountInString(s string) (n int) { ns := len(s) for i := 0; i < ns; n++ { @@ -455,6 +475,11 @@ func RuneStart(b byte) bool { return b&0xC0 != 0x80 } // Valid reports whether p consists entirely of valid UTF-8-encoded runes. func Valid(p []byte) bool { + // This optimization avoids the need to recompute the capacity + // when generating code for p[8:], bringing it to parity with + // ValidString, which was 20% faster on long ASCII strings. + p = p[:len(p):len(p)] + // Fast path. Check for and skip 8 bytes of ASCII characters per iteration. for len(p) >= 8 { // Combining two 32 bit loads allows the same code to be used diff --git a/gnovm/stdlibs/unicode/utf8/utf8_test.gno b/gnovm/stdlibs/unicode/utf8/utf8_test.gno index 7fecb778975..0384b7a88e9 100644 --- a/gnovm/stdlibs/unicode/utf8/utf8_test.gno +++ b/gnovm/stdlibs/unicode/utf8/utf8_test.gno @@ -127,6 +127,17 @@ func TestEncodeRune(t *testing.T) { } } +func TestAppendRune(t *testing.T) { + for _, m := range utf8map { + if buf := utf8.AppendRune(nil, m.r); string(buf) != m.str { + t.Errorf("AppendRune(nil, %#04x) = %s, want %s", m.r, buf, m.str) + } + if buf := utf8.AppendRune([]byte("init"), m.r); string(buf) != "init"+m.str { + t.Errorf("AppendRune(init, %#04x) = %s, want %s", m.r, buf, "init"+m.str) + } + } +} + func TestDecodeRune(t *testing.T) { for _, m := range utf8map { b := []byte(m.str) diff --git a/gnovm/tests/file.go b/gnovm/tests/file.go index f6bd789f1bf..98e54114af9 100644 --- a/gnovm/tests/file.go +++ b/gnovm/tests/file.go @@ -2,6 +2,7 @@ package tests import ( "bytes" + "encoding/json" "fmt" "go/ast" "go/parser" @@ -14,6 +15,7 @@ import ( "strings" "github.com/gnolang/gno/gno.land/pkg/gnoland/ugnot" + "github.com/gnolang/gno/gnovm" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" "github.com/gnolang/gno/gnovm/stdlibs" teststd "github.com/gnolang/gno/gnovm/tests/stdlibs/std" @@ -54,7 +56,7 @@ func TestContext(pkgPath string, send std.Coins) *teststd.TestExecContext { pkgAddr := gno.DerivePkgAddr(pkgPath) // the addr of the pkgPath called. caller := gno.DerivePkgAddr("user1.gno") - pkgCoins := std.MustParseCoins(ugnot.ValueString(200000000)).Add(send) // >= send. + pkgCoins := std.MustParseCoins(ugnot.ValueString(200_000_000)).Add(send) // >= send. banker := newTestBanker(pkgAddr.Bech32(), pkgCoins) ctx := stdlibs.ExecContext{ ChainID: "dev", @@ -74,6 +76,19 @@ func TestContext(pkgPath string, send std.Coins) *teststd.TestExecContext { } } +// CleanupMachine can be called during two tests while reusing the same Machine instance. +func CleanupMachine(m *gno.Machine) { + prevCtx := m.Context.(*teststd.TestExecContext) + prevSend := prevCtx.OrigSend + + newCtx := TestContext("", prevCtx.OrigSend) + pkgCoins := std.MustParseCoins(ugnot.ValueString(200_000_000)).Add(prevSend) // >= send. + banker := newTestBanker(prevCtx.OrigPkgAddr, pkgCoins) + newCtx.OrigPkgAddr = prevCtx.OrigPkgAddr + newCtx.Banker = banker + m.Context = newCtx +} + type runFileTestOptions struct { nativeLibs bool logger loggerFunc @@ -110,7 +125,7 @@ func RunFileTest(rootDir string, path string, opts ...RunFileTestOption) error { opt(&f) } - directives, pkgPath, resWanted, errWanted, rops, stacktraceWanted, maxAlloc, send := wantedFromComment(path) + directives, pkgPath, resWanted, errWanted, rops, eventsWanted, stacktraceWanted, maxAlloc, send, preWanted := wantedFromComment(path) if pkgPath == "" { pkgPath = "main" } @@ -186,10 +201,10 @@ func RunFileTest(rootDir string, path string, opts ...RunFileTestOption) error { store.SetStrictGo2GnoMapping(true) // in gno.land, natives must be registered. gno.DisableDebug() // until main call. // save package using realm crawl procedure. - memPkg := &std.MemPackage{ + memPkg := &gnovm.MemPackage{ Name: string(pkgName), Path: pkgPath, - Files: []*std.MemFile{ + Files: []*gnovm.MemFile{ { Name: "main.gno", // dontcare Body: string(bz), @@ -347,6 +362,45 @@ func RunFileTest(rootDir string, path string, opts ...RunFileTestOption) error { } } } + case "Events": + // panic if got unexpected error + + if pnc != nil { + if tv, ok := pnc.(*gno.TypedValue); ok { + panic(fmt.Sprintf("fail on %s: got unexpected error: %s", path, tv.Sprint(m))) + } else { // happens on 'unknown import path ...' + panic(fmt.Sprintf("fail on %s: got unexpected error: %v", path, pnc)) + } + } + // check result + events := m.Context.(*teststd.TestExecContext).EventLogger.Events() + evtjson, err := json.MarshalIndent(events, "", " ") + if err != nil { + panic(err) + } + evtstr := trimTrailingSpaces(string(evtjson)) + if evtstr != eventsWanted { + if f.syncWanted { + // write output to file. + replaceWantedInPlace(path, "Events", evtstr) + } else { + // panic so tests immediately fail (for now). + if eventsWanted == "" { + panic(fmt.Sprintf("fail on %s: got unexpected events: %s", path, evtstr)) + } else { + diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{ + A: difflib.SplitLines(eventsWanted), + B: difflib.SplitLines(evtstr), + FromFile: "Expected", + FromDate: "", + ToFile: "Actual", + ToDate: "", + Context: 1, + }) + panic(fmt.Sprintf("fail on %s: diff:\n%s\n", path, diff)) + } + } + } case "Realm": // panic if got unexpected error if pnc != nil { @@ -377,6 +431,28 @@ func RunFileTest(rootDir string, path string, opts ...RunFileTestOption) error { } } } + case "Preprocessed": + // check preprocessed AST. + pn := store.GetBlockNode(gno.PackageNodeLocation(pkgPath)) + pre := pn.(*gno.PackageNode).FileSet.Files[0].String() + if pre != preWanted { + if f.syncWanted { + // write error to file + replaceWantedInPlace(path, "Preprocessed", pre) + } else { + // panic so tests immediately fail (for now). + diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{ + A: difflib.SplitLines(preWanted), + B: difflib.SplitLines(pre), + FromFile: "Expected", + FromDate: "", + ToFile: "Actual", + ToDate: "", + Context: 1, + }) + panic(fmt.Sprintf("fail on %s: diff:\n%s\n", path, diff)) + } + } case "Stacktrace": if stacktraceWanted != "" { var stacktrace string @@ -388,22 +464,27 @@ func RunFileTest(rootDir string, path string, opts ...RunFileTestOption) error { stacktrace = m.Stacktrace().String() } - if !strings.Contains(stacktrace, stacktraceWanted) { - diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{ - A: difflib.SplitLines(stacktraceWanted), - B: difflib.SplitLines(stacktrace), - FromFile: "Expected", - FromDate: "", - ToFile: "Actual", - ToDate: "", - Context: 1, - }) - panic(fmt.Sprintf("fail on %s: diff:\n%s\n", path, diff)) + if f.syncWanted { + // write stacktrace to file + replaceWantedInPlace(path, "Stacktrace", stacktrace) + } else { + if !strings.Contains(stacktrace, stacktraceWanted) { + diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{ + A: difflib.SplitLines(stacktraceWanted), + B: difflib.SplitLines(stacktrace), + FromFile: "Expected", + FromDate: "", + ToFile: "Actual", + ToDate: "", + Context: 1, + }) + panic(fmt.Sprintf("fail on %s: diff:\n%s\n", path, diff)) + } } } checkMachineIsEmpty = false default: - checkMachineIsEmpty = false + return nil } } } @@ -421,7 +502,7 @@ func RunFileTest(rootDir string, path string, opts ...RunFileTestOption) error { return nil } -func wantedFromComment(p string) (directives []string, pkgPath, res, err, rops, stacktrace string, maxAlloc int64, send std.Coins) { +func wantedFromComment(p string) (directives []string, pkgPath, res, err, rops, events, stacktrace string, maxAlloc int64, send std.Coins, pre string) { fset := token.NewFileSet() f, err2 := parser.ParseFile(fset, p, nil, parser.ParseComments) if err2 != nil { @@ -463,6 +544,14 @@ func wantedFromComment(p string) (directives []string, pkgPath, res, err, rops, rops = strings.TrimPrefix(text, "Realm:\n") rops = strings.TrimSpace(rops) directives = append(directives, "Realm") + } else if strings.HasPrefix(text, "Events:\n") { + events = strings.TrimPrefix(text, "Events:\n") + events = strings.TrimSpace(events) + directives = append(directives, "Events") + } else if strings.HasPrefix(text, "Preprocessed:\n") { + pre = strings.TrimPrefix(text, "Preprocessed:\n") + pre = strings.TrimSpace(pre) + directives = append(directives, "Preprocessed") } else if strings.HasPrefix(text, "Stacktrace:\n") { stacktrace = strings.TrimPrefix(text, "Stacktrace:\n") stacktrace = strings.TrimSpace(stacktrace) @@ -597,12 +686,12 @@ func (tb *testBanker) TotalCoin(denom string) int64 { func (tb *testBanker) IssueCoin(addr crypto.Bech32Address, denom string, amt int64) { coins, _ := tb.coinTable[addr] - sum := coins.Add(std.Coins{{denom, amt}}) + sum := coins.Add(std.Coins{{Denom: denom, Amount: amt}}) tb.coinTable[addr] = sum } func (tb *testBanker) RemoveCoin(addr crypto.Bech32Address, denom string, amt int64) { coins, _ := tb.coinTable[addr] - rest := coins.Sub(std.Coins{{denom, amt}}) + rest := coins.Sub(std.Coins{{Denom: denom, Amount: amt}}) tb.coinTable[addr] = rest } diff --git a/gnovm/tests/files/assign29_native.gno b/gnovm/tests/files/assign29_native.gno new file mode 100644 index 00000000000..a404f703fc1 --- /dev/null +++ b/gnovm/tests/files/assign29_native.gno @@ -0,0 +1,14 @@ +package main + +import ( + "time" +) + +func main() { + time.Now = func() time.Time { + return time.Time{} + } +} + +// Error: +// main/files/assign29_native.gno:8:2: cannot assign to time.Now (neither addressable nor a map index expression) diff --git a/gnovm/tests/files/assign_unnamed_type/more/realm_compositelit_filetest.gno b/gnovm/tests/files/assign_unnamed_type/more/realm_compositelit_filetest.gno index 5bdd878c146..d61170334d7 100644 --- a/gnovm/tests/files/assign_unnamed_type/more/realm_compositelit_filetest.gno +++ b/gnovm/tests/files/assign_unnamed_type/more/realm_compositelit_filetest.gno @@ -1,10 +1,6 @@ // PKGPATH: gno.land/r/test package test -import ( - "fmt" -) - type ( word uint nat []word @@ -226,7 +222,7 @@ func main() { // "Location": { // "Column": "1", // "File": "main.gno", -// "Line": "20", +// "Line": "16", // "PkgPath": "gno.land/r/test" // } // }, diff --git a/gnovm/tests/files/break0.gno b/gnovm/tests/files/break0.gno new file mode 100644 index 00000000000..17d68dc1dbf --- /dev/null +++ b/gnovm/tests/files/break0.gno @@ -0,0 +1,8 @@ +package main + +func main() { + break +} + +// Error: +// main/files/break0.gno:4:2: cannot break with no parent loop or switch diff --git a/gnovm/tests/files/cont3.gno b/gnovm/tests/files/cont3.gno new file mode 100644 index 00000000000..8a305d4ceb2 --- /dev/null +++ b/gnovm/tests/files/cont3.gno @@ -0,0 +1,8 @@ +package main + +func main() { + continue +} + +// Error: +// main/files/cont3.gno:4:2: cannot continue with no parent loop diff --git a/gnovm/tests/files/for20.gno b/gnovm/tests/files/for20.gno new file mode 100644 index 00000000000..ad9f1f124d0 --- /dev/null +++ b/gnovm/tests/files/for20.gno @@ -0,0 +1,15 @@ +package main + +func main() { + // Ensure `break` works also when we have a label for the for loop. + +loop: + for { + break + } + + println("hey") +} + +// Output: +// hey diff --git a/gnovm/tests/files/heap_alloc_defer.gno b/gnovm/tests/files/heap_alloc_defer.gno new file mode 100644 index 00000000000..788d9326695 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_defer.gno @@ -0,0 +1,37 @@ +package main + +type Foo struct { + num int + f func() +} + +func main() { + s := []Foo{ + { + num: 1, + f: func() { println("hello") }, + }, + { + num: 2, + f: func() { println("hola") }, + }, + } + + // tt is heap defined every iteration, + // different with for loopvar spec. + for _, tt := range s { + f := func() { + println(tt.num) + } + f() + defer func() { + tt.f() + }() + } +} + +// Output: +// 1 +// 2 +// hola +// hola diff --git a/gnovm/tests/files/heap_alloc_defer2.gno b/gnovm/tests/files/heap_alloc_defer2.gno new file mode 100644 index 00000000000..dc865b1a430 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_defer2.gno @@ -0,0 +1,28 @@ +package main + +type rand struct{} + +func (r *rand) Seed() { + println("seed...") +} + +func fromSeed() *rand { + return &rand{} +} + +func genResult(s0 string, x int) (int, bool) { + z := 0 + println(z) + r := fromSeed() + defer func() { r.Seed() }() + + return -1, true +} + +func main() { + genResult("hey", 0) +} + +// Output: +// 0 +// seed... diff --git a/gnovm/tests/files/heap_alloc_forloop1.gno b/gnovm/tests/files/heap_alloc_forloop1.gno new file mode 100644 index 00000000000..c166bf8e167 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop1.gno @@ -0,0 +1,31 @@ +package main + +import "fmt" + +var s1 []*int + +func forLoopRef() { + defer func() { + for i, e := range s1 { + fmt.Printf("s1[%d] is: %d\n", i, *e) + } + }() + + for i := 0; i < 3; i++ { + s1 = append(s1, &i) + } +} + +func main() { + forLoopRef() +} + +// go 1.22 loop var is not supported for now. + +// Preprocessed: +// file{ package main; import fmt fmt; var s1 []*((const-type int)); func forLoopRef() { defer func func(){ for i, e := range s1 { fmt.Printf((const ("s1[%d] is: %d\n" string)), (const-type gonative{interface {}})(i), (const-type gonative{interface {}})(*(e))) } }(); for i := (const (0 int)); i<~VPBlock(1,0)> < (const (3 int)); i<~VPBlock(1,0)>++ { s1 = (const (append func(x []*int,args ...*int)(res []*int)))(s1, &(i<~VPBlock(1,0)>)) } }; func main() { forLoopRef() } } + +// Output: +// s1[0] is: 3 +// s1[1] is: 3 +// s1[2] is: 3 diff --git a/gnovm/tests/files/heap_alloc_forloop1a.gno b/gnovm/tests/files/heap_alloc_forloop1a.gno new file mode 100644 index 00000000000..6d0895902bd --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop1a.gno @@ -0,0 +1,39 @@ +package main + +import "fmt" + +type Int int + +var s1 []*Int + +func inc2(j *Int) { + *j = *j + 2 // Just as an example, increment j by 2. +} + +func forLoopRef() { + defer func() { + for i, e := range s1 { + fmt.Printf("s1[%d] is: %d\n", i, *e) + } + }() + + for i := Int(0); i < 10; inc2(&i) { + s1 = append(s1, &i) + } +} + +func main() { + forLoopRef() +} + +// go 1.22 loop var is not supported for now. + +// Preprocessed: +// file{ package main; import fmt fmt; type Int (const-type main.Int); var s1 []*(Int); func inc2(j *(Int)) { *(j) = *(j) + (const (2 main.Int)) }; func forLoopRef() { defer func func(){ for i, e := range s1 { fmt.Printf((const ("s1[%d] is: %d\n" string)), (const-type gonative{interface {}})(i), (const-type gonative{interface {}})(*(e))) } }(); for i := (const (0 main.Int)); i<~VPBlock(1,0)> < (const (10 main.Int)); inc2(&(i<~VPBlock(1,0)>)) { s1 = (const (append func(x []*main.Int,args ...*main.Int)(res []*main.Int)))(s1, &(i<~VPBlock(1,0)>)) } }; func main() { forLoopRef() } } + +// Output: +// s1[0] is: 10 +// s1[1] is: 10 +// s1[2] is: 10 +// s1[3] is: 10 +// s1[4] is: 10 diff --git a/gnovm/tests/files/heap_alloc_forloop1b.gno b/gnovm/tests/files/heap_alloc_forloop1b.gno new file mode 100644 index 00000000000..35b167e4168 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop1b.gno @@ -0,0 +1,37 @@ +package main + +import "fmt" + +var s1 []*int + +func forLoopRef() { + defer func() { + for i, e := range s1 { + fmt.Printf("s1[%d] is: %d\n", i, *e) + } + }() + + for i := 0; i < 3; i++ { + r := i + r, ok := 0, true + println(ok, r) + s1 = append(s1, &i) + } +} + +func main() { + forLoopRef() +} + +// go 1.22 loop var is not supported for now. + +// Preprocessed: +// file{ package main; import fmt fmt; var s1 []*((const-type int)); func forLoopRef() { defer func func(){ for i, e := range s1 { fmt.Printf((const ("s1[%d] is: %d\n" string)), (const-type gonative{interface {}})(i), (const-type gonative{interface {}})(*(e))) } }(); for i := (const (0 int)); i<~VPBlock(1,0)> < (const (3 int)); i<~VPBlock(1,0)>++ { r := i<~VPBlock(1,0)>; r, ok := (const (0 int)), (const (true bool)); (const (println func(xs ...interface{})()))(ok, r); s1 = (const (append func(x []*int,args ...*int)(res []*int)))(s1, &(i<~VPBlock(1,0)>)) } }; func main() { forLoopRef() } } + +// Output: +// true 0 +// true 0 +// true 0 +// s1[0] is: 3 +// s1[1] is: 3 +// s1[2] is: 3 diff --git a/gnovm/tests/files/heap_alloc_forloop2.gno b/gnovm/tests/files/heap_alloc_forloop2.gno new file mode 100644 index 00000000000..aa7f6e44dd3 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop2.gno @@ -0,0 +1,33 @@ +package main + +import "fmt" + +var s1 []*int + +func forLoopRef() { + defer func() { + for i, e := range s1 { + fmt.Printf("s1[%d] is: %d\n", i, *e) + } + }() + + for i := 0; i < 3; i++ { + z := i + 1 + s1 = append(s1, &z) + } +} + +func main() { + forLoopRef() +} + +// This does make 'z' NameExprTypeHeapDefine. +// You can tell by the preprocess printout of z and z<~...>. + +// Preprocessed: +// file{ package main; import fmt fmt; var s1 []*((const-type int)); func forLoopRef() { defer func func(){ for i, e := range s1 { fmt.Printf((const ("s1[%d] is: %d\n" string)), (const-type gonative{interface {}})(i), (const-type gonative{interface {}})(*(e))) } }(); for i := (const (0 int)); i < (const (3 int)); i++ { z := i + (const (1 int)); s1 = (const (append func(x []*int,args ...*int)(res []*int)))(s1, &(z<~VPBlock(1,1)>)) } }; func main() { forLoopRef() } } + +// Output: +// s1[0] is: 1 +// s1[1] is: 2 +// s1[2] is: 3 diff --git a/gnovm/tests/files/heap_alloc_forloop2a.gno b/gnovm/tests/files/heap_alloc_forloop2a.gno new file mode 100644 index 00000000000..be4b089ccad --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop2a.gno @@ -0,0 +1,34 @@ +package main + +import "fmt" + +var s1 []*int + +func forLoopRef() { + defer func() { + for i, e := range s1 { + fmt.Printf("s1[%d] is: %d\n", i, *e) + } + }() + + for i := 0; i < 3; i++ { + z := i + s1 = append(s1, &z) + z++ + } +} + +func main() { + forLoopRef() +} + +// This does make 'z' NameExprTypeHeapDefine. +// You can tell by the preprocess printout of z and z<~...>. + +// Preprocessed: +// file{ package main; import fmt fmt; var s1 []*((const-type int)); func forLoopRef() { defer func func(){ for i, e := range s1 { fmt.Printf((const ("s1[%d] is: %d\n" string)), (const-type gonative{interface {}})(i), (const-type gonative{interface {}})(*(e))) } }(); for i := (const (0 int)); i < (const (3 int)); i++ { z := i; s1 = (const (append func(x []*int,args ...*int)(res []*int)))(s1, &(z<~VPBlock(1,1)>)); z<~VPBlock(1,1)>++ } }; func main() { forLoopRef() } } + +// Output: +// s1[0] is: 1 +// s1[1] is: 2 +// s1[2] is: 3 diff --git a/gnovm/tests/files/heap_alloc_forloop3.gno b/gnovm/tests/files/heap_alloc_forloop3.gno new file mode 100644 index 00000000000..91c9b627120 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop3.gno @@ -0,0 +1,33 @@ +package main + +type f func() + +var fs []f + +func forLoopClosure() { + defer func() { + for _, f := range fs { + f() + } + }() + + for i := 0; i < 3; i++ { + z := i + fs = append(fs, func() { println(z) }) + } +} + +func main() { + forLoopClosure() +} + +// This does make 'z' NameExprTypeHeapDefine. +// You can tell by the preprocess printout of z and z<()~...>. + +// Preprocessed: +// file{ package main; type f (const-type main.f); var fs []f; func forLoopClosure() { defer func func(){ for _, f := range fs { f() } }(); for i := (const (0 int)); i < (const (3 int)); i++ { z := i; fs = (const (append func(x []main.f,args ...main.f)(res []main.f)))(fs, (const-type main.f)(func func(){ (const (println func(xs ...interface{})()))(z<~VPBlock(1,0)>) }>)) } }; func main() { forLoopClosure() } } + +// Output: +// 0 +// 1 +// 2 diff --git a/gnovm/tests/files/heap_alloc_forloop3a.gno b/gnovm/tests/files/heap_alloc_forloop3a.gno new file mode 100644 index 00000000000..fd361e7134e --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop3a.gno @@ -0,0 +1,38 @@ +package main + +type f func() + +var fs []f + +func forLoopClosure() { + defer func() { + for _, f := range fs { + f() + } + }() + + for i := 0; i < 3; i++ { + x := i + println(x) + z := i + fs = append(fs, func() { println(z) }) + } +} + +func main() { + forLoopClosure() +} + +// This does make 'z' NameExprTypeHeapDefine. +// You can tell by the preprocess printout of z and z<()~...>. + +// Preprocessed: +// file{ package main; type f (const-type main.f); var fs []f; func forLoopClosure() { defer func func(){ for _, f := range fs { f() } }(); for i := (const (0 int)); i < (const (3 int)); i++ { x := i; (const (println func(xs ...interface{})()))(x); z := i; fs = (const (append func(x []main.f,args ...main.f)(res []main.f)))(fs, (const-type main.f)(func func(){ (const (println func(xs ...interface{})()))(z<~VPBlock(1,0)>) }>)) } }; func main() { forLoopClosure() } } + +// Output: +// 0 +// 1 +// 2 +// 0 +// 1 +// 2 diff --git a/gnovm/tests/files/heap_alloc_forloop4.gno b/gnovm/tests/files/heap_alloc_forloop4.gno new file mode 100644 index 00000000000..3cddb1a60fe --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop4.gno @@ -0,0 +1,31 @@ +package main + +type f func() + +var fs []f + +func forLoopClosure() { + defer func() { + for _, f := range fs { + f() + } + }() + + for i := 0; i < 3; i++ { + fs = append(fs, func() { println(i) }) + } +} + +func main() { + forLoopClosure() +} + +// go 1.22 loop var is not supported for now. + +// Preprocessed: +// file{ package main; type f (const-type main.f); var fs []f; func forLoopClosure() { defer func func(){ for _, f := range fs { f() } }(); for i := (const (0 int)); i<~VPBlock(1,0)> < (const (3 int)); i<~VPBlock(1,0)>++ { fs = (const (append func(x []main.f,args ...main.f)(res []main.f)))(fs, (const-type main.f)(func func(){ (const (println func(xs ...interface{})()))(i<~VPBlock(1,0)>) }>)) } }; func main() { forLoopClosure() } } + +// Output: +// 3 +// 3 +// 3 diff --git a/gnovm/tests/files/heap_alloc_forloop5.gno b/gnovm/tests/files/heap_alloc_forloop5.gno new file mode 100644 index 00000000000..4f563ec866b --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop5.gno @@ -0,0 +1,32 @@ +package main + +type f func() + +var fs []f + +func forLoopClosure() { + defer func() { + for _, f := range fs { + f() + } + }() + + for i := 0; i < 3; i++ { + fs = append(fs, func() { + z := i + println(z) + }) + } +} + +func main() { + forLoopClosure() +} + +// Preprocessed: +// file{ package main; type f (const-type main.f); var fs []f; func forLoopClosure() { defer func func(){ for _, f := range fs { f() } }(); for i := (const (0 int)); i<~VPBlock(1,0)> < (const (3 int)); i<~VPBlock(1,0)>++ { fs = (const (append func(x []main.f,args ...main.f)(res []main.f)))(fs, (const-type main.f)(func func(){ z := i<~VPBlock(1,1)>; (const (println func(xs ...interface{})()))(z) }>)) } }; func main() { forLoopClosure() } } + +// Output: +// 3 +// 3 +// 3 diff --git a/gnovm/tests/files/heap_alloc_forloop5a.gno b/gnovm/tests/files/heap_alloc_forloop5a.gno new file mode 100644 index 00000000000..039be2b86a8 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop5a.gno @@ -0,0 +1,33 @@ +package main + +type f func() + +var fs []f + +func forLoopClosure() { + defer func() { + for _, f := range fs { + f() + } + }() + + for i := 0; i < 3; i++ { + x := i + fs = append(fs, func() { + z := x + println(z) + }) + } +} + +func main() { + forLoopClosure() +} + +// Preprocessed: +// file{ package main; type f (const-type main.f); var fs []f; func forLoopClosure() { defer func func(){ for _, f := range fs { f() } }(); for i := (const (0 int)); i < (const (3 int)); i++ { x := i; fs = (const (append func(x []main.f,args ...main.f)(res []main.f)))(fs, (const-type main.f)(func func(){ z := x<~VPBlock(1,1)>; (const (println func(xs ...interface{})()))(z) }>)) } }; func main() { forLoopClosure() } } + +// Output: +// 0 +// 1 +// 2 diff --git a/gnovm/tests/files/heap_alloc_forloop6.gno b/gnovm/tests/files/heap_alloc_forloop6.gno new file mode 100644 index 00000000000..6cfa8a65fc8 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop6.gno @@ -0,0 +1,25 @@ +package main + +func main() { + var fns []func() int + + for i := 0; i < 3; i++ { + z := i + f := func() int { + return z + } + fns = append(fns, f) + } + + for _, fn := range fns { + println(fn()) + } +} + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); for i := (const (0 int)); i < (const (3 int)); i++ { z := i; f := func func() (const-type int){ return z<~VPBlock(1,1)> }>; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Output: +// 0 +// 1 +// 2 diff --git a/gnovm/tests/files/heap_alloc_forloop6a.gno b/gnovm/tests/files/heap_alloc_forloop6a.gno new file mode 100644 index 00000000000..6365fcd8c62 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop6a.gno @@ -0,0 +1,26 @@ +package main + +func main() { + var fns []func() int + for i := 0; i < 5; i++ { + f := func() int { + return i + } + fns = append(fns, f) + } + for _, fn := range fns { + println(fn()) + } +} + +// go 1.22 loop var is not supported for now. + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); for i := (const (0 int)); i<~VPBlock(1,0)> < (const (5 int)); i<~VPBlock(1,0)>++ { f := func func() (const-type int){ return i<~VPBlock(1,1)> }>; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Output: +// 5 +// 5 +// 5 +// 5 +// 5 diff --git a/gnovm/tests/files/heap_alloc_forloop6b.gno b/gnovm/tests/files/heap_alloc_forloop6b.gno new file mode 100644 index 00000000000..73d9e5cd6a7 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop6b.gno @@ -0,0 +1,25 @@ +package main + +func main() { + var fns []func() int + for i := 0; i < 2; i++ { + x := i + y := 0 + f := func() int { + x += y + x += 1 + return x + } + fns = append(fns, f) + } + for _, fn := range fns { + println(fn()) + } +} + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); for i := (const (0 int)); i < (const (2 int)); i++ { x := i; y := (const (0 int)); f := func func() (const-type int){ x<~VPBlock(1,1)> += y<~VPBlock(1,2)>; x<~VPBlock(1,1)> += (const (1 int)); return x<~VPBlock(1,1)> }, y<()~VPBlock(1,2)>>; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Output: +// 1 +// 2 diff --git a/gnovm/tests/files/heap_alloc_forloop6c.gno b/gnovm/tests/files/heap_alloc_forloop6c.gno new file mode 100644 index 00000000000..f8d2d410f6c --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop6c.gno @@ -0,0 +1,23 @@ +package main + +func main() { + var fns []func() int + for i := 0; i < 2; i++ { + f := func() int { + return i + } + fns = append(fns, f) + } + for _, fn := range fns { + println(fn()) + } +} + +// go 1.22 loop var is not supported for now. + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); for i := (const (0 int)); i<~VPBlock(1,0)> < (const (2 int)); i<~VPBlock(1,0)>++ { f := func func() (const-type int){ return i<~VPBlock(1,1)> }>; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Output: +// 2 +// 2 diff --git a/gnovm/tests/files/heap_alloc_forloop6f.gno b/gnovm/tests/files/heap_alloc_forloop6f.gno new file mode 100644 index 00000000000..fcc2cdfdcc1 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop6f.gno @@ -0,0 +1,26 @@ +package main + +func main() { + var fns []func() int + for i := 0; i < 5; i++ { + var x int + f := func() int { + return x + } + x = i + fns = append(fns, f) + } + for _, fn := range fns { + println(fn()) + } +} + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); for i := (const (0 int)); i < (const (5 int)); i++ { var x (const-type int); f := func func() (const-type int){ return x<~VPBlock(1,1)> }>; x<~VPBlock(1,1)> = i; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Output: +// 0 +// 1 +// 2 +// 3 +// 4 diff --git a/gnovm/tests/files/heap_alloc_forloop6g.gno b/gnovm/tests/files/heap_alloc_forloop6g.gno new file mode 100644 index 00000000000..4ff7856c97c --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop6g.gno @@ -0,0 +1,27 @@ +package main + +func main() { + var fns []func() int + for i := 0; i < 5; i++ { + x := i + { // another block + f := func() int { + return x + } + fns = append(fns, f) + } + } + for _, fn := range fns { + println(fn()) + } +} + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); for i := (const (0 int)); i < (const (5 int)); i++ { x := i; { f := func func() (const-type int){ return x<~VPBlock(1,1)> }>; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) } }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Output: +// 0 +// 1 +// 2 +// 3 +// 4 diff --git a/gnovm/tests/files/heap_alloc_forloop6h.gno b/gnovm/tests/files/heap_alloc_forloop6h.gno new file mode 100644 index 00000000000..75b84bebf91 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop6h.gno @@ -0,0 +1,33 @@ +package main + +func main() { + var fns []func() int + for i := 0; i < 2; i++ { + x := i + for j := 0; j < 2; j++ { + y := j + f := func() int { + return x + y + } + fns = append(fns, f) + } + } + for _, fn := range fns { + println(fn()) + } +} + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); for i := (const (0 int)); i < (const (2 int)); i++ { x := i; for j := (const (0 int)); j < (const (2 int)); j++ { y := j; f := func func() (const-type int){ return x<~VPBlock(1,1)> + y<~VPBlock(1,2)> }, y<()~VPBlock(1,1)>>; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) } }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Go Output: +// 0 +// 1 +// 1 +// 2 + +// Output: +// 0 +// 1 +// 1 +// 2 diff --git a/gnovm/tests/files/heap_alloc_forloop6h0.gno b/gnovm/tests/files/heap_alloc_forloop6h0.gno new file mode 100644 index 00000000000..0225bd62cf6 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop6h0.gno @@ -0,0 +1,27 @@ +package main + +func main() { + var fns []func() int + for i := 0; i < 2; i++ { + for j := 0; j < 2; j++ { + f := func() int { + return i + j + } + fns = append(fns, f) + } + } + for _, fn := range fns { + println(fn()) + } +} + +// go 1.22 loop var is not supported for now. + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); for i := (const (0 int)); i<~VPBlock(1,0)> < (const (2 int)); i<~VPBlock(1,0)>++ { for j := (const (0 int)); j<~VPBlock(1,0)> < (const (2 int)); j<~VPBlock(1,0)>++ { f := func func() (const-type int){ return i<~VPBlock(1,1)> + j<~VPBlock(1,2)> }, j<()~VPBlock(1,0)>>; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) } }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Output: +// 4 +// 4 +// 4 +// 4 diff --git a/gnovm/tests/files/heap_alloc_forloop6i.gno b/gnovm/tests/files/heap_alloc_forloop6i.gno new file mode 100644 index 00000000000..28bb17cbf5f --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop6i.gno @@ -0,0 +1,34 @@ +package main + +func main() { + var fns []func() int + var x int + for i := 0; i < 2; i++ { + x = i + for j := 0; j < 2; j++ { + y := j + f := func() int { + return x + y + } + fns = append(fns, f) + } + } + for _, fn := range fns { + println(fn()) + } +} + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); var x (const-type int); for i := (const (0 int)); i < (const (2 int)); i++ { x = i; for j := (const (0 int)); j < (const (2 int)); j++ { y := j; f := func func() (const-type int){ return x + y<~VPBlock(1,1)> }>; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) } }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Go Output: +// 1 +// 2 +// 1 +// 2 + +// Output: +// 1 +// 2 +// 1 +// 2 diff --git a/gnovm/tests/files/heap_alloc_forloop7.gno b/gnovm/tests/files/heap_alloc_forloop7.gno new file mode 100644 index 00000000000..95fdf42045d --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop7.gno @@ -0,0 +1,28 @@ +package main + +func main() { + var fns []func() int + + for i := 0; i < 2; i++ { + x := i + f := func() int { + if true { + if true { + return x + } + } + return 0 + } + fns = append(fns, f) + } + for _, fn := range fns { + println(fn()) + } +} + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); for i := (const (0 int)); i < (const (2 int)); i++ { x := i; f := func func() (const-type int){ if (const (true bool)) { if (const (true bool)) { return x<~VPBlock(3,1)> } }; return (const (0 int)) }>; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Output: +// 0 +// 1 diff --git a/gnovm/tests/files/heap_alloc_forloop7a.gno b/gnovm/tests/files/heap_alloc_forloop7a.gno new file mode 100644 index 00000000000..59e83022f57 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop7a.gno @@ -0,0 +1,26 @@ +package main + +func main() { + var fns []func() int + + for i := 0; i < 2; i++ { + x := i + f := func() int { + if true { + return x + } + return 0 + } + fns = append(fns, f) + } + for _, fn := range fns { + println(fn()) + } +} + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); for i := (const (0 int)); i < (const (2 int)); i++ { x := i; f := func func() (const-type int){ if (const (true bool)) { return x<~VPBlock(2,1)> }; return (const (0 int)) }>; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Output: +// 0 +// 1 diff --git a/gnovm/tests/files/heap_alloc_forloop8.gno b/gnovm/tests/files/heap_alloc_forloop8.gno new file mode 100644 index 00000000000..7c86fdc5b90 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop8.gno @@ -0,0 +1,25 @@ +package main + +func main() { + var fns []func() int + + for i := 0; i < 2; i++ { + x := i + f := func() int { + { + return x + } + } + fns = append(fns, f) + } + for _, fn := range fns { + println(fn()) + } +} + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); for i := (const (0 int)); i < (const (2 int)); i++ { x := i; f := func func() (const-type int){ { return x<~VPBlock(2,1)> } }>; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Output: +// 0 +// 1 diff --git a/gnovm/tests/files/heap_alloc_forloop8a.gno b/gnovm/tests/files/heap_alloc_forloop8a.gno new file mode 100644 index 00000000000..f0864fa07da --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop8a.gno @@ -0,0 +1,26 @@ +package main + +func main() { + var fns []func() int + + for i := 0; i < 2; i++ { + x := i + f := func() int { + for i := 0; i < 1; i++ { + x++ + } + return x + } + fns = append(fns, f) + } + for _, fn := range fns { + println(fn()) + } +} + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); for i := (const (0 int)); i < (const (2 int)); i++ { x := i; f := func func() (const-type int){ for i := (const (0 int)); i < (const (1 int)); i++ { x<~VPBlock(2,1)>++ }; return x<~VPBlock(1,1)> }>; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Output: +// 1 +// 2 diff --git a/gnovm/tests/files/heap_alloc_forloop8b.gno b/gnovm/tests/files/heap_alloc_forloop8b.gno new file mode 100644 index 00000000000..1cd6bf13cc3 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop8b.gno @@ -0,0 +1,28 @@ +package main + +func main() { + var fns []func() int + + for i := 0; i < 2; i++ { + x := i + s := []int{1, 2} + + f := func() int { + for _, v := range s { + x += v + } + return x + } + fns = append(fns, f) + } + for _, fn := range fns { + println(fn()) + } +} + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); for i := (const (0 int)); i < (const (2 int)); i++ { x := i; s := [](const-type int){(const (1 int)), (const (2 int))}; f := func func() (const-type int){ for _, v := range s<~VPBlock(2,1)> { x<~VPBlock(2,2)> += v }; return x<~VPBlock(1,2)> }, x<()~VPBlock(1,1)>>; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Output: +// 3 +// 4 diff --git a/gnovm/tests/files/heap_alloc_forloop8c.gno b/gnovm/tests/files/heap_alloc_forloop8c.gno new file mode 100644 index 00000000000..11aef1683b8 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop8c.gno @@ -0,0 +1,30 @@ +package main + +func main() { + var fns []func() int + + for i := 0; i < 2; i++ { + x := i + y := 1 + f := func() int { + switch y { + case 1: + x += 1 + default: + x += 0 + } + return x + } + fns = append(fns, f) + } + for _, fn := range fns { + println(fn()) + } +} + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); for i := (const (0 int)); i < (const (2 int)); i++ { x := i; y := (const (1 int)); f := func func() (const-type int){ switch y<~VPBlock(2,1)> { case (const (1 int)): x<~VPBlock(2,2)> += (const (1 int)); default: x<~VPBlock(2,2)> += (const (0 int)) }; return x<~VPBlock(1,2)> }, x<()~VPBlock(1,1)>>; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Output: +// 1 +// 2 diff --git a/gnovm/tests/files/heap_alloc_forloop9.gno b/gnovm/tests/files/heap_alloc_forloop9.gno new file mode 100644 index 00000000000..0f1d0b8b23c --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop9.gno @@ -0,0 +1,42 @@ +package main + +import "fmt" + +// recursive closure does not capture +func main() { + var fns []func(int) int + var recursiveFunc func(int) int + + for i := 0; i < 3; i++ { + recursiveFunc = func(num int) int { + x := i + println("value of x: ", x) + if num <= 0 { + return 1 + } + return num * recursiveFunc(num-1) + } + fns = append(fns, recursiveFunc) + } + + for i, r := range fns { + result := r(i) + fmt.Printf("Factorial of %d is: %d\n", i, result) + } +} + +// go 1.22 loop var is not supported for now. + +// Preprocessed: +// file{ package main; import fmt fmt; func main() { var fns []func(.arg_0 (const-type int)) (const-type int); var recursiveFunc func(.arg_0 (const-type int)) (const-type int); for i := (const (0 int)); i<~VPBlock(1,0)> < (const (3 int)); i<~VPBlock(1,0)>++ { recursiveFunc = func func(num (const-type int)) (const-type int){ x := i<~VPBlock(1,3)>; (const (println func(xs ...interface{})()))((const ("value of x: " string)), x); if num <= (const (0 int)) { return (const (1 int)) }; return num * recursiveFunc(num - (const (1 int))) }>; fns = (const (append func(x []func(.arg_0 int)( int),args ...func(.arg_0 int)( int))(res []func(.arg_0 int)( int))))(fns, recursiveFunc) }; for i, r := range fns { result := r(i); fmt.Printf((const ("Factorial of %d is: %d\n" string)), (const-type gonative{interface {}})(i), (const-type gonative{interface {}})(result)) } } } + +// Output: +// value of x: 3 +// Factorial of 0 is: 1 +// value of x: 3 +// value of x: 3 +// Factorial of 1 is: 1 +// value of x: 3 +// value of x: 3 +// value of x: 3 +// Factorial of 2 is: 2 diff --git a/gnovm/tests/files/heap_alloc_forloop9_1.gno b/gnovm/tests/files/heap_alloc_forloop9_1.gno new file mode 100644 index 00000000000..5e3b9af74f6 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop9_1.gno @@ -0,0 +1,25 @@ +package main + +func Search(n int, f func(int) bool) int { + f(1) + return 0 +} + +// TODO: identify this pattern, optimize. +func main() { + for x := 0; x < 2; x++ { + count := 0 + println(" first: count: ", count) + Search(1, func(i int) bool { count++; return i >= x }) + println("second: count: ", count) + } +} + +// Preprocessed: +// file{ package main; func Search(n (const-type int), f func(.arg_0 (const-type int)) (const-type bool)) (const-type int) { f((const (1 int))); return (const (0 int)) }; func main() { for x := (const (0 int)); x<~VPBlock(1,0)> < (const (2 int)); x<~VPBlock(1,0)>++ { count := (const (0 int)); (const (println func(xs ...interface{})()))((const (" first: count: " string)), count<~VPBlock(1,1)>); Search((const (1 int)), func func(i (const-type int)) (const-type bool){ count<~VPBlock(1,2)>++; return (const-type bool)(i >= x<~VPBlock(1,3)>) }, x<()~VPBlock(1,0)>>); (const (println func(xs ...interface{})()))((const ("second: count: " string)), count<~VPBlock(1,1)>) } } } + +// Output: +// first: count: 0 +// second: count: 1 +// first: count: 0 +// second: count: 1 diff --git a/gnovm/tests/files/heap_alloc_forloop9_2.gno b/gnovm/tests/files/heap_alloc_forloop9_2.gno new file mode 100644 index 00000000000..6b1ebdbb7e9 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop9_2.gno @@ -0,0 +1,36 @@ +package main + +func main() { + var fns []func() int + + println("start for loop") + for i := 0; i < 2; i++ { + defer func() { + println("defer") + for _, fn := range fns { + println(fn()) + } + }() + + x := i + f := func() int { + return x + } + + fns = append(fns, f) + } + println("end for loop") +} + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); (const (println func(xs ...interface{})()))((const ("start for loop" string))); for i := (const (0 int)); i < (const (2 int)); i++ { defer func func(){ (const (println func(xs ...interface{})()))((const ("defer" string))); for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } }(); x := i; f := func func() (const-type int){ return x<~VPBlock(1,1)> }>; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) }; (const (println func(xs ...interface{})()))((const ("end for loop" string))) } } + +// Output: +// start for loop +// end for loop +// defer +// 0 +// 1 +// defer +// 0 +// 1 diff --git a/gnovm/tests/files/heap_alloc_forloop9b.gno b/gnovm/tests/files/heap_alloc_forloop9b.gno new file mode 100644 index 00000000000..03e84fcd2b2 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_forloop9b.gno @@ -0,0 +1,28 @@ +package main + +func main() { + var y int + var f []func() + defer func() { + for _, ff := range f { + ff() + } + }() + + for i := 0; i < 2; i++ { + for j := 0; j < 2; j++ { + x := y + f = append(f, func() { println(x) }) + y++ + } + } +} + +// Preprocessed: +// file{ package main; func main() { var y (const-type int); var f []func(); defer func func(){ for _, ff := range f { ff() } }(); for i := (const (0 int)); i < (const (2 int)); i++ { for j := (const (0 int)); j < (const (2 int)); j++ { x := y; f = (const (append func(x []func()(),args ...func()())(res []func()())))(f, func func(){ (const (println func(xs ...interface{})()))(x<~VPBlock(1,0)>) }>); y++ } } } } + +// Output: +// 0 +// 1 +// 2 +// 3 diff --git a/gnovm/tests/files/heap_alloc_gotoloop0.gno b/gnovm/tests/files/heap_alloc_gotoloop0.gno new file mode 100644 index 00000000000..d13baedf7c4 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop0.gno @@ -0,0 +1,28 @@ +package main + +func main() { + var counter int + var f []func() + defer func() { + for _, ff := range f { + ff() + } + }() + + // this is actually an implicit for loop +LABEL_1: + if counter == 2 { + return + } + x := counter + f = append(f, func() { println(x) }) + counter++ + goto LABEL_1 +} + +// Preprocessed: +// file{ package main; func main() { var counter (const-type int); var f []func(); defer func func(){ for _, ff := range f { ff() } }(); if counter == (const (2 int)) { return }; x := counter; f = (const (append func(x []func()(),args ...func()())(res []func()())))(f, func func(){ (const (println func(xs ...interface{})()))(x<~VPBlock(1,0)>) }>); counter++; goto LABEL_1<0,3> } } + +// Output: +// 0 +// 1 diff --git a/gnovm/tests/files/heap_alloc_gotoloop1.gno b/gnovm/tests/files/heap_alloc_gotoloop1.gno new file mode 100644 index 00000000000..ea26952e0a4 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop1.gno @@ -0,0 +1,30 @@ +package main + +func main() { + c := 0 +loop: + i := 1 + println(i) + c += 1 + if c < 10 { + goto loop + } +} + +// This does not make 'i' NameExprTypeHeapDefine, +// because it is not actually used in a &ref or closure context. + +// Preprocessed: +// file{ package main; func main() { c := (const (0 int)); i := (const (1 int)); (const (println func(xs ...interface{})()))(i); c += (const (1 int)); if c < (const (10 int)) { goto loop<1,1> } } } + +// Output: +// 1 +// 1 +// 1 +// 1 +// 1 +// 1 +// 1 +// 1 +// 1 +// 1 diff --git a/gnovm/tests/files/heap_alloc_gotoloop2.gno b/gnovm/tests/files/heap_alloc_gotoloop2.gno new file mode 100644 index 00000000000..e7b2917a8ff --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop2.gno @@ -0,0 +1,37 @@ +package main + +func main() { + c := 0 + closures := []func(){} +loop: + i := c + closures = append(closures, func() { + println(i) + }) + c += 1 + if c < 10 { + goto loop + } + + for _, cl := range closures { + cl() + } +} + +// This does make 'i' NameExprTypeHeapDefine. +// You can tell by the preprocess printout of i and i<()~...>. + +// Preprocessed: +// file{ package main; func main() { c := (const (0 int)); closures := []func(){}; i := c; closures = (const (append func(x []func()(),args ...func()())(res []func()())))(closures, func func(){ (const (println func(xs ...interface{})()))(i<~VPBlock(1,0)>) }>); c += (const (1 int)); if c < (const (10 int)) { goto loop<1,2> }; for _, cl := range closures { cl() } } } + +// Output: +// 0 +// 1 +// 2 +// 3 +// 4 +// 5 +// 6 +// 7 +// 8 +// 9 diff --git a/gnovm/tests/files/heap_alloc_gotoloop3.gno b/gnovm/tests/files/heap_alloc_gotoloop3.gno new file mode 100644 index 00000000000..a248e8aa0bc --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop3.gno @@ -0,0 +1,34 @@ +package main + +func main() { + c := 0 + refs := []*int{} +loop: + i := c + refs = append(refs, &i) + c += 1 + if c < 10 { + goto loop + } + for _, ref := range refs { + println(*ref) + } +} + +// This does make 'i' NameExprTypeHeapDefine. +// You can tell by the preprocess printout of i and i<~...>. + +// Preprocessed: +// file{ package main; func main() { c := (const (0 int)); refs := []*((const-type int)){}; i := c; refs = (const (append func(x []*int,args ...*int)(res []*int)))(refs, &(i<~VPBlock(1,2)>)); c += (const (1 int)); if c < (const (10 int)) { goto loop<1,2> }; for _, ref := range refs { (const (println func(xs ...interface{})()))(*(ref)) } } } + +// Output: +// 0 +// 1 +// 2 +// 3 +// 4 +// 5 +// 6 +// 7 +// 8 +// 9 diff --git a/gnovm/tests/files/heap_alloc_gotoloop4.gno b/gnovm/tests/files/heap_alloc_gotoloop4.gno new file mode 100644 index 00000000000..062d832ac16 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop4.gno @@ -0,0 +1,34 @@ +package main + +func main() { + c := 0 + refs := []*int{} +loop: + var i int = c + refs = append(refs, &i) + c += 1 + if c < 10 { + goto loop + } + for _, ref := range refs { + println(*ref) + } +} + +// This does make 'i' NameExprTypeHeapDefine. +// You can tell by the preprocess printout of i and i<~...>. + +// Preprocessed: +// file{ package main; func main() { c := (const (0 int)); refs := []*((const-type int)){}; var i (const-type int) = c; refs = (const (append func(x []*int,args ...*int)(res []*int)))(refs, &(i<~VPBlock(1,2)>)); c += (const (1 int)); if c < (const (10 int)) { goto loop<1,2> }; for _, ref := range refs { (const (println func(xs ...interface{})()))(*(ref)) } } } + +// Output: +// 0 +// 1 +// 2 +// 3 +// 4 +// 5 +// 6 +// 7 +// 8 +// 9 diff --git a/gnovm/tests/files/heap_alloc_gotoloop5.gno b/gnovm/tests/files/heap_alloc_gotoloop5.gno new file mode 100644 index 00000000000..fb7a82228f1 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop5.gno @@ -0,0 +1,39 @@ +package main + +func main() { + c := 0 + refs := []*int{} +loop: + i, j := c, 2 + refs = append(refs, &i) + i += 1 + j += 1 + c += 1 + if c < 10 { + goto loop + } + for _, ref := range refs { + println(*ref) + } + if false { + println(j) // dummy usage + } +} + +// This does make 'i' NameExprTypeHeapDefine. +// You can tell by the preprocess printout of i and i<~...>. + +// Preprocessed: +// file{ package main; func main() { c := (const (0 int)); refs := []*((const-type int)){}; i, j := c, (const (2 int)); refs = (const (append func(x []*int,args ...*int)(res []*int)))(refs, &(i<~VPBlock(1,2)>)); i<~VPBlock(1,2)> += (const (1 int)); j += (const (1 int)); c += (const (1 int)); if c < (const (10 int)) { goto loop<1,2> }; for _, ref := range refs { (const (println func(xs ...interface{})()))(*(ref)) }; if (const (false bool)) { (const (println func(xs ...interface{})()))(j) } } } + +// Output: +// 1 +// 2 +// 3 +// 4 +// 5 +// 6 +// 7 +// 8 +// 9 +// 10 diff --git a/gnovm/tests/files/heap_alloc_gotoloop6.gno b/gnovm/tests/files/heap_alloc_gotoloop6.gno new file mode 100644 index 00000000000..d2efbb85df2 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop6.gno @@ -0,0 +1,39 @@ +package main + +func main() { + c := 0 + refs := []*int{} +loop: + var i, j int = c, 2 + refs = append(refs, &i) + i += 1 + j += 1 + c += 1 + if c < 10 { + goto loop + } + for _, ref := range refs { + println(*ref) + } + if false { + println(j) // dummy usage + } +} + +// This does make 'i' NameExprTypeHeapDefine. +// You can tell by the preprocess printout of i and i<~...>. + +// Preprocessed: +// file{ package main; func main() { c := (const (0 int)); refs := []*((const-type int)){}; var i, j (const-type int) = c, (const (2 int)); refs = (const (append func(x []*int,args ...*int)(res []*int)))(refs, &(i<~VPBlock(1,2)>)); i<~VPBlock(1,2)> += (const (1 int)); j += (const (1 int)); c += (const (1 int)); if c < (const (10 int)) { goto loop<1,2> }; for _, ref := range refs { (const (println func(xs ...interface{})()))(*(ref)) }; if (const (false bool)) { (const (println func(xs ...interface{})()))(j) } } } + +// Output: +// 1 +// 2 +// 3 +// 4 +// 5 +// 6 +// 7 +// 8 +// 9 +// 10 diff --git a/gnovm/tests/files/heap_alloc_gotoloop7.gno b/gnovm/tests/files/heap_alloc_gotoloop7.gno new file mode 100644 index 00000000000..457fdb74a01 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop7.gno @@ -0,0 +1,48 @@ +package main + +func main() { + c := 0 + refs := []*int{} +loop: + var i, j int = c, 2 + refs = append(refs, &i) + i += 1 + j += 1 + c += 1 + thing := func() { + i := 2 // new i + j := 3 // new j + println(i) + println(j) + } + if c < 10 { + goto loop + } + for _, ref := range refs { + println(*ref) + } + if false { + println(j) // dummy usage + } + if false { + thing() // dummy usage + } +} + +// This does make 'i' NameExprTypeHeapDefine. +// You can tell by the preprocess printout of i and i<~...>. + +// Preprocessed: +// file{ package main; func main() { c := (const (0 int)); refs := []*((const-type int)){}; var i, j (const-type int) = c, (const (2 int)); refs = (const (append func(x []*int,args ...*int)(res []*int)))(refs, &(i<~VPBlock(1,2)>)); i<~VPBlock(1,2)> += (const (1 int)); j += (const (1 int)); c += (const (1 int)); thing := func func(){ i := (const (2 int)); j := (const (3 int)); (const (println func(xs ...interface{})()))(i); (const (println func(xs ...interface{})()))(j) }; if c < (const (10 int)) { goto loop<1,2> }; for _, ref := range refs { (const (println func(xs ...interface{})()))(*(ref)) }; if (const (false bool)) { (const (println func(xs ...interface{})()))(j) }; if (const (false bool)) { thing() } } } + +// Output: +// 1 +// 2 +// 3 +// 4 +// 5 +// 6 +// 7 +// 8 +// 9 +// 10 diff --git a/gnovm/tests/files/heap_alloc_gotoloop8.gno b/gnovm/tests/files/heap_alloc_gotoloop8.gno new file mode 100644 index 00000000000..f3421048d41 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop8.gno @@ -0,0 +1,37 @@ +package main + +func main() { + c := 0 + closures := []func(){} + goto loop1 +loop1: // not a loop + i := 1 +loop2: + closures = append(closures, func() { + println(i) + }) + c += 1 + if c < 10 { + goto loop2 + } + for _, cl := range closures { + cl() + } +} + +// This one doesn't because the goto stmt doesn't go back far enough. + +// Preprocessed: +// file{ package main; func main() { c := (const (0 int)); closures := []func(){}; goto loop1<0,3>; i := (const (1 int)); closures = (const (append func(x []func()(),args ...func()())(res []func()())))(closures, func func(){ (const (println func(xs ...interface{})()))(i) }); c += (const (1 int)); if c < (const (10 int)) { goto loop2<1,4> }; for _, cl := range closures { cl() } } } + +// Output: +// 1 +// 1 +// 1 +// 1 +// 1 +// 1 +// 1 +// 1 +// 1 +// 1 diff --git a/gnovm/tests/files/heap_alloc_gotoloop9.gno b/gnovm/tests/files/heap_alloc_gotoloop9.gno new file mode 100644 index 00000000000..38204652216 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop9.gno @@ -0,0 +1,35 @@ +package main + +func main() { + c := 0 + closures := []func(){} + i := 1 +loop2: + closures = append(closures, func() { + println(i) + }) + c += 1 + if c < 10 { + goto loop2 + } + for _, cl := range closures { + cl() + } +} + +// This one doesn't because the goto stmt doesn't go back far enough. + +// Preprocessed: +// file{ package main; func main() { c := (const (0 int)); closures := []func(){}; i := (const (1 int)); closures = (const (append func(x []func()(),args ...func()())(res []func()())))(closures, func func(){ (const (println func(xs ...interface{})()))(i) }); c += (const (1 int)); if c < (const (10 int)) { goto loop2<1,3> }; for _, cl := range closures { cl() } } } + +// Output: +// 1 +// 1 +// 1 +// 1 +// 1 +// 1 +// 1 +// 1 +// 1 +// 1 diff --git a/gnovm/tests/files/heap_alloc_gotoloop9_10.gno b/gnovm/tests/files/heap_alloc_gotoloop9_10.gno new file mode 100644 index 00000000000..bb8a2bad3ef --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop9_10.gno @@ -0,0 +1,64 @@ +package main + +import "fmt" + +var s1 []*int +var s2 []*int + +// intersection loop +func main() { + defer func() { + for i, v := range s1 { + fmt.Printf("s1[%d] is %d\n", i, *v) + } + for i, v := range s2 { + fmt.Printf("s2[%d] is %d\n", i, *v) + } + }() + + // counter for loop + var c1, c2 int + +LOOP_1: + x := c1 + s1 = append(s1, &x) + println("loop_1", c1) + c1++ + +LOOP_2: + y := c2 + s2 = append(s2, &y) + println("loop_2", c2) + c2++ + + if c1 < 3 { + goto LOOP_1 + } + + if c2 < 6 { + goto LOOP_2 + } +} + +// Preprocessed: +// file{ package main; import fmt fmt; var s1 []*((const-type int)); var s2 []*((const-type int)); func main() { defer func func(){ for i, v := range s1 { fmt.Printf((const ("s1[%d] is %d\n" string)), (const-type gonative{interface {}})(i), (const-type gonative{interface {}})(*(v))) }; for i, v := range s2 { fmt.Printf((const ("s2[%d] is %d\n" string)), (const-type gonative{interface {}})(i), (const-type gonative{interface {}})(*(v))) } }(); var c1, c2 (const-type int); x := c1; s1 = (const (append func(x []*int,args ...*int)(res []*int)))(s1, &(x<~VPBlock(1,2)>)); (const (println func(xs ...interface{})()))((const ("loop_1" string)), c1); c1++; y := c2; s2 = (const (append func(x []*int,args ...*int)(res []*int)))(s2, &(y<~VPBlock(1,3)>)); (const (println func(xs ...interface{})()))((const ("loop_2" string)), c2); c2++; if c1 < (const (3 int)) { goto LOOP_1<1,2> }; if c2 < (const (6 int)) { goto LOOP_2<1,6> } } } + +// Output: +// loop_1 0 +// loop_2 0 +// loop_1 1 +// loop_2 1 +// loop_1 2 +// loop_2 2 +// loop_2 3 +// loop_2 4 +// loop_2 5 +// s1[0] is 0 +// s1[1] is 1 +// s1[2] is 2 +// s2[0] is 0 +// s2[1] is 1 +// s2[2] is 2 +// s2[3] is 3 +// s2[4] is 4 +// s2[5] is 5 diff --git a/gnovm/tests/files/heap_alloc_gotoloop9_11.gno b/gnovm/tests/files/heap_alloc_gotoloop9_11.gno new file mode 100644 index 00000000000..839612704a8 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop9_11.gno @@ -0,0 +1,29 @@ +package main + +func main() { + var y, counter int + var f []func() + defer func() { + for _, ff := range f { + ff() + } + }() + + // this is actually an implicit for loop +LABEL_1: + if counter == 2 { + return + } + var _, x = 0, y + f = append(f, func() { println(x) }) + y++ + counter++ + goto LABEL_1 +} + +// Preprocessed: +// file{ package main; func main() { var y, counter (const-type int); var f []func(); defer func func(){ for _, ff := range f { ff() } }(); if counter == (const (2 int)) { return }; var _, x = (const (0 int)), y; f = (const (append func(x []func()(),args ...func()())(res []func()())))(f, func func(){ (const (println func(xs ...interface{})()))(x<~VPBlock(1,0)>) }>); y++; counter++; goto LABEL_1<0,3> } } + +// Output: +// 0 +// 1 diff --git a/gnovm/tests/files/heap_alloc_gotoloop9_12.gno b/gnovm/tests/files/heap_alloc_gotoloop9_12.gno new file mode 100644 index 00000000000..4d024a58673 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop9_12.gno @@ -0,0 +1,56 @@ +package main + +import "fmt" + +func main() { + counter0 := 0 + counter1 := 0 + + y := 0 + + var fs []func() + + defer func() { + for _, ff := range fs { + ff() + } + }() + +LOOP_START: + if counter0 < 2 { + counter1 = 0 + fmt.Printf("Outer loop start: counter0=%d\n", counter0) + + NESTED_LOOP_START: + if counter1 < 2 { + fmt.Printf(" Nested loop: counter1=%d\n", counter1) + counter1++ + goto NESTED_LOOP_START + } + + x := y + fs = append(fs, func() { println(x) }) + + fmt.Println("Exiting nested loop") + counter0++ + y++ + goto LOOP_START + } else { + return + } +} + +// Preprocessed: +// file{ package main; import fmt fmt; func main() { counter0 := (const (0 int)); counter1 := (const (0 int)); y := (const (0 int)); var fs []func(); defer func func(){ for _, ff := range fs { ff() } }(); if counter0 < (const (2 int)) { counter1 = (const (0 int)); fmt.Printf((const ("Outer loop start: counter0=%d\n" string)), (const-type gonative{interface {}})(counter0)); if counter1 < (const (2 int)) { fmt.Printf((const (" Nested loop: counter1=%d\n" string)), (const-type gonative{interface {}})(counter1)); counter1++; goto NESTED_LOOP_START<1,2> }; x := y; fs = (const (append func(x []func()(),args ...func()())(res []func()())))(fs, func func(){ (const (println func(xs ...interface{})()))(x<~VPBlock(1,0)>) }>); fmt.Println((const ("Exiting nested loop" string))); counter0++; y++; goto LOOP_START<1,5> } else { return } } } + +// Output: +// Outer loop start: counter0=0 +// Nested loop: counter1=0 +// Nested loop: counter1=1 +// Exiting nested loop +// Outer loop start: counter0=1 +// Nested loop: counter1=0 +// Nested loop: counter1=1 +// Exiting nested loop +// 0 +// 1 diff --git a/gnovm/tests/files/heap_alloc_gotoloop9_13.gno b/gnovm/tests/files/heap_alloc_gotoloop9_13.gno new file mode 100644 index 00000000000..7c7b6777223 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop9_13.gno @@ -0,0 +1,41 @@ +package main + +func main() { + var y, counter int + var f []func() + defer func() { + for _, ff := range f { + ff() + } + }() + +LABEL_1: + x := y + if counter == 2 { + counter = 0 + goto LABEL_2 + } + f = append(f, func() { println(x) }) + y++ + counter++ + goto LABEL_1 + +LABEL_2: + if counter == 2 { + return + } + z := y + f = append(f, func() { println(z) }) + y++ + counter++ + goto LABEL_2 +} + +// Preprocessed: +// file{ package main; func main() { var y, counter (const-type int); var f []func(); defer func func(){ for _, ff := range f { ff() } }(); x := y; if counter == (const (2 int)) { counter = (const (0 int)); goto LABEL_2<1,9> }; f = (const (append func(x []func()(),args ...func()())(res []func()())))(f, func func(){ (const (println func(xs ...interface{})()))(x<~VPBlock(1,0)>) }>); y++; counter++; goto LABEL_1<0,3>; if counter == (const (2 int)) { return }; z := y; f = (const (append func(x []func()(),args ...func()())(res []func()())))(f, func func(){ (const (println func(xs ...interface{})()))(z<~VPBlock(1,0)>) }>); y++; counter++; goto LABEL_2<0,9> } } + +// Output: +// 0 +// 1 +// 2 +// 3 diff --git a/gnovm/tests/files/heap_alloc_gotoloop9_14.gno b/gnovm/tests/files/heap_alloc_gotoloop9_14.gno new file mode 100644 index 00000000000..f92b31eb7de --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop9_14.gno @@ -0,0 +1,43 @@ +package main + +func main() { + var y, counter int + var f []func() + defer func() { + for _, ff := range f { + ff() + } + }() + + { + LABEL_1: + x := y + if counter == 2 { + counter = 0 + goto LABEL_2 + } + f = append(f, func() { println(x) }) + y++ + counter++ + goto LABEL_1 + } + +LABEL_2: + if counter == 2 { + return + } + z := y + f = append(f, func() { println(z) }) + y++ + counter++ + goto LABEL_2 +} + +// Preprocessed: +// file{ package main; func main() { var y, counter (const-type int); var f []func(); defer func func(){ for _, ff := range f { ff() } }(); { x := y; if counter == (const (2 int)) { counter = (const (0 int)); goto LABEL_2<2,4> }; f = (const (append func(x []func()(),args ...func()())(res []func()())))(f, func func(){ (const (println func(xs ...interface{})()))(x<~VPBlock(1,0)>) }>); y++; counter++; goto LABEL_1<0,0> }; if counter == (const (2 int)) { return }; z := y; f = (const (append func(x []func()(),args ...func()())(res []func()())))(f, func func(){ (const (println func(xs ...interface{})()))(z<~VPBlock(1,0)>) }>); y++; counter++; goto LABEL_2<0,4> } } + +// Output: +// 0 +// 1 +// 2 +// 3 diff --git a/gnovm/tests/files/heap_alloc_gotoloop9_15.gno b/gnovm/tests/files/heap_alloc_gotoloop9_15.gno new file mode 100644 index 00000000000..d774af55eb6 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop9_15.gno @@ -0,0 +1,48 @@ +package main + +var y, counter int +var f []func() + +func main() { + defer func() { + for _, ff := range f { // XXX, why defer on this not work + ff() + } + }() +LABEL_1: + x := y + if counter == 2 { + counter = 0 + bar() + return + } + f = append(f, func() { println(x) }) + y++ + counter++ + goto LABEL_1 +} + +func bar() { + println("---bar---") +LABEL_2: + if counter == 2 { + println("---end---") + return + } + z := y + f = append(f, func() { println(z) }) + y++ + counter++ + goto LABEL_2 +} + +// Preprocessed: +// file{ package main; var y, counter (const-type int); var f []func(); func main() { defer func func(){ for _, ff := range f { ff() } }(); x := y; if counter == (const (2 int)) { counter = (const (0 int)); bar(); return }; f = (const (append func(x []func()(),args ...func()())(res []func()())))(f, func func(){ (const (println func(xs ...interface{})()))(x<~VPBlock(1,0)>) }>); y++; counter++; goto LABEL_1<0,1> }; func bar() { (const (println func(xs ...interface{})()))((const ("---bar---" string))); if counter == (const (2 int)) { (const (println func(xs ...interface{})()))((const ("---end---" string))); return }; z := y; f = (const (append func(x []func()(),args ...func()())(res []func()())))(f, func func(){ (const (println func(xs ...interface{})()))(z<~VPBlock(1,0)>) }>); y++; counter++; goto LABEL_2<0,1> } } + +// Output: +// ---bar--- +// ---end--- +// 0 +// 1 +// 2 +// 3 diff --git a/gnovm/tests/files/heap_alloc_gotoloop9_15a.gno b/gnovm/tests/files/heap_alloc_gotoloop9_15a.gno new file mode 100644 index 00000000000..2d9de02ecc3 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop9_15a.gno @@ -0,0 +1,46 @@ +package main + +var y, counter int +var f []func() + +func main() { +LABEL_1: + x := y + if counter == 2 { + counter = 0 + bar() + for _, ff := range f { // XXX, why defer on this not work + ff() + } + return + } + f = append(f, func() { println(x) }) + y++ + counter++ + goto LABEL_1 +} + +func bar() { + println("---bar---") +LABEL_2: + if counter == 2 { + println("---end---") + return + } + z := y + f = append(f, func() { println(z) }) + y++ + counter++ + goto LABEL_2 +} + +// Preprocessed: +// file{ package main; var y, counter (const-type int); var f []func(); func main() { x := y; if counter == (const (2 int)) { counter = (const (0 int)); bar(); for _, ff := range f { ff() }; return }; f = (const (append func(x []func()(),args ...func()())(res []func()())))(f, func func(){ (const (println func(xs ...interface{})()))(x<~VPBlock(1,0)>) }>); y++; counter++; goto LABEL_1<0,0> }; func bar() { (const (println func(xs ...interface{})()))((const ("---bar---" string))); if counter == (const (2 int)) { (const (println func(xs ...interface{})()))((const ("---end---" string))); return }; z := y; f = (const (append func(x []func()(),args ...func()())(res []func()())))(f, func func(){ (const (println func(xs ...interface{})()))(z<~VPBlock(1,0)>) }>); y++; counter++; goto LABEL_2<0,1> } } + +// Output: +// ---bar--- +// ---end--- +// 0 +// 1 +// 2 +// 3 diff --git a/gnovm/tests/files/heap_alloc_gotoloop9_16.gno b/gnovm/tests/files/heap_alloc_gotoloop9_16.gno new file mode 100644 index 00000000000..8971b04aee6 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop9_16.gno @@ -0,0 +1,58 @@ +package main + +import "fmt" + +func main() { + counter0 := 0 + counter1 := 0 + + y := 0 + + var fs []func() + + defer func() { + for _, ff := range fs { + ff() + } + }() + +LOOP_START: + if counter0 < 2 { + x := y + counter1 = 0 + fmt.Printf("Outer loop start: counter0=%d\n", counter0) + + NESTED_LOOP_START: + if counter1 < 2 { + fmt.Printf(" Nested loop: counter1=%d\n", counter1) + fs = append(fs, func() { println(x) }) + + counter1++ + goto NESTED_LOOP_START + } + + fmt.Println("Exiting nested loop") + counter0++ + y++ + goto LOOP_START + } else { + return + } +} + +// Preprocessed: +// file{ package main; import fmt fmt; func main() { counter0 := (const (0 int)); counter1 := (const (0 int)); y := (const (0 int)); var fs []func(); defer func func(){ for _, ff := range fs { ff() } }(); if counter0 < (const (2 int)) { x := y; counter1 = (const (0 int)); fmt.Printf((const ("Outer loop start: counter0=%d\n" string)), (const-type gonative{interface {}})(counter0)); if counter1 < (const (2 int)) { fmt.Printf((const (" Nested loop: counter1=%d\n" string)), (const-type gonative{interface {}})(counter1)); fs = (const (append func(x []func()(),args ...func()())(res []func()())))(fs, func func(){ (const (println func(xs ...interface{})()))(x<~VPBlock(1,0)>) }>); counter1++; goto NESTED_LOOP_START<1,3> }; fmt.Println((const ("Exiting nested loop" string))); counter0++; y++; goto LOOP_START<1,5> } else { return } } } + +// Output: +// Outer loop start: counter0=0 +// Nested loop: counter1=0 +// Nested loop: counter1=1 +// Exiting nested loop +// Outer loop start: counter0=1 +// Nested loop: counter1=0 +// Nested loop: counter1=1 +// Exiting nested loop +// 0 +// 0 +// 1 +// 1 diff --git a/gnovm/tests/files/heap_alloc_gotoloop9_17.gno b/gnovm/tests/files/heap_alloc_gotoloop9_17.gno new file mode 100644 index 00000000000..9e5073c1bfe --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop9_17.gno @@ -0,0 +1,58 @@ +package main + +import "fmt" + +func main() { + counter0 := 0 + counter1 := 0 + + y := 0 + + var fs []func() + + defer func() { + for _, ff := range fs { + ff() + } + }() + +LOOP_START: + x := y + if counter0 < 2 { + counter1 = 0 + fmt.Printf("Outer loop start: counter0=%d\n", counter0) + + NESTED_LOOP_START: + if counter1 < 2 { + fmt.Printf(" Nested loop: counter1=%d\n", counter1) + fs = append(fs, func() { println(x) }) + + counter1++ + goto NESTED_LOOP_START + } + + fmt.Println("Exiting nested loop") + counter0++ + y++ + goto LOOP_START + } else { + return + } +} + +// Preprocessed: +// file{ package main; import fmt fmt; func main() { counter0 := (const (0 int)); counter1 := (const (0 int)); y := (const (0 int)); var fs []func(); defer func func(){ for _, ff := range fs { ff() } }(); x := y; if counter0 < (const (2 int)) { counter1 = (const (0 int)); fmt.Printf((const ("Outer loop start: counter0=%d\n" string)), (const-type gonative{interface {}})(counter0)); if counter1 < (const (2 int)) { fmt.Printf((const (" Nested loop: counter1=%d\n" string)), (const-type gonative{interface {}})(counter1)); fs = (const (append func(x []func()(),args ...func()())(res []func()())))(fs, func func(){ (const (println func(xs ...interface{})()))(x<~VPBlock(1,0)>) }>); counter1++; goto NESTED_LOOP_START<1,2> }; fmt.Println((const ("Exiting nested loop" string))); counter0++; y++; goto LOOP_START<1,5> } else { return } } } + +// Output: +// Outer loop start: counter0=0 +// Nested loop: counter1=0 +// Nested loop: counter1=1 +// Exiting nested loop +// Outer loop start: counter0=1 +// Nested loop: counter1=0 +// Nested loop: counter1=1 +// Exiting nested loop +// 0 +// 0 +// 1 +// 1 diff --git a/gnovm/tests/files/heap_alloc_gotoloop9_18.gno b/gnovm/tests/files/heap_alloc_gotoloop9_18.gno new file mode 100644 index 00000000000..1578eb5897f --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop9_18.gno @@ -0,0 +1,30 @@ +package main + +func main() { + var y, counter int + var f []func() + defer func() { + for _, ff := range f { + ff() + } + }() + + { + LABEL_1: + if counter == 2 { + return + } + x := y + f = append(f, func() { println(x) }) + y++ + counter++ + goto LABEL_1 + } +} + +// Preprocessed: +// file{ package main; func main() { var y, counter (const-type int); var f []func(); defer func func(){ for _, ff := range f { ff() } }(); { if counter == (const (2 int)) { return }; x := y; f = (const (append func(x []func()(),args ...func()())(res []func()())))(f, func func(){ (const (println func(xs ...interface{})()))(x<~VPBlock(1,0)>) }>); y++; counter++; goto LABEL_1<0,0> } } } + +// Output: +// 0 +// 1 diff --git a/gnovm/tests/files/heap_alloc_gotoloop9_19.gno b/gnovm/tests/files/heap_alloc_gotoloop9_19.gno new file mode 100644 index 00000000000..fb1b995372e --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop9_19.gno @@ -0,0 +1,30 @@ +package main + +func main() { + var y, counter int + var f []func() func() int + defer func() { + for _, ff := range f { + println(ff()()) + } + }() + +LABEL_1: + if counter == 2 { + return + } + x := y + f = append(f, func() func() int { + return func() int { return x } + }) + y++ + counter++ + goto LABEL_1 +} + +// Preprocessed: +// file{ package main; func main() { var y, counter (const-type int); var f []func() func() (const-type int); defer func func(){ for _, ff := range f { (const (println func(xs ...interface{})()))(ff()()) } }(); if counter == (const (2 int)) { return }; x := y; f = (const (append func(x []func()( func()( int)),args ...func()( func()( int)))(res []func()( func()( int)))))(f, func func() func() (const-type int){ return func func() (const-type int){ return x<~VPBlock(2,1)> } }>); y++; counter++; goto LABEL_1<0,3> } } + +// Output: +// 0 +// 1 diff --git a/gnovm/tests/files/heap_alloc_gotoloop9_20.gno b/gnovm/tests/files/heap_alloc_gotoloop9_20.gno new file mode 100644 index 00000000000..04896b425a5 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop9_20.gno @@ -0,0 +1,32 @@ +package main + +func main() { + var y, counter int + var f []func() (int, func() int) + defer func() { + for _, ff := range f { + n, f := ff() + println(n + f()) + } + }() + +LABEL_1: + if counter == 2 { + return + } + x := y + z := y + f = append(f, func() (int, func() int) { + return z, func() int { return x } + }) + y++ + counter++ + goto LABEL_1 +} + +// Preprocessed: +// file{ package main; func main() { var y, counter (const-type int); var f []func() (const-type int), func() (const-type int); defer func func(){ for _, ff := range f { n, f := ff(); (const (println func(xs ...interface{})()))(n + f()) } }(); if counter == (const (2 int)) { return }; x := y; z := y; f = (const (append func(x []func()( int, func()( int)),args ...func()( int, func()( int)))(res []func()( int, func()( int)))))(f, func func() (const-type int), func() (const-type int){ return z<~VPBlock(1,2)>, func func() (const-type int){ return x<~VPBlock(2,3)> } }, x<()~VPBlock(1,3)>>); y++; counter++; goto LABEL_1<0,3> } } + +// Output: +// 0 +// 2 diff --git a/gnovm/tests/files/heap_alloc_gotoloop9_21.gno b/gnovm/tests/files/heap_alloc_gotoloop9_21.gno new file mode 100644 index 00000000000..fa27f3376e0 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop9_21.gno @@ -0,0 +1,31 @@ +package main + +func main() { + var counter int + var f []func() + defer func() { + for _, ff := range f { + ff() + } + }() + + f1 := func() { + LABEL_1: + if counter == 2 { + return + } + x := counter + f = append(f, func() { println(x) }) + counter++ + goto LABEL_1 + } + + f1() +} + +// Preprocessed: +// file{ package main; func main() { var counter (const-type int); var f []func(); defer func func(){ for _, ff := range f { ff() } }(); f1 := func func(){ if counter == (const (2 int)) { return }; x := counter; f = (const (append func(x []func()(),args ...func()())(res []func()())))(f, func func(){ (const (println func(xs ...interface{})()))(x<~VPBlock(1,0)>) }>); counter++; goto LABEL_1<0,0> }; f1() } } + +// Output: +// 0 +// 1 diff --git a/gnovm/tests/files/heap_alloc_gotoloop9_21a.gno b/gnovm/tests/files/heap_alloc_gotoloop9_21a.gno new file mode 100644 index 00000000000..48364ed4075 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop9_21a.gno @@ -0,0 +1,33 @@ +package main + +func main() { + var counter int + var f []func() + defer func() { + for _, ff := range f { + ff() + } + }() + + f1 := func() { + LABEL_1: + if counter == 2 { + return + } + x := counter + func() { + f = append(f, func() { println(x) }) + }() + counter++ + goto LABEL_1 + } + + f1() +} + +// Preprocessed: +// file{ package main; func main() { var counter (const-type int); var f []func(); defer func func(){ for _, ff := range f { ff() } }(); f1 := func func(){ if counter == (const (2 int)) { return }; x := counter; func func(){ f = (const (append func(x []func()(),args ...func()())(res []func()())))(f, func func(){ (const (println func(xs ...interface{})()))(x<~VPBlock(2,0)>) }) }>(); counter++; goto LABEL_1<0,0> }; f1() } } + +// Output: +// 0 +// 1 diff --git a/gnovm/tests/files/heap_alloc_gotoloop9_21b.gno b/gnovm/tests/files/heap_alloc_gotoloop9_21b.gno new file mode 100644 index 00000000000..8758608a5e6 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop9_21b.gno @@ -0,0 +1,34 @@ +package main + +func main() { + var counter int + var f []func() + defer func() { + for _, ff := range f { + ff() + } + }() + + f1 := func() { + LABEL_1: + if counter == 2 { + return + } + + func() { + x := counter + f = append(f, func() { println(x) }) + }() + counter++ + goto LABEL_1 + } + + f1() +} + +// Preprocessed: +// file{ package main; func main() { var counter (const-type int); var f []func(); defer func func(){ for _, ff := range f { ff() } }(); f1 := func func(){ if counter == (const (2 int)) { return }; func func(){ x := counter; f = (const (append func(x []func()(),args ...func()())(res []func()())))(f, func func(){ (const (println func(xs ...interface{})()))(x) }) }(); counter++; goto LABEL_1<0,0> }; f1() } } + +// Output: +// 0 +// 1 diff --git a/gnovm/tests/files/heap_alloc_gotoloop9_22.gno b/gnovm/tests/files/heap_alloc_gotoloop9_22.gno new file mode 100644 index 00000000000..cd283345869 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_gotoloop9_22.gno @@ -0,0 +1,33 @@ +package main + +func main() { + var y, counter int + var f []func() + defer func() { + for _, ff := range f { + ff() + } + }() + + for i := 0; i < 2; i++ { + counter = 0 + LABEL_1: + if counter == 2 { + continue + } + x := y + f = append(f, func() { println(x) }) + y++ + counter++ + goto LABEL_1 + } +} + +// Preprocessed: +// file{ package main; func main() { var y, counter (const-type int); var f []func(); defer func func(){ for _, ff := range f { ff() } }(); for i := (const (0 int)); i < (const (2 int)); i++ { counter = (const (0 int)); if counter == (const (2 int)) { continue }; x := y; f = (const (append func(x []func()(),args ...func()())(res []func()())))(f, func func(){ (const (println func(xs ...interface{})()))(x<~VPBlock(1,0)>) }>); y++; counter++; goto LABEL_1<0,1> } } } + +// Output: +// 0 +// 1 +// 2 +// 3 diff --git a/gnovm/tests/files/heap_alloc_range1.gno b/gnovm/tests/files/heap_alloc_range1.gno new file mode 100644 index 00000000000..34520729a06 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_range1.gno @@ -0,0 +1,30 @@ +package main + +import "fmt" + +var s1 []*int + +func forLoopRef() { + defer func() { + for i, e := range s1 { + fmt.Printf("s1[%d] is: %d\n", i, *e) + } + }() + + s := []int{0, 1, 2} + for i, _ := range s { + s1 = append(s1, &i) + } +} + +func main() { + forLoopRef() +} + +// Preprocessed: +// file{ package main; import fmt fmt; var s1 []*((const-type int)); func forLoopRef() { defer func func(){ for i, e := range s1 { fmt.Printf((const ("s1[%d] is: %d\n" string)), (const-type gonative{interface {}})(i), (const-type gonative{interface {}})(*(e))) } }(); s := [](const-type int){(const (0 int)), (const (1 int)), (const (2 int))}; for i, _ := range s { s1 = (const (append func(x []*int,args ...*int)(res []*int)))(s1, &(i)) } }; func main() { forLoopRef() } } + +// Output: +// s1[0] is: 2 +// s1[1] is: 2 +// s1[2] is: 2 diff --git a/gnovm/tests/files/heap_alloc_range2.gno b/gnovm/tests/files/heap_alloc_range2.gno new file mode 100644 index 00000000000..34b7cc527af --- /dev/null +++ b/gnovm/tests/files/heap_alloc_range2.gno @@ -0,0 +1,30 @@ +package main + +import "fmt" + +var s1 []*int + +func forLoopRef() { + defer func() { + for i, e := range s1 { + fmt.Printf("s1[%d] is: %d\n", i, *e) + } + }() + + s := []int{0, 1, 2} + for _, v := range s { + s1 = append(s1, &v) + } +} + +func main() { + forLoopRef() +} + +// Preprocessed: +// file{ package main; import fmt fmt; var s1 []*((const-type int)); func forLoopRef() { defer func func(){ for i, e := range s1 { fmt.Printf((const ("s1[%d] is: %d\n" string)), (const-type gonative{interface {}})(i), (const-type gonative{interface {}})(*(e))) } }(); s := [](const-type int){(const (0 int)), (const (1 int)), (const (2 int))}; for _, v := range s { s1 = (const (append func(x []*int,args ...*int)(res []*int)))(s1, &(v)) } }; func main() { forLoopRef() } } + +// Output: +// s1[0] is: 2 +// s1[1] is: 2 +// s1[2] is: 2 diff --git a/gnovm/tests/files/heap_alloc_range3.gno b/gnovm/tests/files/heap_alloc_range3.gno new file mode 100644 index 00000000000..032d0cf8b6d --- /dev/null +++ b/gnovm/tests/files/heap_alloc_range3.gno @@ -0,0 +1,23 @@ +package main + +func main() { + s := []int{1, 2} + + f := func() { + for i, v := range s { + println(i) + println(v) + } + } + + f() +} + +// Preprocessed: +// file{ package main; func main() { s := [](const-type int){(const (1 int)), (const (2 int))}; f := func func(){ for i, v := range s { (const (println func(xs ...interface{})()))(i); (const (println func(xs ...interface{})()))(v) } }; f() } } + +// Output: +// 0 +// 1 +// 1 +// 2 diff --git a/gnovm/tests/files/heap_alloc_range4.gno b/gnovm/tests/files/heap_alloc_range4.gno new file mode 100644 index 00000000000..2418184caca --- /dev/null +++ b/gnovm/tests/files/heap_alloc_range4.gno @@ -0,0 +1,24 @@ +package main + +func main() { + var fns []func() int + s := []int{1, 2, 3} + for i, _ := range s { + x := i + f := func() int { + return x + } + fns = append(fns, f) + } + for _, fn := range fns { + println(fn()) + } +} + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); s := [](const-type int){(const (1 int)), (const (2 int)), (const (3 int))}; for i, _ := range s { x := i; f := func func() (const-type int){ return x<~VPBlock(1,1)> }>; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Output: +// 0 +// 1 +// 2 diff --git a/gnovm/tests/files/heap_alloc_range4a.gno b/gnovm/tests/files/heap_alloc_range4a.gno new file mode 100644 index 00000000000..229d59d6011 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_range4a.gno @@ -0,0 +1,26 @@ +package main + +func main() { + var fns []func() int + m := map[string]int{"a": 1, "b": 2} + for _, v := range m { + x := v + f := func() int { + if true { + return x + } + return 0 + } + fns = append(fns, f) + } + for _, fn := range fns { + println(fn()) + } +} + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); m := map[(const-type string)] (const-type int){(const ("a" string)): (const (1 int)), (const ("b" string)): (const (2 int))}; for _, v := range m { x := v; f := func func() (const-type int){ if (const (true bool)) { return x<~VPBlock(2,1)> }; return (const (0 int)) }>; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Output: +// 1 +// 2 diff --git a/gnovm/tests/files/heap_alloc_range4a1.gno b/gnovm/tests/files/heap_alloc_range4a1.gno new file mode 100644 index 00000000000..7b126b0e530 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_range4a1.gno @@ -0,0 +1,22 @@ +package main + +func main() { + var fns []func() int + m := map[string]int{"a": 1, "b": 2} + for _, v := range m { + f := func() int { + return v + } + fns = append(fns, f) + } + for _, fn := range fns { + println(fn()) + } +} + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); m := map[(const-type string)] (const-type int){(const ("a" string)): (const (1 int)), (const ("b" string)): (const (2 int))}; for _, v := range m { f := func func() (const-type int){ return v }; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Output: +// 2 +// 2 diff --git a/gnovm/tests/files/heap_alloc_range4a2.gno b/gnovm/tests/files/heap_alloc_range4a2.gno new file mode 100644 index 00000000000..c54450f4619 --- /dev/null +++ b/gnovm/tests/files/heap_alloc_range4a2.gno @@ -0,0 +1,32 @@ +package main + +func main() { + var fns []func() int + y := 0 + m := map[string]int{"a": 1, "b": 2} + for _, v := range m { + x := v + f := func() int { + switch y { + case 0: + if true { + return x + } + default: + return 0 + } + return 0 + } + fns = append(fns, f) + } + for _, fn := range fns { + println(fn()) + } +} + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); y := (const (0 int)); m := map[(const-type string)] (const-type int){(const ("a" string)): (const (1 int)), (const ("b" string)): (const (2 int))}; for _, v := range m { x := v; f := func func() (const-type int){ switch y { case (const (0 int)): if (const (true bool)) { return x<~VPBlock(3,1)> }; default: return (const (0 int)) }; return (const (0 int)) }>; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Output: +// 1 +// 2 diff --git a/gnovm/tests/files/heap_alloc_range4b.gno b/gnovm/tests/files/heap_alloc_range4b.gno new file mode 100644 index 00000000000..b4a380b361b --- /dev/null +++ b/gnovm/tests/files/heap_alloc_range4b.gno @@ -0,0 +1,26 @@ +package main + +func main() { + var fns []func() int + s := "hello" + for i, _ := range s { + x := i + f := func() int { + return x + } + fns = append(fns, f) + } + for _, fn := range fns { + println(fn()) + } +} + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); s := (const ("hello" string)); for i, _ := range s { x := i; f := func func() (const-type int){ return x<~VPBlock(1,1)> }>; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Output: +// 0 +// 1 +// 2 +// 3 +// 4 diff --git a/gnovm/tests/files/heap_alloc_range4b1.gno b/gnovm/tests/files/heap_alloc_range4b1.gno new file mode 100644 index 00000000000..24dd99ea98f --- /dev/null +++ b/gnovm/tests/files/heap_alloc_range4b1.gno @@ -0,0 +1,25 @@ +package main + +func main() { + var fns []func() int + s := "hello" + for i, _ := range s { + f := func() int { + return i + } + fns = append(fns, f) + } + for _, fn := range fns { + println(fn()) + } +} + +// Preprocessed: +// file{ package main; func main() { var fns []func() (const-type int); s := (const ("hello" string)); for i, _ := range s { f := func func() (const-type int){ return i }; fns = (const (append func(x []func()( int),args ...func()( int))(res []func()( int))))(fns, f) }; for _, fn := range fns { (const (println func(xs ...interface{})()))(fn()) } } } + +// Output: +// 4 +// 4 +// 4 +// 4 +// 4 diff --git a/gnovm/tests/files/import6.gno b/gnovm/tests/files/import6.gno index 6909e1ad923..f3cd9930eb5 100644 --- a/gnovm/tests/files/import6.gno +++ b/gnovm/tests/files/import6.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// github.com/gnolang/gno/_test/c2/c2.gno:3:1: import cycle detected: "github.com/gnolang/gno/_test/c1" (through [github.com/gnolang/gno/_test/c1 github.com/gnolang/gno/_test/c2]) +// github.com/gnolang/gno/_test/c2/c2.gno:3:8: import cycle detected: "github.com/gnolang/gno/_test/c1" (through [github.com/gnolang/gno/_test/c1 github.com/gnolang/gno/_test/c2]) diff --git a/gnovm/tests/files/ptr10.gno b/gnovm/tests/files/ptr10.gno new file mode 100644 index 00000000000..807fc149808 --- /dev/null +++ b/gnovm/tests/files/ptr10.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(*nil) +} + +// Error: +// main/files/ptr10.gno:4:10: invalid operation: cannot indirect nil diff --git a/gnovm/tests/files/ptr9.gno b/gnovm/tests/files/ptr9.gno new file mode 100644 index 00000000000..6e104942d81 --- /dev/null +++ b/gnovm/tests/files/ptr9.gno @@ -0,0 +1,9 @@ +package main + +func main() { + v := 1 + println(*v) +} + +// Error: +// main/files/ptr9.gno:5:10: invalid operation: cannot indirect v (variable of type int) diff --git a/gnovm/tests/files/recursive1.gno b/gnovm/tests/files/recursive1.gno index 8279e247d84..cd86d351dec 100644 --- a/gnovm/tests/files/recursive1.gno +++ b/gnovm/tests/files/recursive1.gno @@ -10,4 +10,4 @@ func main() { } // Error: -// main/files/recursive1.gno:1:1: invalid recursive type: S -> S +// main/files/recursive1.gno:3:6: invalid recursive type: S -> S diff --git a/gnovm/tests/files/recursive1c.gno b/gnovm/tests/files/recursive1c.gno index 7797f375027..36237b039c0 100644 --- a/gnovm/tests/files/recursive1c.gno +++ b/gnovm/tests/files/recursive1c.gno @@ -14,4 +14,4 @@ func main() { } // Error: -// main/files/recursive1c.gno:1:1: invalid recursive type: S -> S +// main/files/recursive1c.gno:5:6: invalid recursive type: S -> S diff --git a/gnovm/tests/files/recursive1d.gno b/gnovm/tests/files/recursive1d.gno index 22bf172b5ac..11c48bed3eb 100644 --- a/gnovm/tests/files/recursive1d.gno +++ b/gnovm/tests/files/recursive1d.gno @@ -14,4 +14,4 @@ func main() { } // Error: -// main/files/recursive1d.gno:1:1: invalid recursive type: S -> S +// main/files/recursive1d.gno:5:6: invalid recursive type: S -> S diff --git a/gnovm/tests/files/recursive1f.gno b/gnovm/tests/files/recursive1f.gno index 81fe2a5699c..7c6bc8f52fe 100644 --- a/gnovm/tests/files/recursive1f.gno +++ b/gnovm/tests/files/recursive1f.gno @@ -10,4 +10,4 @@ func main() { } // Error: -// main/files/recursive1f.gno:3:1: invalid recursive type: S -> S +// main/files/recursive1f.gno:4:7: invalid recursive type: S -> S diff --git a/gnovm/tests/files/recursive2.gno b/gnovm/tests/files/recursive2.gno index 4ed86f03d58..f2382d7ce1a 100644 --- a/gnovm/tests/files/recursive2.gno +++ b/gnovm/tests/files/recursive2.gno @@ -18,4 +18,4 @@ func main() { } // Error: -// main/files/recursive2.gno:1:1: invalid recursive type: A -> B -> C -> A +// main/files/recursive2.gno:3:6: invalid recursive type: A -> B -> C -> A diff --git a/gnovm/tests/files/recursive2c.gno b/gnovm/tests/files/recursive2c.gno index 3b5c27ed8ea..d6068fba1bc 100644 --- a/gnovm/tests/files/recursive2c.gno +++ b/gnovm/tests/files/recursive2c.gno @@ -18,4 +18,4 @@ func main() { } // Error: -// main/files/recursive2c.gno:3:1: name B not defined in fileset with files [files/recursive2c.gno] +// main/files/recursive2c.gno:4:7: name B not defined in fileset with files [files/recursive2c.gno] diff --git a/gnovm/tests/files/recursive4a.gno b/gnovm/tests/files/recursive4a.gno index 8b4d13b4785..3d2b4e33590 100644 --- a/gnovm/tests/files/recursive4a.gno +++ b/gnovm/tests/files/recursive4a.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/recursive4a.gno:1:1: invalid recursive type: time -> time +// main/files/recursive4a.gno:3:6: invalid recursive type: time -> time diff --git a/gnovm/tests/files/recursive5.gno b/gnovm/tests/files/recursive5.gno index 1c2fbd89fb8..1498926f305 100644 --- a/gnovm/tests/files/recursive5.gno +++ b/gnovm/tests/files/recursive5.gno @@ -10,4 +10,4 @@ func main() { } // Error: -// main/files/recursive5.gno:1:1: invalid recursive type: S -> S +// main/files/recursive5.gno:3:6: invalid recursive type: S -> S diff --git a/gnovm/tests/files/recursive6a.gno b/gnovm/tests/files/recursive6a.gno index 8123fc626a5..a0791aca7f5 100644 --- a/gnovm/tests/files/recursive6a.gno +++ b/gnovm/tests/files/recursive6a.gno @@ -9,4 +9,4 @@ func main() { } // Error: -// main/files/recursive6a.gno:1:1: invalid recursive type: SelfReferencing -> SelfReferencing +// main/files/recursive6a.gno:3:6: invalid recursive type: SelfReferencing -> SelfReferencing diff --git a/gnovm/tests/files/recursive7a.gno b/gnovm/tests/files/recursive7a.gno index b3c57516f13..b27a3a01324 100644 --- a/gnovm/tests/files/recursive7a.gno +++ b/gnovm/tests/files/recursive7a.gno @@ -5,4 +5,4 @@ type S [2]S func main() {} // Error: -// main/files/recursive7a.gno:1:1: invalid recursive type: S -> S +// main/files/recursive7a.gno:3:6: invalid recursive type: S -> S diff --git a/gnovm/tests/files/recursive8.gno b/gnovm/tests/files/recursive8.gno index 1f9325ae35c..afd5b44fcc6 100644 --- a/gnovm/tests/files/recursive8.gno +++ b/gnovm/tests/files/recursive8.gno @@ -5,4 +5,4 @@ type Int Int func main() {} // Error: -// main/files/recursive8.gno:1:1: invalid recursive type: Int -> Int +// main/files/recursive8.gno:3:6: invalid recursive type: Int -> Int diff --git a/gnovm/tests/files/recursive9.gno b/gnovm/tests/files/recursive9.gno index 8181be55d33..3b930ee248d 100644 --- a/gnovm/tests/files/recursive9.gno +++ b/gnovm/tests/files/recursive9.gno @@ -5,4 +5,4 @@ type Int = Int func main() {} // Error: -// main/files/recursive9.gno:1:1: invalid recursive type: Int -> Int +// main/files/recursive9.gno:3:6: invalid recursive type: Int -> Int diff --git a/gnovm/tests/files/recursive9a.gno b/gnovm/tests/files/recursive9a.gno index b96efa090e4..acd11893bad 100644 --- a/gnovm/tests/files/recursive9a.gno +++ b/gnovm/tests/files/recursive9a.gno @@ -5,4 +5,4 @@ type Int = *Int func main() {} // Error: -// main/files/recursive9a.gno:1:1: invalid recursive type: Int -> Int \ No newline at end of file +// main/files/recursive9a.gno:3:6: invalid recursive type: Int -> Int diff --git a/gnovm/tests/files/recursive9b.gno b/gnovm/tests/files/recursive9b.gno index e033349d597..3901099ec60 100644 --- a/gnovm/tests/files/recursive9b.gno +++ b/gnovm/tests/files/recursive9b.gno @@ -5,4 +5,4 @@ type Int = func() Int func main() {} // Error: -// main/files/recursive9b.gno:1:1: invalid recursive type: Int -> Int \ No newline at end of file +// main/files/recursive9b.gno:3:6: invalid recursive type: Int -> Int diff --git a/gnovm/tests/files/recursive9c.gno b/gnovm/tests/files/recursive9c.gno index ad865978920..bf08d406dc2 100644 --- a/gnovm/tests/files/recursive9c.gno +++ b/gnovm/tests/files/recursive9c.gno @@ -5,4 +5,4 @@ type Int = []Int func main() {} // Error: -// main/files/recursive9c.gno:1:1: invalid recursive type: Int -> Int +// main/files/recursive9c.gno:3:6: invalid recursive type: Int -> Int diff --git a/gnovm/tests/files/recursive9d.gno b/gnovm/tests/files/recursive9d.gno index ae7310ede0f..7ea4c934c65 100644 --- a/gnovm/tests/files/recursive9d.gno +++ b/gnovm/tests/files/recursive9d.gno @@ -7,4 +7,4 @@ type S = struct { func main() {} // Error: -// main/files/recursive9d.gno:1:1: invalid recursive type: S -> S +// main/files/recursive9d.gno:3:6: invalid recursive type: S -> S diff --git a/gnovm/tests/files/redeclaration10.gno b/gnovm/tests/files/redeclaration10.gno index 01584b1755c..afbf3c6a607 100644 --- a/gnovm/tests/files/redeclaration10.gno +++ b/gnovm/tests/files/redeclaration10.gno @@ -6,7 +6,5 @@ func main() { println("should not happen") } -// XXX show what was redeclared. - // Error: -// running package "github.com/gnolang/gno/_test/redeclaration3": duplicate declarations not allowed +// running package "github.com/gnolang/gno/_test/redeclaration3": redeclarations for identifiers: "a.method" diff --git a/gnovm/tests/files/redeclaration6.gno b/gnovm/tests/files/redeclaration6.gno index 25e36fa61aa..74e762604ba 100644 --- a/gnovm/tests/files/redeclaration6.gno +++ b/gnovm/tests/files/redeclaration6.gno @@ -6,7 +6,5 @@ func main() { println("should not happen") } -// XXX show what was redeclared. - // Error: -// running package "github.com/gnolang/gno/_test/redeclaration1": duplicate declarations not allowed +// running package "github.com/gnolang/gno/_test/redeclaration1": redeclarations for identifiers: "a" diff --git a/gnovm/tests/files/redeclaration8.gno b/gnovm/tests/files/redeclaration8.gno index d0e5b958030..51c8871a4f2 100644 --- a/gnovm/tests/files/redeclaration8.gno +++ b/gnovm/tests/files/redeclaration8.gno @@ -6,7 +6,5 @@ func main() { println("should not happen") } -// XXX show what was redeclared. - // Error: -// running package "github.com/gnolang/gno/_test/redeclaration2": duplicate declarations not allowed +// running package "github.com/gnolang/gno/_test/redeclaration2": redeclarations for identifiers: "a" diff --git a/gnovm/tests/files/redefine.gno b/gnovm/tests/files/redefine.gno new file mode 100644 index 00000000000..62eea61f25e --- /dev/null +++ b/gnovm/tests/files/redefine.gno @@ -0,0 +1,15 @@ +package main + +var ss = []int{1, 2, 3} + +func main() { + for _, s := range ss { + s := s + println(s) + } +} + +// Output: +// 1 +// 2 +// 3 diff --git a/gnovm/tests/files/redefine2.gno b/gnovm/tests/files/redefine2.gno new file mode 100644 index 00000000000..b0621fe2a03 --- /dev/null +++ b/gnovm/tests/files/redefine2.gno @@ -0,0 +1,25 @@ +package main + +var testTable = []struct { + name string +}{ + { + "one", + }, + { + "two", + }, +} + +func main() { + + for _, testCase := range testTable { + testCase := testCase + + println(testCase.name) + } +} + +// Output: +// one +// two diff --git a/gnovm/tests/files/redefine3.gno b/gnovm/tests/files/redefine3.gno new file mode 100644 index 00000000000..7a2d0859f5c --- /dev/null +++ b/gnovm/tests/files/redefine3.gno @@ -0,0 +1,13 @@ +package main + +func main() { + for i := 0; i < 3; i++ { + i := i + println(i) + } +} + +// Output: +// 0 +// 1 +// 2 diff --git a/gnovm/tests/files/redefine4.gno b/gnovm/tests/files/redefine4.gno new file mode 100644 index 00000000000..db310fae3c2 --- /dev/null +++ b/gnovm/tests/files/redefine4.gno @@ -0,0 +1,15 @@ +package main + +func main() { + a := 1 + b := 3 + println(a, b) // prints 1 3 + + // Re-declaration of 'a' is allowed because 'c' is a new variable + a, c := 2, 5 + println(a, c) // prints 2 5 +} + +// Output: +// 1 3 +// 2 5 diff --git a/gnovm/tests/files/redefine5.gno b/gnovm/tests/files/redefine5.gno new file mode 100644 index 00000000000..9637df913f0 --- /dev/null +++ b/gnovm/tests/files/redefine5.gno @@ -0,0 +1,18 @@ +package main + +func main() { + a := 1 + println(a) // prints 1 + + if true { + a := 2 // valid: new scope inside the if statement + println(a) // prints 2 + } + + println(a) // prints 1: outer variable is unchanged +} + +// Output: +// 1 +// 2 +// 1 diff --git a/gnovm/tests/files/redefine6.gno b/gnovm/tests/files/redefine6.gno new file mode 100644 index 00000000000..ff5ca97d063 --- /dev/null +++ b/gnovm/tests/files/redefine6.gno @@ -0,0 +1,9 @@ +package main + +func main() { + a, b := 1, 2 + a, b := 3, 4 +} + +// Error: +// files/redefine6.gno:5:2: no new variables on left side of := diff --git a/gnovm/tests/files/stdbanker_stdlibs.gno b/gnovm/tests/files/stdbanker_stdlibs.gno new file mode 100644 index 00000000000..d0872dd38e6 --- /dev/null +++ b/gnovm/tests/files/stdbanker_stdlibs.gno @@ -0,0 +1,13 @@ +package main + +import "std" + +func main() { + defer func() { + println(recover()) + }() + std.TestSetRealm(std.NewCodeRealm("gno.land/p/demo/users")) +} + +// Output: +// should only be called for Realms diff --git a/gnovm/tests/files/switch13.gno b/gnovm/tests/files/switch13.gno index b2223c85256..f69f09d1037 100644 --- a/gnovm/tests/files/switch13.gno +++ b/gnovm/tests/files/switch13.gno @@ -14,4 +14,4 @@ func main() { } // Error: -// main/files/switch13.gno:0:0: i is not a type +// main/files/switch13.gno:8:0: i is not a type diff --git a/gnovm/tests/files/types/assign_literal11.gno b/gnovm/tests/files/types/assign_literal11.gno index 851fe74593d..ab916e4c752 100644 --- a/gnovm/tests/files/types/assign_literal11.gno +++ b/gnovm/tests/files/types/assign_literal11.gno @@ -8,4 +8,4 @@ func main() { } // Error: -// main/files/types/assign_literal11.gno:6:2: cannot assign to (const (3.14 bigdec)) +// main/files/types/assign_literal11.gno:6:2: cannot assign to const Pi diff --git a/gnovm/tests/files/types/assign_literal3.gno b/gnovm/tests/files/types/assign_literal3.gno index e4a4441853d..ce051b0dcbb 100644 --- a/gnovm/tests/files/types/assign_literal3.gno +++ b/gnovm/tests/files/types/assign_literal3.gno @@ -5,4 +5,4 @@ func main() { } // Error: -// main/files/types/assign_literal3.gno:4:2: cannot assign to (const (true bool)) +// main/files/types/assign_literal3.gno:4:2: cannot assign to uverse true diff --git a/gnovm/tests/files/types/assign_nil.gno b/gnovm/tests/files/types/assign_nil.gno index 8c756da3b60..ecbca26dad0 100644 --- a/gnovm/tests/files/types/assign_nil.gno +++ b/gnovm/tests/files/types/assign_nil.gno @@ -8,4 +8,4 @@ func main() { } // Error: -// main/files/types/assign_nil.gno:7:2: cannot assign to (const (undefined)) +// main/files/types/assign_nil.gno:7:2: cannot assign to uverse nil diff --git a/gnovm/tests/files/types/assign_nil2.gno b/gnovm/tests/files/types/assign_nil2.gno index fd7d509fccc..a1559d9de1f 100644 --- a/gnovm/tests/files/types/assign_nil2.gno +++ b/gnovm/tests/files/types/assign_nil2.gno @@ -8,4 +8,4 @@ func main() { } // Error: -// main/files/types/assign_nil2.gno:7:2: cannot assign to (const (undefined)) +// main/files/types/assign_nil2.gno:7:2: cannot assign to uverse nil diff --git a/gnovm/tests/files/types/cmp_slice.gno b/gnovm/tests/files/types/cmp_slice.gno new file mode 100644 index 00000000000..bd926979844 --- /dev/null +++ b/gnovm/tests/files/types/cmp_slice.gno @@ -0,0 +1,14 @@ +package main + +func main() { + // test against uninitialized value: https://github.com/gnolang/gno/pull/1132 + var x string + y := "Hello" + results := [...]bool{ + x < y, + } + println(results) +} + +// Output: +// array[(true bool)] diff --git a/gnovm/tests/files/types/explicit_conversion_0.gno b/gnovm/tests/files/types/explicit_conversion_0.gno new file mode 100644 index 00000000000..ac5e8c2eb94 --- /dev/null +++ b/gnovm/tests/files/types/explicit_conversion_0.gno @@ -0,0 +1,13 @@ +package main + +import "fmt" + +func main() { + r := int(uint(1)) + println(r) + fmt.Printf("%T \n", r) +} + +// Output: +// 1 +// int diff --git a/gnovm/tests/files/types/explicit_conversion_1.gno b/gnovm/tests/files/types/explicit_conversion_1.gno new file mode 100644 index 00000000000..60fc7b95b64 --- /dev/null +++ b/gnovm/tests/files/types/explicit_conversion_1.gno @@ -0,0 +1,13 @@ +package main + +import "fmt" + +// case of const in type call +func main() { + r := int(uint(string("hello"))) + println(r) + fmt.Printf("%T \n", r) +} + +// Error: +// main/files/types/explicit_conversion_1.gno:7:11: cannot convert StringKind to UintKind diff --git a/gnovm/tests/files/types/explicit_conversion_2.gno b/gnovm/tests/files/types/explicit_conversion_2.gno new file mode 100644 index 00000000000..f932a970a9a --- /dev/null +++ b/gnovm/tests/files/types/explicit_conversion_2.gno @@ -0,0 +1,14 @@ +package main + +import "fmt" + +func main() { + x := 1 + r := uint(+x) + println(r) + fmt.Printf("%T \n", r) +} + +// Output: +// 1 +// uint diff --git a/gnovm/tests/files/types/explicit_conversion_4.gno b/gnovm/tests/files/types/explicit_conversion_4.gno new file mode 100644 index 00000000000..e510b33bf69 --- /dev/null +++ b/gnovm/tests/files/types/explicit_conversion_4.gno @@ -0,0 +1,9 @@ +package main + +func main() { + x := 1 + println(uint(+x)) +} + +// Output: +// 1 diff --git a/gnovm/tests/files/types/explicit_conversion_5.gno b/gnovm/tests/files/types/explicit_conversion_5.gno new file mode 100644 index 00000000000..49cfd8f85f5 --- /dev/null +++ b/gnovm/tests/files/types/explicit_conversion_5.gno @@ -0,0 +1,9 @@ +package main + +func main() { + x := int(1) + println(uint(x)) +} + +// Output: +// 1 diff --git a/gnovm/tests/files/types/shift_a11.gno b/gnovm/tests/files/types/shift_a11.gno index 2fbcb86b682..17593ecfa21 100644 --- a/gnovm/tests/files/types/shift_a11.gno +++ b/gnovm/tests/files/types/shift_a11.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/types/shift_a11.gno:3:1: cannot convert StringKind to UintKind +// main/files/types/shift_a11.gno:5:7: cannot convert (const ("hello" string)) to type uint diff --git a/gnovm/tests/files/types/shift_a2.gno b/gnovm/tests/files/types/shift_a2.gno index 91072929306..726d5415b15 100644 --- a/gnovm/tests/files/types/shift_a2.gno +++ b/gnovm/tests/files/types/shift_a2.gno @@ -1,6 +1,5 @@ package main -// both typed(different) const func main() { println(1 << int(1)) println(1 >> int(1)) diff --git a/gnovm/tests/files/types/shift_a4.gno b/gnovm/tests/files/types/shift_a4.gno index 3561929b672..694d771f190 100644 --- a/gnovm/tests/files/types/shift_a4.gno +++ b/gnovm/tests/files/types/shift_a4.gno @@ -1,6 +1,5 @@ package main -// both typed(different) const func main() { println(1 << 1.0) println(1 >> 1.0) diff --git a/gnovm/tests/files/types/shift_a5.gno b/gnovm/tests/files/types/shift_a5.gno index a0b7652c6d1..5d2c4304732 100644 --- a/gnovm/tests/files/types/shift_a5.gno +++ b/gnovm/tests/files/types/shift_a5.gno @@ -1,10 +1,10 @@ package main -// TODO: support this? func main() { println(1.0 << 1) println(1.0 >> 1) } -// Error: -// main/files/types/shift_a5.gno:5:10: operator << not defined on: BigdecKind +// Output: +// 2 +// 0 diff --git a/gnovm/tests/files/types/shift_a7.gno b/gnovm/tests/files/types/shift_a7.gno index 62151c5cfc5..cd1b3d95ec7 100644 --- a/gnovm/tests/files/types/shift_a7.gno +++ b/gnovm/tests/files/types/shift_a7.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/shift_a7.gno:3:1: cannot convert StringKind to UintKind +// main/files/types/shift_a7.gno:5:10: cannot convert (const ("a" string)) to type uint diff --git a/gnovm/tests/files/types/shift_b0.gno b/gnovm/tests/files/types/shift_b0.gno new file mode 100644 index 00000000000..fa9ee4ed2a0 --- /dev/null +++ b/gnovm/tests/files/types/shift_b0.gno @@ -0,0 +1,14 @@ +package main + +import "fmt" + +func main() { + x := 2 + r := uint64(1 << x) + println(r) + fmt.Printf("%T \n", r) +} + +// Output: +// 4 +// uint64 diff --git a/gnovm/tests/files/types/shift_b1.gno b/gnovm/tests/files/types/shift_b1.gno new file mode 100644 index 00000000000..403887269c0 --- /dev/null +++ b/gnovm/tests/files/types/shift_b1.gno @@ -0,0 +1,14 @@ +package main + +import "fmt" + +func main() { + x := 2 + r := uint64(1< bigint does not implement main.R (missing method foo) diff --git a/gnovm/tests/files/types/shift_b6a.gno b/gnovm/tests/files/types/shift_b6a.gno new file mode 100644 index 00000000000..26b7f1b2ea1 --- /dev/null +++ b/gnovm/tests/files/types/shift_b6a.gno @@ -0,0 +1,31 @@ +package main + +import "fmt" + +type R interface { + foo() +} + +type U64 uint64 + +func (u64 U64) foo() { + println("bar") +} + +func bar(r R) { + r.foo() +} + +func main() { + x := 2 + var r R + r = U64(1) << x + + r.foo() + + fmt.Printf("%T \n", r) // TODO: should output main.U64 rather than the underlying type +} + +// Output: +// bar +// uint64 diff --git a/gnovm/tests/files/types/shift_b7.gno b/gnovm/tests/files/types/shift_b7.gno new file mode 100644 index 00000000000..ccc6cd41b7f --- /dev/null +++ b/gnovm/tests/files/types/shift_b7.gno @@ -0,0 +1,13 @@ +package main + +import "fmt" + +func main() { + x := 2 + r := float32(1<>2) +} + +// Output: +// 4 0 diff --git a/gnovm/tests/files/types/shift_c3.gno b/gnovm/tests/files/types/shift_c3.gno new file mode 100644 index 00000000000..6ca9a8b7cc2 --- /dev/null +++ b/gnovm/tests/files/types/shift_c3.gno @@ -0,0 +1,14 @@ +package main + +import "fmt" + +func main() { + x := 1 + r := uint(+(1 << x)) + println(r) + fmt.Printf("%T \n", r) +} + +// Output: +// 2 +// uint diff --git a/gnovm/tests/files/types/shift_c4.gno b/gnovm/tests/files/types/shift_c4.gno new file mode 100644 index 00000000000..55b5fa782d7 --- /dev/null +++ b/gnovm/tests/files/types/shift_c4.gno @@ -0,0 +1,14 @@ +package main + +import "fmt" + +func main() { + x := 63 + r := int32(+(1<>x) +} + +// Output: +// uint64 +// int64 +// 2048 +// 0 diff --git a/gnovm/tests/files/types/shift_d12.gno b/gnovm/tests/files/types/shift_d12.gno new file mode 100644 index 00000000000..3d8c6e3de16 --- /dev/null +++ b/gnovm/tests/files/types/shift_d12.gno @@ -0,0 +1,16 @@ +package main + +import "fmt" + +func foo(a uint64, b float32) { + fmt.Printf("%T \n", a) + println(a) +} + +func main() { + x := 11 + foo(1<>x) +} + +// Error: +// main/files/types/shift_d12.gno:12:2: operator >> not defined on: Float32Kind diff --git a/gnovm/tests/files/types/shift_d13.gno b/gnovm/tests/files/types/shift_d13.gno new file mode 100644 index 00000000000..0ab495c1a26 --- /dev/null +++ b/gnovm/tests/files/types/shift_d13.gno @@ -0,0 +1,17 @@ +package main + +import "fmt" + +// it's like assign +func foo(a uint64, b float32) { + fmt.Printf("%T \n", a) + println(a) +} + +func main() { + x := 11 + foo(1<>x) +} + +// Error: +// main/files/types/shift_d13.gno:13:2: cannot use int as float32 diff --git a/gnovm/tests/files/types/shift_d14.gno b/gnovm/tests/files/types/shift_d14.gno new file mode 100644 index 00000000000..8458cf94ffb --- /dev/null +++ b/gnovm/tests/files/types/shift_d14.gno @@ -0,0 +1,18 @@ +package main + +import "fmt" + +// it's like assign +func foo(a uint64, b int64) { + fmt.Printf("%T\n", a) + println(a) +} + +func main() { + x := 11 + foo(1<>x) +} + +// Output: +// uint64 +// 2048 diff --git a/gnovm/tests/files/types/shift_d15.gno b/gnovm/tests/files/types/shift_d15.gno new file mode 100644 index 00000000000..a29108aef5a --- /dev/null +++ b/gnovm/tests/files/types/shift_d15.gno @@ -0,0 +1,10 @@ +package main + +func main() { + x := 64 + y := uint64(1 << x) + println(y) +} + +// Output: +// 0 diff --git a/gnovm/tests/files/types/shift_d16.gno b/gnovm/tests/files/types/shift_d16.gno new file mode 100644 index 00000000000..3b7fb0aec50 --- /dev/null +++ b/gnovm/tests/files/types/shift_d16.gno @@ -0,0 +1,10 @@ +package main + +func main() { + x := 64 + y := uint64(1<>2) //special case with == !=, untyped bool + println(r) +} + +// Error: +// main/files/types/shift_d4.gno:4:7: cannot convert BoolKind to Uint64Kind diff --git a/gnovm/tests/files/types/shift_d40.gno b/gnovm/tests/files/types/shift_d40.gno new file mode 100644 index 00000000000..8840f8b7322 --- /dev/null +++ b/gnovm/tests/files/types/shift_d40.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := 2 + s := []float32{1 << a} + println(s[0]) +} + +// Error: +// main/files/types/shift_d40.gno:5:7: operator << not defined on: Float32Kind diff --git a/gnovm/tests/files/types/shift_d41.gno b/gnovm/tests/files/types/shift_d41.gno new file mode 100644 index 00000000000..bf46da524f7 --- /dev/null +++ b/gnovm/tests/files/types/shift_d41.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := 2 + s := map[string]float32{"k": 1 << a} + println(s["k"]) +} + +// Error: +// main/files/types/shift_d41.gno:5:7: operator << not defined on: Float32Kind diff --git a/gnovm/tests/files/types/shift_d42.gno b/gnovm/tests/files/types/shift_d42.gno new file mode 100644 index 00000000000..c2bbfe94e2b --- /dev/null +++ b/gnovm/tests/files/types/shift_d42.gno @@ -0,0 +1,14 @@ +package main + +func main() { + type S struct { + a float32 + } + s := S{ + a: 1 << 2, + } + println(s.a) +} + +// Output: +// 4 diff --git a/gnovm/tests/files/types/shift_d43.gno b/gnovm/tests/files/types/shift_d43.gno new file mode 100644 index 00000000000..e9b0032ac9a --- /dev/null +++ b/gnovm/tests/files/types/shift_d43.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := 2 + s := map[string]interface{}{"k": 1 << a} + println(s["k"]) +} + +// Output: +// 4 diff --git a/gnovm/tests/files/types/shift_d44.gno b/gnovm/tests/files/types/shift_d44.gno new file mode 100644 index 00000000000..0ef024f1e6b --- /dev/null +++ b/gnovm/tests/files/types/shift_d44.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := 1 + b := 1 + (a == b)++ // LHS is untyped bool, determined in preprocess +} + +// Error: +// main/files/types/shift_d44.gno:6:2: operator ++ not defined on: BoolKind diff --git a/gnovm/tests/files/types/shift_d45.gno b/gnovm/tests/files/types/shift_d45.gno new file mode 100644 index 00000000000..5c504d7d616 --- /dev/null +++ b/gnovm/tests/files/types/shift_d45.gno @@ -0,0 +1,10 @@ +package main + +func main() { + x := 11 + y := uint64(1 << x) + println(y) +} + +// Output: +// 2048 diff --git a/gnovm/tests/files/types/shift_d46.gno b/gnovm/tests/files/types/shift_d46.gno new file mode 100644 index 00000000000..8490c751c88 --- /dev/null +++ b/gnovm/tests/files/types/shift_d46.gno @@ -0,0 +1,10 @@ +package main + +func main() { + x := 11 + y := uint64(1.0 << x) + println(y) +} + +// Output: +// 2048 diff --git a/gnovm/tests/files/types/shift_d47.gno b/gnovm/tests/files/types/shift_d47.gno new file mode 100644 index 00000000000..d50c3944e90 --- /dev/null +++ b/gnovm/tests/files/types/shift_d47.gno @@ -0,0 +1,26 @@ +package main + +var specialBytes [16]byte + +func main() { + for i, b := range []byte(`\.+*?()|[]{}^$`) { + specialBytes[b%16] |= 1 << (b / 16) + println(i, (1 << (b / 16)), specialBytes[b%16]) + } +} + +// Output: +// 0 32 32 +// 1 4 4 +// 2 4 4 +// 3 4 4 +// 4 8 8 +// 5 4 4 +// 6 4 4 +// 7 128 160 +// 8 32 36 +// 9 32 32 +// 10 128 164 +// 11 128 160 +// 12 32 36 +// 13 4 4 diff --git a/gnovm/tests/files/types/shift_d48.gno b/gnovm/tests/files/types/shift_d48.gno new file mode 100644 index 00000000000..2ec6782c7f0 --- /dev/null +++ b/gnovm/tests/files/types/shift_d48.gno @@ -0,0 +1,23 @@ +package main + +import ( + "github.com/gnolang/gno/_test/net/http" +) + +type extendedRequest struct { + Request http.Request + + Data string +} + +func main() { + r := extendedRequest{} + // req := &r.Request + + println(r) + // XXX removed temporarily until recursion detection implemented for sprintString(). + // println(req) +} + +// Output: +// (struct{(struct{( string),( string),(0 int),(0 int),(nil github.com/gnolang/gno/_test/net/http.Header),(undefined),(0 int64),(nil []string),(false bool),( string),(nil github.com/gnolang/gno/_test/net/http.Values),(nil github.com/gnolang/gno/_test/net/http.Values),(nil github.com/gnolang/gno/_test/net/http.Header),( string),( string),(nil *github.com/gnolang/gno/_test/net/http.Response)} github.com/gnolang/gno/_test/net/http.Request),( string)} main.extendedRequest) diff --git a/gnovm/tests/files/types/shift_d4a.gno b/gnovm/tests/files/types/shift_d4a.gno new file mode 100644 index 00000000000..803da33ea64 --- /dev/null +++ b/gnovm/tests/files/types/shift_d4a.gno @@ -0,0 +1,9 @@ +package main + +func main() { + r := string(1<<2 == 1>>2) //special case with == !=, untyped bool + println(r) +} + +// Error: +// main/files/types/shift_d4a.gno:4:7: cannot convert BoolKind to StringKind diff --git a/gnovm/tests/files/types/shift_d5.gno b/gnovm/tests/files/types/shift_d5.gno new file mode 100644 index 00000000000..43c0e117f5e --- /dev/null +++ b/gnovm/tests/files/types/shift_d5.gno @@ -0,0 +1,10 @@ +package main + +func main() { + x := 11 + y := 1.0 << x // no const + println(y) +} + +// Error: +// main/files/types/shift_d5.gno:5:2: operator << not defined on: Float64Kind diff --git a/gnovm/tests/files/types/shift_d50.gno b/gnovm/tests/files/types/shift_d50.gno new file mode 100644 index 00000000000..fec552e48d7 --- /dev/null +++ b/gnovm/tests/files/types/shift_d50.gno @@ -0,0 +1,13 @@ +package main + +import "fmt" + +func main() { + x := 11 + y := uint64(-(1.0 << 2) << x) + println(y) + fmt.Printf("%T \n", y) +} + +// Error: +// main/files/types/shift_d50.gno:7:7: bigint underflows target kind diff --git a/gnovm/tests/files/types/shift_d51.gno b/gnovm/tests/files/types/shift_d51.gno new file mode 100644 index 00000000000..bd2b432479f --- /dev/null +++ b/gnovm/tests/files/types/shift_d51.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := 1.0 + a <<= 1 + println(a) +} + +// Error: +// main/files/types/shift_d51.gno:5:2: operator <<= not defined on: Float64Kind diff --git a/gnovm/tests/files/types/shift_d52.gno b/gnovm/tests/files/types/shift_d52.gno new file mode 100644 index 00000000000..f998381ef1c --- /dev/null +++ b/gnovm/tests/files/types/shift_d52.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := 1 + a <<= 1 + println(a) +} + +// Output: +// 2 diff --git a/gnovm/tests/files/types/shift_d53.gno b/gnovm/tests/files/types/shift_d53.gno new file mode 100644 index 00000000000..575dc1e146b --- /dev/null +++ b/gnovm/tests/files/types/shift_d53.gno @@ -0,0 +1,12 @@ +package main + +import "fmt" + +func main() { + a := 1 // a is inferred as int + b := a << 3 // b is also int + fmt.Printf("%T, %T, %d, %d \n", a, b, a, b) +} + +// Output: +// int, int, 1, 8 diff --git a/gnovm/tests/files/types/shift_d54.gno b/gnovm/tests/files/types/shift_d54.gno new file mode 100644 index 00000000000..13266f44379 --- /dev/null +++ b/gnovm/tests/files/types/shift_d54.gno @@ -0,0 +1,14 @@ +package main + +import "fmt" + +func main() { + a := 5 // infer type int + var b int32 = 10 + c := b + a<<2 + + fmt.Printf("%T, %d \n", c, c) +} + +// Error: +// main/files/types/shift_d54.gno:8:7: invalid operation: mismatched types int32 and int diff --git a/gnovm/tests/files/types/shift_d55.gno b/gnovm/tests/files/types/shift_d55.gno new file mode 100644 index 00000000000..58628376421 --- /dev/null +++ b/gnovm/tests/files/types/shift_d55.gno @@ -0,0 +1,16 @@ +package main + +import "fmt" + +func shiftReturn() int64 { + return 1 << 4 // The shift result is cast to int64 +} + +func main() { + r := shiftReturn() + + fmt.Printf("%T, %d \n", r, r) +} + +// Output: +// int64, 16 diff --git a/gnovm/tests/files/types/shift_d56.gno b/gnovm/tests/files/types/shift_d56.gno new file mode 100644 index 00000000000..3f734bb993e --- /dev/null +++ b/gnovm/tests/files/types/shift_d56.gno @@ -0,0 +1,16 @@ +package main + +import "fmt" + +func shiftReturn() int64 { + return 1<<4 + int(1) // The shift result is cast to int64 +} + +func main() { + r := shiftReturn() + + fmt.Printf("%T, %d \n", r, r) +} + +// Error: +// main/files/types/shift_d56.gno:6:2: cannot use int as int64 diff --git a/gnovm/tests/files/types/shift_d5a.gno b/gnovm/tests/files/types/shift_d5a.gno new file mode 100644 index 00000000000..8490c751c88 --- /dev/null +++ b/gnovm/tests/files/types/shift_d5a.gno @@ -0,0 +1,10 @@ +package main + +func main() { + x := 11 + y := uint64(1.0 << x) + println(y) +} + +// Output: +// 2048 diff --git a/gnovm/tests/files/types/shift_d5b.gno b/gnovm/tests/files/types/shift_d5b.gno new file mode 100644 index 00000000000..8c04105a450 --- /dev/null +++ b/gnovm/tests/files/types/shift_d5b.gno @@ -0,0 +1,10 @@ +package main + +func main() { + x := 11 + y := float32(1.0 << x) + println(y) +} + +// Error: +// main/files/types/shift_d5b.gno:5:7: operator << not defined on: Float32Kind diff --git a/gnovm/tests/files/types/shift_d6.gno b/gnovm/tests/files/types/shift_d6.gno new file mode 100644 index 00000000000..e2ce1d02157 --- /dev/null +++ b/gnovm/tests/files/types/shift_d6.gno @@ -0,0 +1,18 @@ +package main + +import "fmt" + +func main() { + x := 11 + y := 1 << x + println(y) + fmt.Printf("%T\n", y) + fmt.Printf("%T\n", 1) + fmt.Printf("%T\n", x) +} + +// Output: +// 2048 +// int +// int +// int diff --git a/gnovm/tests/files/types/shift_d9.gno b/gnovm/tests/files/types/shift_d9.gno new file mode 100644 index 00000000000..e766e5e218d --- /dev/null +++ b/gnovm/tests/files/types/shift_d9.gno @@ -0,0 +1,9 @@ +package main + +func main() { + r := bool(1<<2+1 == 1>>2) + println(r) +} + +// Output: +// false diff --git a/gnovm/tests/files/types/shift_e0.gno b/gnovm/tests/files/types/shift_e0.gno new file mode 100644 index 00000000000..d5b75063d3e --- /dev/null +++ b/gnovm/tests/files/types/shift_e0.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(1 << -1) +} + +// Error: +// main/files/types/shift_e0.gno:4:10: invalid operation: negative shift count: (const (-1 bigint)) diff --git a/gnovm/tests/files/types/shift_e1.gno b/gnovm/tests/files/types/shift_e1.gno new file mode 100644 index 00000000000..343dee1f933 --- /dev/null +++ b/gnovm/tests/files/types/shift_e1.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(1.0 << float32(2.58485848)) +} + +// Error: +// main/files/types/shift_e1.gno:4:10: invalid operation: invalid shift count: (const (2.5848584 float32)) diff --git a/gnovm/tests/files/types/shift_e1a.gno b/gnovm/tests/files/types/shift_e1a.gno new file mode 100644 index 00000000000..bb6bedd2016 --- /dev/null +++ b/gnovm/tests/files/types/shift_e1a.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(1.0 << 2.0) +} + +// Output: +// 4 diff --git a/gnovm/tests/files/types/shift_e2.gno b/gnovm/tests/files/types/shift_e2.gno new file mode 100644 index 00000000000..192d5c1b3e9 --- /dev/null +++ b/gnovm/tests/files/types/shift_e2.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(1 << 1.25) +} + +// Error: +// main/files/types/shift_e2.gno:4:10: invalid operation: invalid shift count: (const (1.25 bigdec)) diff --git a/gnovm/tests/files/types/shift_e3.gno b/gnovm/tests/files/types/shift_e3.gno new file mode 100644 index 00000000000..81c803897c7 --- /dev/null +++ b/gnovm/tests/files/types/shift_e3.gno @@ -0,0 +1,9 @@ +package main + +func main() { + x := 1.25 + println(1 << x) +} + +// Error: +// main/files/types/shift_e3.gno:5:10: invalid operation: invalid shift count: x diff --git a/gnovm/tests/files/types/shift_e4.gno b/gnovm/tests/files/types/shift_e4.gno new file mode 100644 index 00000000000..02746eb04fe --- /dev/null +++ b/gnovm/tests/files/types/shift_e4.gno @@ -0,0 +1,9 @@ +package main + +func main() { + x := 1.25 + println(1 << x) +} + +// Error: +// main/files/types/shift_e4.gno:5:10: invalid operation: invalid shift count: x \ No newline at end of file diff --git a/gnovm/tests/files/types/shift_e5.gno b/gnovm/tests/files/types/shift_e5.gno new file mode 100644 index 00000000000..acd351bd50d --- /dev/null +++ b/gnovm/tests/files/types/shift_e5.gno @@ -0,0 +1,9 @@ +package main + +func main() { + x := -1 + println(1 << x) +} + +// Error: +// runtime error: negative shift amount: (-1 int) diff --git a/gnovm/tests/files/types/shift_e6.gno b/gnovm/tests/files/types/shift_e6.gno new file mode 100644 index 00000000000..43cb2464132 --- /dev/null +++ b/gnovm/tests/files/types/shift_e6.gno @@ -0,0 +1,9 @@ +package main + +func main() { + x := -1 + println(1 >> x) +} + +// Error: +// runtime error: negative shift amount: (-1 int) diff --git a/gnovm/tests/files/types/shift_e7.gno b/gnovm/tests/files/types/shift_e7.gno new file mode 100644 index 00000000000..c7d8aded350 --- /dev/null +++ b/gnovm/tests/files/types/shift_e7.gno @@ -0,0 +1,9 @@ +package main + +func main() { + y := 1 + y <<= -1 +} + +// Error: +// main/files/types/shift_e7.gno:5:2: invalid operation: negative shift count: (-1 bigint) diff --git a/gnovm/tests/files/types/shift_e7a.gno b/gnovm/tests/files/types/shift_e7a.gno new file mode 100644 index 00000000000..2e81fc102bc --- /dev/null +++ b/gnovm/tests/files/types/shift_e7a.gno @@ -0,0 +1,9 @@ +package main + +func main() { + a := float64(-100) + println(1 << a) +} + +// Error: +// main/files/types/shift_e7a.gno:5:10: invalid operation: invalid shift count: a diff --git a/gnovm/tests/files/types/shift_e7b.gno b/gnovm/tests/files/types/shift_e7b.gno new file mode 100644 index 00000000000..80766d2928e --- /dev/null +++ b/gnovm/tests/files/types/shift_e7b.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(1 << float64(-1)) +} + +// Error: +// main/files/types/shift_e7b.gno:4:10: invalid operation: invalid shift count: (const (-1 float64)) diff --git a/gnovm/tests/files/types/shift_e8.gno b/gnovm/tests/files/types/shift_e8.gno new file mode 100644 index 00000000000..1940dd9b8fb --- /dev/null +++ b/gnovm/tests/files/types/shift_e8.gno @@ -0,0 +1,9 @@ +package main + +func main() { + y := 1 + y <<= 1.25 +} + +// Error: +// main/files/types/shift_e8.gno:5:2: invalid operation: invalid shift count: (const (1.25 bigdec)) diff --git a/gnovm/tests/files/types/shift_e9.gno b/gnovm/tests/files/types/shift_e9.gno new file mode 100644 index 00000000000..2bd408860f2 --- /dev/null +++ b/gnovm/tests/files/types/shift_e9.gno @@ -0,0 +1,11 @@ +package main + +func main() { + x := -1 + y := 1 + y <<= x + println(y) +} + +// Error: +// runtime error: negative shift amount: (-1 int) diff --git a/gnovm/tests/files/types/shift_e9a.gno b/gnovm/tests/files/types/shift_e9a.gno new file mode 100644 index 00000000000..03ce9343948 --- /dev/null +++ b/gnovm/tests/files/types/shift_e9a.gno @@ -0,0 +1,11 @@ +package main + +func main() { + x := -1 + y := 1 + y >>= x + println(y) +} + +// Error: +// runtime error: negative shift amount: (-1 int) diff --git a/gnovm/tests/files/types/shift_f1a.gno b/gnovm/tests/files/types/shift_f1a.gno new file mode 100644 index 00000000000..ca35144bacc --- /dev/null +++ b/gnovm/tests/files/types/shift_f1a.gno @@ -0,0 +1,12 @@ +package main + +func main() { + var s uint = 33 + + var u1 bool + u1 = 1< bigint NEQ bigdec diff --git a/gnovm/tests/files/types/shift_f2e.gno b/gnovm/tests/files/types/shift_f2e.gno new file mode 100644 index 00000000000..dec0a2a6626 --- /dev/null +++ b/gnovm/tests/files/types/shift_f2e.gno @@ -0,0 +1,10 @@ +package main + +func main() { + var s uint = 33 + var u2 = 1.0< +// main/files/var18.gno:4:6: missing init expr for c diff --git a/gnovm/tests/files/var19.gno b/gnovm/tests/files/var19.gno index 99d7452f603..2856d6cd05a 100644 --- a/gnovm/tests/files/var19.gno +++ b/gnovm/tests/files/var19.gno @@ -1,12 +1,11 @@ package main func main() { - var a, b, c = 1, a+1 - + var a, b, c = 1, a + 1 println(a) println(b) println(c) } // Error: -// main/files/var19.gno:4:6: missing init expr for c +// main/files/var19.gno:4:6: missing init expr for c diff --git a/gnovm/tests/files/var22.gno b/gnovm/tests/files/var22.gno index 3f85f0f156d..5b21f7aa5bc 100644 --- a/gnovm/tests/files/var22.gno +++ b/gnovm/tests/files/var22.gno @@ -11,4 +11,4 @@ func main() { } // Error: -// main/files/var22.gno:8:6: missing init expr for c +// main/files/var22.gno:8:6: missing init expr for c diff --git a/gnovm/tests/imports.go b/gnovm/tests/imports.go index 30f410fa8d5..66398ba5f50 100644 --- a/gnovm/tests/imports.go +++ b/gnovm/tests/imports.go @@ -222,23 +222,23 @@ func TestStore(rootDir, filesPath string, stdin io.Reader, stdout, stderr io.Wri return pkg, pkg.NewPackage() case "time": pkg := gno.NewPackageNode("time", pkgPath, nil) - pkg.DefineGoNativeValue("Millisecond", time.Millisecond) - pkg.DefineGoNativeValue("Second", time.Second) - pkg.DefineGoNativeValue("Minute", time.Minute) - pkg.DefineGoNativeValue("Hour", time.Hour) - pkg.DefineGoNativeValue("Date", time.Date) - pkg.DefineGoNativeValue("Now", func() time.Time { return time.Unix(0, 0).UTC() }) // deterministic - pkg.DefineGoNativeValue("January", time.January) - pkg.DefineGoNativeValue("February", time.February) - pkg.DefineGoNativeValue("March", time.March) - pkg.DefineGoNativeValue("April", time.April) - pkg.DefineGoNativeValue("May", time.May) - pkg.DefineGoNativeValue("June", time.June) - pkg.DefineGoNativeValue("July", time.July) - pkg.DefineGoNativeValue("August", time.August) - pkg.DefineGoNativeValue("September", time.September) - pkg.DefineGoNativeValue("November", time.November) - pkg.DefineGoNativeValue("December", time.December) + pkg.DefineGoNativeConstValue("Millisecond", time.Millisecond) + pkg.DefineGoNativeConstValue("Second", time.Second) + pkg.DefineGoNativeConstValue("Minute", time.Minute) + pkg.DefineGoNativeConstValue("Hour", time.Hour) + pkg.DefineGoNativeConstValue("Date", time.Date) + pkg.DefineGoNativeConstValue("Now", func() time.Time { return time.Unix(0, 0).UTC() }) // deterministic + pkg.DefineGoNativeConstValue("January", time.January) + pkg.DefineGoNativeConstValue("February", time.February) + pkg.DefineGoNativeConstValue("March", time.March) + pkg.DefineGoNativeConstValue("April", time.April) + pkg.DefineGoNativeConstValue("May", time.May) + pkg.DefineGoNativeConstValue("June", time.June) + pkg.DefineGoNativeConstValue("July", time.July) + pkg.DefineGoNativeConstValue("August", time.August) + pkg.DefineGoNativeConstValue("September", time.September) + pkg.DefineGoNativeConstValue("November", time.November) + pkg.DefineGoNativeConstValue("December", time.December) pkg.DefineGoNativeValue("UTC", time.UTC) pkg.DefineGoNativeValue("Unix", time.Unix) pkg.DefineGoNativeType(reflect.TypeOf(time.Time{})) @@ -246,6 +246,15 @@ func TestStore(rootDir, filesPath string, stdin io.Reader, stdout, stderr io.Wri pkg.DefineGoNativeType(reflect.TypeOf(time.Month(0))) pkg.DefineGoNativeValue("LoadLocation", time.LoadLocation) return pkg, pkg.NewPackage() + case "strconv": + pkg := gno.NewPackageNode("strconv", pkgPath, nil) + pkg.DefineGoNativeValue("Itoa", strconv.Itoa) + pkg.DefineGoNativeValue("Atoi", strconv.Atoi) + pkg.DefineGoNativeValue("ParseInt", strconv.ParseInt) + pkg.DefineGoNativeValue("Quote", strconv.Quote) + pkg.DefineGoNativeValue("FormatUint", strconv.FormatUint) + pkg.DefineGoNativeType(reflect.TypeOf(strconv.NumError{})) + return pkg, pkg.NewPackage() case "strings": pkg := gno.NewPackageNode("strings", pkgPath, nil) pkg.DefineGoNativeValue("Split", strings.Split) @@ -263,21 +272,20 @@ func TestStore(rootDir, filesPath string, stdin io.Reader, stdout, stderr io.Wri pkg := gno.NewPackageNode("math", pkgPath, nil) pkg.DefineGoNativeValue("Abs", math.Abs) pkg.DefineGoNativeValue("Cos", math.Cos) - pkg.DefineGoNativeValue("Pi", math.Pi) + pkg.DefineGoNativeConstValue("Pi", math.Pi) pkg.DefineGoNativeValue("Float64bits", math.Float64bits) - pkg.DefineGoNativeValue("Pi", math.Pi) - pkg.DefineGoNativeValue("MaxFloat32", math.MaxFloat32) - pkg.DefineGoNativeValue("MaxFloat64", math.MaxFloat64) - pkg.DefineGoNativeValue("MaxUint32", uint32(math.MaxUint32)) - pkg.DefineGoNativeValue("MaxUint64", uint64(math.MaxUint64)) - pkg.DefineGoNativeValue("MinInt8", math.MinInt8) - pkg.DefineGoNativeValue("MinInt16", math.MinInt16) - pkg.DefineGoNativeValue("MinInt32", math.MinInt32) - pkg.DefineGoNativeValue("MinInt64", int64(math.MinInt64)) - pkg.DefineGoNativeValue("MaxInt8", math.MaxInt8) - pkg.DefineGoNativeValue("MaxInt16", math.MaxInt16) - pkg.DefineGoNativeValue("MaxInt32", math.MaxInt32) - pkg.DefineGoNativeValue("MaxInt64", int64(math.MaxInt64)) + pkg.DefineGoNativeConstValue("MaxFloat32", math.MaxFloat32) + pkg.DefineGoNativeConstValue("MaxFloat64", math.MaxFloat64) + pkg.DefineGoNativeConstValue("MaxUint32", uint32(math.MaxUint32)) + pkg.DefineGoNativeConstValue("MaxUint64", uint64(math.MaxUint64)) + pkg.DefineGoNativeConstValue("MinInt8", math.MinInt8) + pkg.DefineGoNativeConstValue("MinInt16", math.MinInt16) + pkg.DefineGoNativeConstValue("MinInt32", math.MinInt32) + pkg.DefineGoNativeConstValue("MinInt64", int64(math.MinInt64)) + pkg.DefineGoNativeConstValue("MaxInt8", math.MaxInt8) + pkg.DefineGoNativeConstValue("MaxInt16", math.MaxInt16) + pkg.DefineGoNativeConstValue("MaxInt32", math.MaxInt32) + pkg.DefineGoNativeConstValue("MaxInt64", int64(math.MaxInt64)) return pkg, pkg.NewPackage() case "math/rand": // XXX only expose for tests. @@ -312,13 +320,13 @@ func TestStore(rootDir, filesPath string, stdin io.Reader, stdout, stderr io.Wri return pkg, pkg.NewPackage() case "compress/flate": pkg := gno.NewPackageNode("flate", pkgPath, nil) - pkg.DefineGoNativeValue("BestSpeed", flate.BestSpeed) + pkg.DefineGoNativeConstValue("BestSpeed", flate.BestSpeed) return pkg, pkg.NewPackage() case "compress/gzip": pkg := gno.NewPackageNode("gzip", pkgPath, nil) pkg.DefineGoNativeType(reflect.TypeOf(gzip.Writer{})) - pkg.DefineGoNativeValue("BestCompression", gzip.BestCompression) - pkg.DefineGoNativeValue("BestSpeed", gzip.BestSpeed) + pkg.DefineGoNativeConstValue("BestCompression", gzip.BestCompression) + pkg.DefineGoNativeConstValue("BestSpeed", gzip.BestSpeed) return pkg, pkg.NewPackage() case "context": pkg := gno.NewPackageNode("context", pkgPath, nil) @@ -418,7 +426,6 @@ func TestStore(rootDir, filesPath string, stdin io.Reader, stdout, stderr io.Wri resStore = gno.NewStore(nil, baseStore, iavlStore) resStore.SetPackageGetter(getPackage) resStore.SetNativeStore(teststdlibs.NativeStore) - resStore.SetPackageInjector(testPackageInjector) resStore.SetStrictGo2GnoMapping(false) return } @@ -465,19 +472,6 @@ func loadStdlib(rootDir, pkgPath string, store gno.Store, stdout io.Writer) (*gn return m2.RunMemPackageWithOverrides(memPkg, save) } -func testPackageInjector(store gno.Store, pn *gno.PackageNode) { - // Test specific injections: - switch pn.PkgPath { - case "strconv": - // NOTE: Itoa and Atoi are already injected - // from stdlibs.InjectNatives. - pn.DefineGoNativeType(reflect.TypeOf(strconv.NumError{})) - pn.DefineGoNativeValue("ParseInt", strconv.ParseInt) - } -} - -// ---------------------------------------- - type dummyReader struct{} func (*dummyReader) Read(b []byte) (n int, err error) { diff --git a/gnovm/tests/integ/several-files-multiple-errors/file2.gno b/gnovm/tests/integ/several-files-multiple-errors/file2.gno new file mode 100644 index 00000000000..39ec59973ef --- /dev/null +++ b/gnovm/tests/integ/several-files-multiple-errors/file2.gno @@ -0,0 +1,5 @@ +package main + +type{ + +} \ No newline at end of file diff --git a/gnovm/tests/integ/several-files-multiple-errors/gno.mod b/gnovm/tests/integ/several-files-multiple-errors/gno.mod new file mode 100644 index 00000000000..88485411822 --- /dev/null +++ b/gnovm/tests/integ/several-files-multiple-errors/gno.mod @@ -0,0 +1 @@ +module gno.land/tests/severalerrors \ No newline at end of file diff --git a/gnovm/tests/integ/several-files-multiple-errors/main.gno b/gnovm/tests/integ/several-files-multiple-errors/main.gno new file mode 100644 index 00000000000..f29aa7ecd33 --- /dev/null +++ b/gnovm/tests/integ/several-files-multiple-errors/main.gno @@ -0,0 +1,6 @@ +package main + +func main() { + for { + _ example +} \ No newline at end of file diff --git a/gnovm/tests/package_test.go b/gnovm/tests/package_test.go index 8e497941c7f..d4ddfc9a4f0 100644 --- a/gnovm/tests/package_test.go +++ b/gnovm/tests/package_test.go @@ -16,6 +16,8 @@ import ( ) func TestStdlibs(t *testing.T) { + t.Parallel() + // NOTE: this test only works using _test.gno files; // filetests are not meant to be used for testing standard libraries. // The examples directory is tested directly using `gno test`u @@ -51,6 +53,8 @@ func TestStdlibs(t *testing.T) { for _, pkgPath := range pkgPaths { testDir := testDirs[pkgPath] t.Run(pkgPath, func(t *testing.T) { + pkgPath := pkgPath + t.Parallel() runPackageTest(t, testDir, pkgPath) }) } diff --git a/gnovm/tests/stdlibs/generated.go b/gnovm/tests/stdlibs/generated.go index 23bb3cfa594..f3d74e214eb 100644 --- a/gnovm/tests/stdlibs/generated.go +++ b/gnovm/tests/stdlibs/generated.go @@ -296,6 +296,36 @@ var nativeFuncs = [...]NativeFunc{ )) }, }, + { + "std", + "isRealm", + []gno.FieldTypeExpr{ + {Name: gno.N("p0"), Type: gno.X("string")}, + }, + []gno.FieldTypeExpr{ + {Name: gno.N("r0"), Type: gno.X("bool")}, + }, + true, + func(m *gno.Machine) { + b := m.LastBlock() + var ( + p0 string + rp0 = reflect.ValueOf(&p0).Elem() + ) + + gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 0, "")).TV, rp0) + + r0 := testlibs_std.X_isRealm( + m, + p0) + + m.PushValue(gno.Go2GnoValue( + m.Alloc, + m.Store, + reflect.ValueOf(&r0).Elem(), + )) + }, + }, { "testing", "unixNano", diff --git a/gnovm/tests/stdlibs/std/frame_testing.gno b/gnovm/tests/stdlibs/std/frame_testing.gno index 171756c54f5..f9952969497 100644 --- a/gnovm/tests/stdlibs/std/frame_testing.gno +++ b/gnovm/tests/stdlibs/std/frame_testing.gno @@ -8,5 +8,8 @@ func NewUserRealm(user Address) Realm { // NewCodeRealm creates a new realm for a published code realm with the given // pkgPath. func NewCodeRealm(pkgPath string) Realm { + if !isRealm(pkgPath) { + panic("should only be called for Realms") + } return Realm{pkgPath: pkgPath, addr: DerivePkgAddr(pkgPath)} } diff --git a/gnovm/tests/stdlibs/std/std.gno b/gnovm/tests/stdlibs/std/std.gno index f583342ae04..3a56ecc1c47 100644 --- a/gnovm/tests/stdlibs/std/std.gno +++ b/gnovm/tests/stdlibs/std/std.gno @@ -38,3 +38,4 @@ func testSetOrigSend( spentDenom []string, spentAmt []int64) func testIssueCoins(addr string, denom []string, amt []int64) func getRealm(height int) (address string, pkgPath string) +func isRealm(pkgPath string) bool diff --git a/gnovm/tests/stdlibs/std/std.go b/gnovm/tests/stdlibs/std/std.go index 0421f359932..d580572e9c5 100644 --- a/gnovm/tests/stdlibs/std/std.go +++ b/gnovm/tests/stdlibs/std/std.go @@ -173,6 +173,10 @@ func X_getRealm(m *gno.Machine, height int) (address string, pkgPath string) { return string(ctx.OrigCaller), "" } +func X_isRealm(m *gno.Machine, pkgPath string) bool { + return gno.IsRealmPath(pkgPath) +} + func X_testSetOrigSend(m *gno.Machine, sentDenom []string, sentAmt []int64, spentDenom []string, spentAmt []int64, diff --git a/go.mod b/go.mod index d890ab020a4..24d09a87236 100644 --- a/go.mod +++ b/go.mod @@ -13,15 +13,12 @@ require ( github.com/davecgh/go-spew v1.1.1 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 github.com/fortytw2/leaktest v1.3.0 - github.com/gdamore/tcell/v2 v2.7.4 github.com/gnolang/overflow v0.0.0-20170615021017-4d914c927216 - github.com/golang/protobuf v1.5.4 github.com/google/gofuzz v1.2.0 github.com/gorilla/mux v1.8.1 github.com/gorilla/websocket v1.5.3 github.com/gotuna/gotuna v0.6.0 github.com/libp2p/go-buffer-pool v0.1.0 - github.com/mattn/go-runewidth v0.0.16 github.com/pelletier/go-toml v1.9.5 github.com/peterbourgon/ff/v3 v3.4.0 github.com/pmezard/go-difflib v1.0.0 @@ -47,24 +44,22 @@ require ( golang.org/x/sync v0.8.0 golang.org/x/term v0.23.0 golang.org/x/tools v0.24.0 - google.golang.org/protobuf v1.34.2 + google.golang.org/protobuf v1.35.1 gopkg.in/yaml.v3 v3.0.1 ) require ( github.com/cenkalti/backoff/v4 v4.3.0 // indirect - github.com/gdamore/encoding v1.0.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/securecookie v1.1.1 // indirect github.com/gorilla/sessions v1.2.1 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect - github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/nxadm/tail v1.4.11 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/rivo/uniseg v0.4.3 // indirect github.com/zondax/hid v0.9.2 // indirect github.com/zondax/ledger-go v0.14.3 // indirect go.opentelemetry.io/otel/trace v1.29.0 // indirect diff --git a/go.sum b/go.sum index 9495dd5b451..78d60eeea90 100644 --- a/go.sum +++ b/go.sum @@ -51,10 +51,6 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= -github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= -github.com/gdamore/tcell/v2 v2.7.4 h1:sg6/UnTM9jGpZU+oFYAsDahfchWAFW8Xx2yFinNSAYU= -github.com/gdamore/tcell/v2 v2.7.4/go.mod h1:dSXtXTSK0VsW1biw65DZLZ2NKr7j0qP/0J7ONmsraWg= github.com/gnolang/overflow v0.0.0-20170615021017-4d914c927216 h1:GKvsK3oLWG9B1GL7WP/VqwM6C92j5tIvB844oggL9Lk= github.com/gnolang/overflow v0.0.0-20170615021017-4d914c927216/go.mod h1:xJhtEL7ahjM1WJipt89gel8tHzfIl/LyMY+lCYh38d8= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -110,11 +106,6 @@ github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= -github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= -github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= -github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= -github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= @@ -136,9 +127,6 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw= -github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= @@ -156,7 +144,6 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw= @@ -190,30 +177,20 @@ 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-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY= golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -225,36 +202,19 @@ golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -270,8 +230,8 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/misc/autocounterd/Dockerfile b/misc/autocounterd/Dockerfile deleted file mode 100644 index d860fc5f37f..00000000000 --- a/misc/autocounterd/Dockerfile +++ /dev/null @@ -1,16 +0,0 @@ -FROM golang:alpine AS builder - -COPY . /go/src/github.com/gnolang/gno/misc/autocounterd - -WORKDIR /go/src/github.com/gnolang/gno/misc/autocounterd - -RUN go build -o /build/autocounterd ./cmd - -# Final image for autocounterd -FROM alpine AS autocounterd - -COPY --from=builder /build/autocounterd /usr/bin/autocounterd - -ENTRYPOINT [ "/usr/bin/autocounterd" ] -CMD [ "start" ] - diff --git a/misc/autocounterd/cmd/cmd_start.go b/misc/autocounterd/cmd/cmd_start.go index a32d01fa324..ecf70f750be 100644 --- a/misc/autocounterd/cmd/cmd_start.go +++ b/misc/autocounterd/cmd/cmd_start.go @@ -7,6 +7,7 @@ import ( "time" "github.com/gnolang/gno/gno.land/pkg/gnoclient" + "github.com/gnolang/gno/gno.land/pkg/sdk/vm" rpcclient "github.com/gnolang/gno/tm2/pkg/bft/rpc/client" "github.com/gnolang/gno/tm2/pkg/commands" ) @@ -73,7 +74,10 @@ func execStart(cfg *startCfg, args []string, io commands.IO) error { return err } - rpcClient := rpcclient.NewHTTP(cfg.rpcURL, "/websocket") + rpcClient, err := rpcclient.NewHTTPClient(cfg.rpcURL) + if err != nil { + return err + } client := gnoclient.Client{ Signer: signer, @@ -81,14 +85,16 @@ func execStart(cfg *startCfg, args []string, io commands.IO) error { } for { - res, err := client.Call(gnoclient.CallCfg{ - PkgPath: cfg.realmPath, - FuncName: "Incr", - GasFee: "10000000ugnot", - GasWanted: 800000, - Args: nil, - }) - _ = res + _, err := client.Call( + gnoclient.BaseTxCfg{ + GasFee: "10000000ugnot", + GasWanted: 800000, + }, + vm.MsgCall{ + PkgPath: cfg.realmPath, + Func: "Incr", + Args: nil, + }) if err != nil { fmt.Printf("[ERROR] Failed to call Incr on %s, %+v\n", cfg.realmPath, err.Error()) diff --git a/misc/autocounterd/docker-compose.yml b/misc/autocounterd/docker-compose.yml index d71e6997b51..49d1ad413f3 100644 --- a/misc/autocounterd/docker-compose.yml +++ b/misc/autocounterd/docker-compose.yml @@ -3,7 +3,8 @@ services: autocounterd: image: ghcr.io/gnolang/gno/autocounterd build: - context: . + context: ../.. + target: autocounterd restart: unless-stopped environment: COUNTER_MNEMONIC: "source bonus chronic canvas draft south burst lottery vacant surface solve popular case indicate oppose farm nothing bullet exhibit title speed wink action roast" diff --git a/misc/autocounterd/go.mod b/misc/autocounterd/go.mod index 12297e3c6ca..5de1d3c2974 100644 --- a/misc/autocounterd/go.mod +++ b/misc/autocounterd/go.mod @@ -1,54 +1,57 @@ -module loop +module autocounterd go 1.22 toolchain go1.22.4 -require github.com/gnolang/gno v0.0.0-20240125181217-b6193518e278 +require github.com/gnolang/gno v0.0.0-00010101000000-000000000000 require ( - dario.cat/mergo v1.0.0 // indirect - github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect - github.com/btcsuite/btcd/btcutil v1.1.3 // indirect - github.com/cespare/xxhash v1.1.0 // indirect - github.com/cespare/xxhash/v2 v2.1.1 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/btcsuite/btcd/btcutil v1.1.6 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cockroachdb/apd/v3 v3.2.1 // indirect + github.com/cosmos/ledger-cosmos-go v0.13.3 // 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 - github.com/dustin/go-humanize v1.0.0 // indirect - github.com/gnolang/goleveldb v0.0.9 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect github.com/gnolang/overflow v0.0.0-20170615021017-4d914c927216 // indirect - github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b // indirect - github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/golang/protobuf v1.5.4 // indirect 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/google/uuid v1.6.0 // indirect + github.com/gorilla/websocket v1.5.3 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // 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 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 - 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 + github.com/rs/xid v1.6.0 // indirect + github.com/stretchr/testify v1.9.0 // indirect + github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect + github.com/zondax/hid v0.9.2 // indirect + github.com/zondax/ledger-go v0.14.3 // indirect + go.opentelemetry.io/otel v1.29.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.29.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.29.0 // indirect + go.opentelemetry.io/otel/metric v1.29.0 // indirect + go.opentelemetry.io/otel/sdk v1.29.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.29.0 // indirect + go.opentelemetry.io/otel/trace v1.29.0 // indirect + go.opentelemetry.io/proto/otlp v1.3.1 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/crypto v0.26.0 // indirect + golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 // indirect + golang.org/x/mod v0.20.0 // indirect + golang.org/x/net v0.28.0 // indirect + golang.org/x/sys v0.24.0 // indirect + golang.org/x/term v0.23.0 // indirect + golang.org/x/text v0.17.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd // indirect + google.golang.org/grpc v1.65.0 // indirect + google.golang.org/protobuf v1.35.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) + +replace github.com/gnolang/gno => ../.. diff --git a/misc/autocounterd/go.sum b/misc/autocounterd/go.sum index 905c884857e..b34cbde0c00 100644 --- a/misc/autocounterd/go.sum +++ b/misc/autocounterd/go.sum @@ -1,27 +1,24 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= -dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= +dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= 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/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= -github.com/btcsuite/btcd v0.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= +github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= +github.com/btcsuite/btcd v0.24.2 h1:aLmxPguqxza+4ag8R1I2nnJjSu2iFn/kqtHTIImswcY= +github.com/btcsuite/btcd v0.24.2/go.mod h1:5C8ChTkl5ejr3WHj8tkQSCmydiMEPB0ZhQhehpq7Dgg= github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= -github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= -github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= -github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= -github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= +github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= +github.com/btcsuite/btcd/btcutil v1.1.6 h1:zFL2+c3Lb9gEgqKNzowKUPQNb8jV7v5Oaodi/AYFd6c= +github.com/btcsuite/btcd/btcutil v1.1.6/go.mod h1:9dFymx8HpuLqBnsPELrImQeTQfKBQqzqGbbV3jK55aE= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 h1:KdUfX2zKommPRa+PD0sWZUyXe9w277ABlgELO7H04IM= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= @@ -31,17 +28,12 @@ github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cockroachdb/apd/v3 v3.2.1 h1:U+8j7t0axsIgvQUqthuNm82HIrYXodOV2iWLWtEaIwg= github.com/cockroachdb/apd/v3 v3.2.1/go.mod h1:klXJcjp+FffLTHlhIG69tezTDvdP065naDsHzKhYSqc= -github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= -github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/cosmos/ledger-cosmos-go v0.13.3 h1:7ehuBGuyIytsXbd4MP43mLeoN2LTOEnk5nvue4rK+yM= +github.com/cosmos/ledger-cosmos-go v0.13.3/go.mod h1:HENcEP+VtahZFw38HZ3+LS3Iv5XV6svsnkk9vdJtLr8= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -50,98 +42,59 @@ github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= -github.com/dgraph-io/badger/v3 v3.2103.5 h1:ylPa6qzbjYRQMU6jokoj4wzcaweHylt//CH0AKt0akg= -github.com/dgraph-io/badger/v3 v3.2103.5/go.mod h1:4MPiseMeDQ3FNCYwRbbcBOGJLf5jsE0PPFzRiKjtcdw= -github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= -github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= -github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= -github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c h1:8ISkoahWXwZR41ois5lSJBSVw4D0OV19Ht/JSTzvSv0= -github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= -github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= -github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= -github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk= -github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/gnolang/gno v0.0.0-20240125181217-b6193518e278 h1:CxF7gG3iqSeYVygTSYsB7Beg+Fpvka06TuTI2a0p+6s= -github.com/gnolang/gno v0.0.0-20240125181217-b6193518e278/go.mod h1:mOhpUTFaKk5CQj90qmjWfI9po2eapqziEu4D+fAtisc= -github.com/gnolang/goleveldb v0.0.9 h1:Q7rGko9oXMKtQA+Apeeed5a3sjba/mcDhzJGoTVLCKE= -github.com/gnolang/goleveldb v0.0.9/go.mod h1:Dz6p9bmpy/FBESTgduiThZt5mToVDipcHGzj/zUOo8E= github.com/gnolang/overflow v0.0.0-20170615021017-4d914c927216 h1:GKvsK3oLWG9B1GL7WP/VqwM6C92j5tIvB844oggL9Lk= github.com/gnolang/overflow v0.0.0-20170615021017-4d914c927216/go.mod h1:xJhtEL7ahjM1WJipt89gel8tHzfIl/LyMY+lCYh38d8= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/flatbuffers v1.12.1 h1:MVlul7pQNoDzWRLTw5imwYsl+usrS1TXG2H4jg6ImGw= -github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 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/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I= 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= -github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 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/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= -github.com/linxGnu/grocksdb v1.8.11 h1:BGol9e5gB1BrsTvOxloC88pe70TCqgrfLNwkyWW0kD8= -github.com/linxGnu/grocksdb v1.8.11/go.mod h1:xZCIb5Muw+nhbDK4Y5UJuOrin5MceOuiXkVUR7vp4WY= -github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= @@ -155,7 +108,6 @@ github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/peterbourgon/ff/v3 v3.4.0 h1:QBvM/rizZM1cB0p0lGMdmR7HxZeI/ZrBWB4DqLkMUBc= @@ -164,146 +116,113 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= -github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= -github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= -github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= -github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= -github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= +github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU= +github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= 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/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 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.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= -github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c h1:g+WoO5jjkqGAzHWCjJB1zZfXPIAaDpzXIEJ0eS6B5Ok= -github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8= -github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -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/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= +github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= +github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= +github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw= +github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI= +go.etcd.io/bbolt v1.3.11 h1:yGEzV1wPz2yVCLsD8ZAiGHhHVlczyC9d1rP43/VCRJ0= +go.etcd.io/bbolt v1.3.11/go.mod h1:dksAq7YMXoljX0xu6VF5DMZGbhYYoLUalEiSySYAS4I= +go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw= +go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.29.0 h1:k6fQVDQexDE+3jG2SfCQjnHS7OamcP73YMoxEVq5B6k= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.29.0/go.mod h1:t4BrYLHU450Zo9fnydWlIuswB1bm7rM8havDpWOJeDo= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.29.0 h1:xvhQxJ/C9+RTnAj5DpTg7LSM1vbbMTiXt7e9hsfqHNw= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.29.0/go.mod h1:Fcvs2Bz1jkDM+Wf5/ozBGmi3tQ/c9zPKLnsipnfhGAo= +go.opentelemetry.io/otel/metric v1.29.0 h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc= +go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8= +go.opentelemetry.io/otel/sdk v1.29.0 h1:vkqKjk7gwhS8VaWb0POZKmIEDimRCMsopNYnriHyryo= +go.opentelemetry.io/otel/sdk v1.29.0/go.mod h1:pM8Dx5WKnvxLCb+8lG1PRNIDxu9g9b9g59Qr7hfAAok= +go.opentelemetry.io/otel/sdk/metric v1.29.0 h1:K2CfmJohnRgvZ9UAj2/FhIf/okdWcNdBwe1m8xFXiSY= +go.opentelemetry.io/otel/sdk/metric v1.29.0/go.mod h1:6zZLdCl2fkauYoZIOn/soQIDSWFmNSRcICarHfuhNJQ= +go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt39JTi4= +go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +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= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -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= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= -golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= +golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= +golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY= +golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= -golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= +golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= +golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= +golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= -golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd h1:BBOTEWLuuEGQy9n1y9MhVJ9Qt0BDu21X8qZs71/uPZo= +google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:fO8wJzT2zbQbAjbIoos1285VfEIYKDDY+Dt+WpTkh6g= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd h1:6TEm2ZxXoQmFWFlt1vNxvVOa1Q0dXFQD1m/rYjXmS0E= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= +google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= @@ -311,4 +230,3 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/misc/devdeps/go.mod b/misc/devdeps/go.mod index 2ca693afc93..c07b82fd11d 100644 --- a/misc/devdeps/go.mod +++ b/misc/devdeps/go.mod @@ -8,7 +8,7 @@ require ( github.com/golangci/golangci-lint v1.59.1 // sync with github action golang.org/x/tools v0.22.1-0.20240628205440-9c895dd76b34 golang.org/x/tools/gopls v0.16.1 - google.golang.org/protobuf v1.33.0 + google.golang.org/protobuf v1.35.1 moul.io/testman v1.5.0 mvdan.cc/gofumpt v0.6.0 ) diff --git a/misc/devdeps/go.sum b/misc/devdeps/go.sum index 4c3f84b6df7..e19e47d0c56 100644 --- a/misc/devdeps/go.sum +++ b/misc/devdeps/go.sum @@ -942,8 +942,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/misc/docs-linter/go.mod b/misc/docs-linter/go.mod index be771c9a952..e27b82ef2f5 100644 --- a/misc/docs-linter/go.mod +++ b/misc/docs-linter/go.mod @@ -5,17 +5,19 @@ go 1.22 toolchain go1.22.4 require ( - github.com/gnolang/gno v0.0.0-20240516161351-0c9849a8ef0c + github.com/gnolang/gno v0.0.0-00010101000000-000000000000 github.com/stretchr/testify v1.9.0 - golang.org/x/sync v0.7.0 + golang.org/x/sync v0.8.0 mvdan.cc/xurls/v2 v2.5.0 ) +replace github.com/gnolang/gno => ../.. + require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/peterbourgon/ff/v3 v3.4.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/sys v0.18.0 // indirect - golang.org/x/term v0.18.0 // indirect + golang.org/x/sys v0.24.0 // indirect + golang.org/x/term v0.23.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/misc/docs-linter/go.sum b/misc/docs-linter/go.sum index ab8c3cf7c48..4957bd0cc88 100644 --- a/misc/docs-linter/go.sum +++ b/misc/docs-linter/go.sum @@ -1,19 +1,17 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/gnolang/gno v0.0.0-20240516161351-0c9849a8ef0c h1:jtZ+oN8ZpBM0wYbcFH0B7NjFFzTFqZZmZellSSKtaCE= -github.com/gnolang/gno v0.0.0-20240516161351-0c9849a8ef0c/go.mod h1:YcZbtNIfXVn4jS1pSG8SeG5RVHjyI7FPS3GypZaXxCI= github.com/peterbourgon/ff/v3 v3.4.0 h1:QBvM/rizZM1cB0p0lGMdmR7HxZeI/ZrBWB4DqLkMUBc= github.com/peterbourgon/ff/v3 v3.4.0/go.mod h1:zjJVUhx+twciwfDl0zBcFzl4dW8axCRyXE/eKY9RztQ= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= -golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= +golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= +golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/misc/genproto/Makefile b/misc/genproto/Makefile index 1033a1b2b24..8c4bfc3118b 100644 --- a/misc/genproto/Makefile +++ b/misc/genproto/Makefile @@ -9,3 +9,7 @@ all: --go_opt=Mproto/compat.proto=github.com/gnolang/gno/tm2/pkg/amino/tests/proto3 \ --go-grpc_opt=Mproto/compat.proto=github.com/gnolang/gno/tm2/pkg/amino/tests/proto3 \ --go-grpc_out=. --go-grpc_opt=paths=source_relative proto/compat.proto + +deps: + go install google.golang.org/protobuf/cmd/protoc-gen-go@latest + go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest diff --git a/misc/genproto/genproto.go b/misc/genproto/genproto.go index b9b97efbe37..c1dfd75ce40 100644 --- a/misc/genproto/genproto.go +++ b/misc/genproto/genproto.go @@ -11,6 +11,7 @@ import ( // TODO: move these out. "github.com/gnolang/gno/gno.land/pkg/sdk/vm" + "github.com/gnolang/gno/gnovm" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" "github.com/gnolang/gno/tm2/pkg/bft/blockchain" @@ -54,6 +55,7 @@ func execGen(_ context.Context, _ []string) error { hd.Package, multisig.Package, std.Package, + gnovm.Package, sdk.Package, bank.Package, vm.Package, diff --git a/misc/genstd/Makefile b/misc/genstd/Makefile new file mode 100644 index 00000000000..2022a6cc2b4 --- /dev/null +++ b/misc/genstd/Makefile @@ -0,0 +1,6 @@ +run: + cd ../../gnovm/stdlibs && go run ../../misc/genstd + cd ../../gnovm/tests/stdlibs && go run ../../../misc/genstd + +test: + go test -v . diff --git a/misc/logos/README.md b/misc/logos/README.md deleted file mode 100644 index ba8ac8333a6..00000000000 --- a/misc/logos/README.md +++ /dev/null @@ -1,11 +0,0 @@ -## Logos Browser - -[Logos](/logos) is a Gno object browser. The modern browser as well as the -modern javascript ecosystem is from a security point of view, completely fucked. -The entire paradigm of continuously updating browsers with incrementally added -features is a security nightmare. - -The Logos browser is based on a new model that is vastly simpler than HTML. -The purpose of Logos is to become a fully expressive web API and implementation -standard that does most of what HTML and the World Wide Web originally intended -to do, but without becoming more complex than necessary. diff --git a/misc/logos/buffer.go b/misc/logos/buffer.go deleted file mode 100644 index 81e8d1abc75..00000000000 --- a/misc/logos/buffer.go +++ /dev/null @@ -1,355 +0,0 @@ -package logos - -import ( - "fmt" - "strings" - - "github.com/gdamore/tcell/v2" -) - -// ---------------------------------------- -// Buffer - -// A Buffer is a buffer area in which to draw. -type Buffer struct { - Size - Cells []Cell -} - -func NewBuffer(sz Size) *Buffer { - return &Buffer{ - Size: sz, - Cells: make([]Cell, sz.Width*sz.Height), - } -} - -func (bb *Buffer) Reset() { - sz := bb.Size - bb.Cells = make([]Cell, sz.Width*sz.Height) -} - -func (bb *Buffer) GetCell(x, y int) *Cell { - if bb.Width <= x { - panic(fmt.Sprintf( - "index x=%d out of bounds, width=%d", - x, bb.Width)) - } - if bb.Height <= y { - panic(fmt.Sprintf( - "index y=%d out of bounds, height=%d", - y, bb.Height)) - } - return &bb.Cells[y*bb.Width+x] -} - -func (bb *Buffer) Sprint() string { - lines := []string{} - for y := 0; y < bb.Height; y++ { - parts := []string{} - for x := 0; x < bb.Width; x++ { - cell := bb.GetCell(x, y) - parts = append(parts, cell.Character) - // NOTE: hacky way to debug. - if true { - attrs := cell.GetAttrs() - flags := attrs.GetAttrFlags() - parts = append(parts, - fmt.Sprintf("%X", flags)) - } - } - line := strings.Join(parts, "") - lines = append(lines, line) - } - return strings.Join(lines, "\n") -} - -func (bb *Buffer) DrawToScreen(s tcell.Screen) { - sw, sh := s.Size() - if bb.Size.Width != sw || bb.Size.Height != sh { - panic("buffer doesn't match screen size") - } - for y := 0; y < sh; y++ { - for x := 0; x < sw; x++ { - cell := bb.GetCell(x, y) - if x == 0 && y == 0 { - // NOTE: to thwart some inexplicable bugs. - s.SetContent(0, 0, tcell.RunePlus, nil, gDefaultSpaceTStyle) - } else { - mainc, combc, tstyle := cell.GetTCellContent() - s.SetContent(x, y, mainc, combc, tstyle) - } - } - } -} - -// ---------------------------------------- -// Cell - -// A terminal character cell. -type Cell struct { - Character string // 1 unicode character, or " ". - Width int - *Style - Attrs - Ref Elem // reference to element -} - -// NOTE: there is a difference in behavior -// from SetValue(...,c2) when c2 has -// attributes not present in c2.Ref, so the -// two are not equivalent. -func (cc *Cell) SetValueFromCell(c2 *Cell) { - cc.SetValue(c2.Character, c2.Width, c2.Style, c2.Ref) - cc.Character = c2.Character - cc.Width = c2.Width - if c2.Style != nil { - cc.Style = c2.Style - } - cc.Attrs.Merge(c2.GetAttrs()) - if c2.Ref != nil { - cc.Ref = c2.Ref - } -} - -func (cc *Cell) SetValue(chs string, w int, st *Style, el Elem) { - cc.Character = chs - cc.Width = w - if st != nil { - cc.Style = st - } - if el != nil { - cc.Attrs.Merge(el.GetAttrs()) - cc.Ref = el - } -} - -func (cc *Cell) Reset() { - *cc = Cell{} -} - -var gDefaultSpaceTStyle = tcell.StyleDefault. - Dim(true). - Background(tcell.ColorGray) - -// This is where a bit of dynamic logic is performed, -// namely where the attr is used to derive the final style. -func (cc *Cell) GetTCellContent() (mainc rune, combc []rune, tstyle tcell.Style) { - style := cc.Style - attrs := &cc.Attrs - if cc.Character == "" { - mainc = '?' // for debugging - if style == nil { - // special case - tstyle = gDefaultSpaceTStyle - } else { - tstyle = style.WithAttrs(attrs).GetTStyle() - } - } else { - rz := toRunes(cc.Character) - mainc = rz[0] - combc = rz[1:] - if style == nil { - tstyle = gDefaultStyle.WithAttrs(attrs).GetTStyle() - } else { - tstyle = style.WithAttrs(attrs).GetTStyle() - } - } - return -} - -// ---------------------------------------- -// View -// analogy: "Buffer:View :: array:slice". - -// Offset and Size must be within bounds of *Buffer. -type View struct { - Base *Buffer - Offset Coord // offset within Buffer - Bounds Size // total size of slice -} - -// offset elements must be 0 or positive. -func (bb *Buffer) NewView(offset Coord) View { - if !offset.IsNonNegative() { - panic("should not happen") - } - return View{ - Base: bb, - Offset: offset, - Bounds: bb.Size, - } -} - -func (bs View) NewView(offset Coord) View { - return View{ - Base: bs.Base, - Offset: bs.Offset.Add(offset), - Bounds: bs.Bounds.SubCoord(offset), - } -} - -func (bs View) GetCell(x, y int) *Cell { - if bs.Bounds.Width <= x { - panic("should not happen") - } - if bs.Bounds.Height <= y { - panic("should not happen") - } - return bs.Base.GetCell( - bs.Offset.X+x, - bs.Offset.Y+y, - ) -} - -// ---------------------------------------- -// BufferedView - -// A view onto an element. -// Somewhat like a slice onto an array -// (as a view is onto an elem), -// except cells are allocated here. -type BufferedElemView struct { - Coord - Size - *Style - Attrs // e.g. to focus on a scrollbar - Base Elem // the underlying elem - Offset Coord // within elem for pagination - *Buffer // view's internal draw screen -} - -// Returns a new *BufferedElemView that spans the whole elem. -// If size is zero, the elem is measured first to get the full -// buffer size. The result must still be rendered before drawing. The -// *BufferedElemView inherits the style and coordinates of the elem, and -// the elem's coord is set to zero. -func NewBufferedElemView(elem Elem, size Size) *BufferedElemView { - if size.IsZero() { - size = elem.Measure() - } - bpv := &BufferedElemView{ - Size: size, - Style: elem.GetStyle(), - Base: elem, - Offset: Coord{0, 0}, - // NOTE: be lazy, size may change. - // Buffer: NewBuffer(size), - } - bpv.SetCoord(elem.GetCoord()) - bpv.SetIsDirty(true) - elem.SetParent(bpv) - elem.SetCoord(Coord{}) // required for abs calc. - return bpv -} - -func (bpv *BufferedElemView) StringIndented(indent string) string { - return fmt.Sprintf("Buffered%v@%p\n%s %s", - bpv.Size, - bpv, - indent, - bpv.Base.StringIndented(indent+" ")) -} - -func (bpv *BufferedElemView) String() string { - return fmt.Sprintf("Buffered%v{%v}@%p", - bpv.Size, - bpv.Base, - bpv) -} - -// Pass on style to the base elem. -func (bpv *BufferedElemView) SetStyle(style *Style) { - bpv.Style = style - bpv.Base.SetStyle(style) - bpv.SetIsDirty(true) -} - -func (bpv *BufferedElemView) SetSize(size Size) { - bpv.Size = size - bpv.Buffer = nil - bpv.SetIsDirty(true) -} - -// Cursor status pierces the buffered elem view; -// but a few key events are still consumed before the base. -func (bpv *BufferedElemView) SetIsCursor(ic bool) { - bpv.Attrs.SetIsCursor(ic) - bpv.Base.SetIsCursor(ic) -} - -// BufferedElemView's size is simply defined by .Size. -func (bpv *BufferedElemView) Measure() Size { - return bpv.Size -} - -// Renders the elem onto the internal buffer. -// Assumes buffered elem view's elem was already rendered. -// TODO: this function could be optimized to reduce -// redundant background cell modifications. -func (bpv *BufferedElemView) Render() (updated bool) { - if !bpv.GetIsDirty() { - return - } else { - defer bpv.SetIsDirty(false) - } - // Get or initialize buffer. - buffer := bpv.Buffer - if buffer == nil { - buffer = NewBuffer(bpv.Size) - bpv.Buffer = buffer - } - // Reset the buffer's cells. We could - // use Buffer.Reset(), but this helps - // distinguish between undefined cells - // and those of an empty buffer. - for x := 0; x < buffer.Size.Width; x++ { - for y := 0; y < buffer.Size.Height; y++ { - cell := buffer.GetCell(x, y) - cell.Reset() - // Draw Logos star background. - cell.SetValue("\u2606", 1, bpv.Style, bpv) - } - } - // Then, render and draw elem. - bpv.Base.Render() - bpv.Base.Draw(bpv.Offset, buffer.NewView(Coord{})) - return true -} - -func (bpv *BufferedElemView) Draw(offset Coord, view View) { - minX, maxX, minY, maxY := computeIntersection(bpv.Size, offset, view.Bounds) - for y := minY; y < maxY; y++ { - for x := minX; x < maxX; x++ { - bcell := bpv.Buffer.GetCell(x, y) - vcell := view.GetCell(x-offset.X, y-offset.Y) - vcell.SetValueFromCell(bcell) - } - } -} - -func (bpv *BufferedElemView) ProcessEventKey(ev *EventKey) bool { - // Pagination is outer-greedy, and so Logos - // generally just likes infinite areas. - switch evr := ev.Rune(); evr { - case 'a': // left - bpv.Scroll(Coord{16, 0}) - case 's': // down - bpv.Scroll(Coord{0, -8}) - case 'd': // right - bpv.Scroll(Coord{-16, 0}) - case 'w': // up - bpv.Scroll(Coord{0, 8}) - default: - // Try to get the base to handle it. - if bpv.Base.ProcessEventKey(ev) { - return true - } - return false - } - return true // convenience for cases. -} - -func (bpv *BufferedElemView) Scroll(dir Coord) { - bpv.Offset = bpv.Offset.Add(dir) - bpv.SetIsDirty(true) -} diff --git a/misc/logos/cmd/logos.go b/misc/logos/cmd/logos.go deleted file mode 100644 index 3a374fecba2..00000000000 --- a/misc/logos/cmd/logos.go +++ /dev/null @@ -1,171 +0,0 @@ -package main - -import ( - "fmt" - "os" - "runtime/debug" - - "github.com/gdamore/tcell/v2" - "github.com/gdamore/tcell/v2/encoding" - "github.com/gnolang/gno/misc/logos" -) - -func main() { - encoding.Register() - - // construct screen - s, e := tcell.NewScreen() - if e != nil { - fmt.Fprintf(os.Stderr, "%v\n", e) - os.Exit(1) - } - // initialize screen - if e = s.Init(); e != nil { - fmt.Fprintf(os.Stderr, "%v\n", e) - os.Exit(1) - } - s.SetStyle(tcell.StyleDefault. - Foreground(tcell.ColorBlack). - Background(tcell.ColorWhite)) - s.Clear() - sw, sh := s.Size() - size := logos.Size{Width: sw, Height: sh} - - // make a buffered stack. - stack := logos.NewStack(size) - stack.PushLayer(makeTestPage()) - bstack := logos.NewBufferedElemView(stack, size) - bstack.Render() - bstack.DrawToScreen(s) - - // recover any panics. - var rec interface{} - var recStack []byte - - // show the screen - quit := make(chan struct{}) - s.Show() - go func() { - // capture panics to print error better. - defer func() { - if rec = recover(); rec != nil { - recStack = debug.Stack() - close(quit) - return - } - }() - // handle event - for { - ev := s.PollEvent() - switch ev := ev.(type) { - case *tcell.EventKey: - switch ev.Key() { - case tcell.KeyCtrlQ: - close(quit) - return - case tcell.KeyCtrlR: - // TODO somehow make it clearer that it happened. - bstack.DrawToScreen(s) - s.Sync() - default: - bstack.ProcessEventKey(ev) - if bstack.Render() { - bstack.DrawToScreen(s) - s.Sync() - } - } - case *tcell.EventResize: - s.Sync() - } - } - }() - - // wait to quit - <-quit - s.Fini() - fmt.Println("charset:", s.CharacterSet()) - fmt.Println("goodbye!") - fmt.Println(bstack.Sprint()) - - if rec != nil { - fmt.Println("====================") - fmt.Println("panic:", rec) - fmt.Println("stacktrace:\n", string(recStack)) - fmt.Println("====================") - } -} - -func makeTestString() string { - s := "" - putln := func(l string) { - s += l + "\n" - } - // putln("Character set: " + s.CharacterSet()) - putln("Press Ctrl-Q to Exit") - putln("English: October") - putln("Icelandic: október") - putln("Arabic: أكتوبر") - putln("Russian: октября") - putln("Greek: Οκτωβρίου") - putln("Chinese: 十月 (note, two double wide characters)") - putln("Combining: A\u030a (should look like Angstrom)") - putln("Emoticon: \U0001f618 (blowing a kiss)") - putln("Airplane: \u2708 (fly away)") - putln("Command: \u2318 (mac clover key)") - putln("Enclose: !\u20e3 (should be enclosed exclamation)") - putln("ZWJ: \U0001f9db\u200d\u2640 (female vampire)") - putln("ZWJ: \U0001f9db\u200d\u2642 (male vampire)") - putln("Family: \U0001f469\u200d\U0001f467\u200d\U0001f467 (woman girl girl)\n") - // XXX why is this broken? - // putln("Region: \U0001f1fa\U0001f1f8 (USA! USA!)\n") - putln("") - putln("Box:") - putln(string([]rune{ - tcell.RuneULCorner, - tcell.RuneHLine, - tcell.RuneTTee, - tcell.RuneHLine, - tcell.RuneURCorner, - })) - putln(string([]rune{ - tcell.RuneVLine, - tcell.RuneBullet, - tcell.RuneVLine, - tcell.RuneLantern, - tcell.RuneVLine, - }) + " (bullet, lantern/section)") - putln(string([]rune{ - tcell.RuneLTee, - tcell.RuneHLine, - tcell.RunePlus, - tcell.RuneHLine, - tcell.RuneRTee, - })) - putln(string([]rune{ - tcell.RuneVLine, - tcell.RuneDiamond, - tcell.RuneVLine, - tcell.RuneUArrow, - tcell.RuneVLine, - }) + " (diamond, up arrow)") - putln(string([]rune{ - tcell.RuneLLCorner, - tcell.RuneHLine, - tcell.RuneBTee, - tcell.RuneHLine, - tcell.RuneLRCorner, - })) - return s -} - -func makeTestPage() *logos.BufferedElemView { - // make a buffered page. - ts := makeTestString() - style := logos.DefaultStyle() - style.Padding = logos.Padding{2, 2, 2, 2} - style.Border = logos.DefaultBorder() - // TODO width shouldn't matter. - page := logos.NewPage(ts, 84, true, style) - bpv := logos.NewBufferedElemView(page, logos.Size{}) - return bpv -} diff --git a/misc/logos/image.png b/misc/logos/image.png deleted file mode 100644 index d6ac0cf3151..00000000000 Binary files a/misc/logos/image.png and /dev/null differ diff --git a/misc/logos/misc.go b/misc/logos/misc.go deleted file mode 100644 index 4bf3c8c6267..00000000000 --- a/misc/logos/misc.go +++ /dev/null @@ -1,155 +0,0 @@ -package logos - -import ( - "strings" - "unicode" - - "github.com/gdamore/tcell/v2" - runewidth "github.com/mattn/go-runewidth" -) - -// splits a string into lines by newline. -func splitLines(s string) (ss []string) { - return strings.Split(s, "\n") -} - -// splits a string according to unicode spaces. -func splitSpaces(s string) (ss []string) { - buf := []rune{} - for _, r := range s { - if unicode.IsSpace(r) { - // continue - if len(buf) > 0 { - ss = append(ss, string(buf)) - buf = nil - } - } else { - buf = append(buf, r) - } - } - if len(buf) > 0 { - ss = append(ss, string(buf)) - // buf = nil - } - return ss -} - -func toRunes(s string) []rune { - runes := make([]rune, 0, len(s)) - for _, r := range s { - runes = append(runes, r) - } - return runes -} - -// gets the terminal display width of a string. -// must be compatible with nextCharacter(). -// NOTE: must be kept in sync with nextCharacter(); see tests. -func widthOf(s string) (l int) { - zwj := false // zero width joiner '\u200d'. - for _, r := range s { - if r == '\u200d' { - zwj = true - continue - } - if zwj { - zwj = false - continue - } - switch runewidth.RuneWidth(r) { - case 0: - if isCombining(r) { - // combining characters have no length. - } else { - l++ // show a blank instead, weird. - } - case 1: - l++ - case 2: - l += 2 - default: - panic("should not happen") - } - } - return l -} - -// given runes of a valid utf8 string, -// return a string that represents -// the next single character (with any modifiers). -// w: width of character. n: number of runes read -func nextCharacter(rz []rune) (s string, w int, n int) { - for n = 0; n < len(rz); n++ { - r := rz[n] - if r == '\u200d' { - // special case: zero width joins. - s = s + string(r) - if n+1 < len(rz) { - s = s + string(rz[n+1]) - n++ - continue - } else { - // just continue, return invalid string s. - n++ - return - } - } else if 0 < len(s) { - return - } else { - // append r to s and inc w. - rw := runewidth.RuneWidth(r) - s = s + string(r) - if rw == 0 { - if isCombining(r) { - // no width - } else { - w += 1 - } - } else { - w += rw - } - } - } - return -} - -//---------------------------------------- - -func AbsCoord(elem Elem) (crd Coord) { - for elem != nil { - crd = crd.Add(elem.GetCoord()) - elem = elem.GetParent() - } - return -} - -var randColors []Color = []Color{ - tcell.ColorAliceBlue, - tcell.ColorAntiqueWhite, - tcell.ColorAquaMarine, - tcell.ColorAzure, - tcell.ColorBeige, - tcell.ColorBisque, - tcell.ColorBlanchedAlmond, - tcell.ColorBlueViolet, - tcell.ColorBrown, - tcell.ColorBurlyWood, -} - -var rctr = 0 - -func RandColor() Color { - rctr++ - return randColors[rctr%len(randColors)] -} - -func IsInBounds(x, y int, origin Coord, size Size) bool { - if x < origin.X || y < origin.Y { - return false - } - if origin.X+size.Width <= x || - origin.Y+size.Height <= y { - return false - } - return true -} diff --git a/misc/logos/misc_test.go b/misc/logos/misc_test.go deleted file mode 100644 index a147f8b41ea..00000000000 --- a/misc/logos/misc_test.go +++ /dev/null @@ -1,166 +0,0 @@ -package logos - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/gnolang/gno/tm2/pkg/random" -) - -// Tests whether widthOf() and nextCharacter() do the same thing. -func TestStringWidthSlow(t *testing.T) { - t.Skip("test failing") - for n := 1; n < 4; n++ { - bz := make([]byte, n) - for { - width1 := widthOf(string(bz)) - width2 := widthOfSlow(string(bz)) - if width1 == 0 { - if isRepeatedWZJ(bz) { - // these bytes encode one or more U+200D WZJ as UTF8. - } else { - require.Fail(t, fmt.Sprintf("unexpected zero width string for bytes %X", bz)) - } - } else { - require.True(t, 0 < width1, "got zero width for bytes %X", bz) - } - require.Equal(t, width1, width2) - if !incBuffer(bz) { - break - } - } - } -} - -// Same as above but for longer pseudo-random strings. -func TestStringWidthRandom(t *testing.T) { - max := 10 * 1024 * 1024 - for i := 0; i < max; i++ { - if i%(max/80) == 0 { - fmt.Print(".") - } - bz := random.RandBytes(12) - width1 := widthOf(string(bz)) - width2 := widthOfSlow(string(bz)) - if width1 == 0 { - if isRepeatedWZJ(bz) { - // these bytes encode one or more U+200D WZJ as UTF8. - } else { - require.Fail(t, "unexpected zero width string") - } - } else { - require.True(t, 0 < width1, "got zero width for bytes %X", bz) - } - require.Equal(t, width1, width2, - "want %d but got %d the slow way: %X", - width1, width2, bz) - } -} - -// For debugging. -func TestStringWidthDummy(t *testing.T) { - bz := []byte{0x0C, 0x5B, 0x0D, 0xCF, 0xC5, 0xE2, 0x80, 0x8D, 0xC1, 0x32, 0x69, 0x41} - width1 := widthOf(string(bz)) - width2 := widthOfSlow(string(bz)) - if width1 == 0 { - if isRepeatedWZJ(bz) { - // these bytes encode one or more U+200D WZJ as UTF8. - } else { - require.Fail(t, "unexpected zero width string") - } - } else { - require.True(t, 0 < width1, "got zero width for bytes %X", bz) - } - require.Equal(t, width1, width2, - "want %d but got %d the slow way: %X", - width1, width2, bz) -} - -// For debugging. -func TestStringWidthDummy2(t *testing.T) { - t.Skip("test failing") - // NOTE: this is broken in the OSX terminal. This should print a USA flag - // and have width 2, or possibly default to two block letters "U" and "S", - // but my terminal prints a flag of width 1. - bz := []byte("\U0001f1fa\U0001f1f8") - width1 := widthOf(string(bz)) - width2 := widthOfSlow(string(bz)) - require.Equal(t, 1, width1) - require.Equal(t, width1, width2, - "want %d but got %d the slow way: %X", - width1, width2, bz) -} - -func isRepeatedWZJ(bz []byte) bool { - if len(bz)%3 != 0 { - return false - } - // this is U+200D is UTF8. - for i := 0; i < len(bz); i += 3 { - if bz[i] != 0xE2 { - return false - } - if bz[i+1] != 0x80 { - return false - } - if bz[i+2] != 0x8D { - return false - } - } - return true -} - -// get the width of a string using nextCharacter(). -func widthOfSlow(s string) (w int) { - rz := toRunes(s) - for 0 < len(rz) { - _, w2, n := nextCharacter(rz) - if n == 0 { - panic("should not happen") - } - w += w2 - rz = rz[n:] - } - return -} - -//---------------------------------------- -// incBuffer for testing - -// If overflow, bz becomes zero and returns false. -func incBuffer(bz []byte) bool { - for i := 0; i < len(bz); i++ { - if bz[i] == 0xFF { - bz[i] = 0x00 - } else { - bz[i]++ - return true - } - } - return false -} - -func TestIncBuffer1(t *testing.T) { - bz := []byte{0x00} - for i := 0; i < (1<<(1*8))-1; i++ { - require.Equal(t, true, incBuffer(bz)) - require.Equal(t, byte(i+1), bz[0]) - } - require.Equal(t, false, incBuffer(bz)) - require.Equal(t, byte(0x00), bz[0]) -} - -func TestIncBuffer2(t *testing.T) { - bz := []byte{0x00, 0x00} - for i := 0; i < (1<<(2*8))-1; i++ { - require.Equal(t, true, incBuffer(bz)) - require.Equal(t, byte(((i+1)>>0)%256), bz[0]) - require.Equal(t, byte(((i+1)>>8)%256), bz[1]) - } - require.Equal(t, []byte{0xFF, 0xFF}, bz) - require.Equal(t, false, incBuffer(bz)) - require.Equal(t, byte(0x00), bz[0]) - require.Equal(t, byte(0x00), bz[1]) -} diff --git a/misc/logos/stack.go b/misc/logos/stack.go deleted file mode 100644 index 17b18327fd2..00000000000 --- a/misc/logos/stack.go +++ /dev/null @@ -1,160 +0,0 @@ -package logos - -import ( - "fmt" - "strings" - - "github.com/gdamore/tcell/v2" -) - -//---------------------------------------- -// Stack - -// A Stack is like a Page, but it only highlights the top -// element, and dims, occludes, or hides lower elements. A -// Stack is therefore ideal for showing modal views. NOTE: -// While most applications shouldn't, it's perfectly fine to -// embed Stacks within Stacks, or layer them on top within a -// stack. -type Stack struct { - Page // a Stack has the same fields as a page. -} - -func NewStack(size Size) *Stack { - return &Stack{ - Page: Page{ - Size: size, // dontcare. - Elems: nil, // nil layers. - Cursor: -1, - }, - } -} - -func (st *Stack) StringIndented(indent string) string { - elines := []string{} - eindent := indent + " " - for _, elem := range st.Elems { - elines = append(elines, eindent+elem.StringIndented(eindent)) - } - return fmt.Sprintf("Stack%v@%p\n%s", - st.Size, - st, - strings.Join(elines, "\n")) -} - -func (st *Stack) String() string { - return fmt.Sprintf("Stack%v{%d}@%p", - st.Size, - len(st.Elems), - st) -} - -func (st *Stack) PushLayer(layer Elem) { - layer.SetParent(st) - st.Elems = append(st.Elems, layer) - st.Cursor++ - st.SetIsDirty(true) -} - -// A Stack's size is simply determined by its .Size. -func (st *Stack) Measure() Size { - return st.Size -} - -// A Stack's render function behaves the same as a Page's; -// it renders its elements (here, its layers). -func (st *Stack) Render() (updated bool) { - return st.Page.Render() -} - -// Draw the rendered layers onto the view. Any dimming of -// occluded layers must actually stretch in all directions -// infinitely (since we can scroll beyond the bounds of any -// view and we expect the dimming effect to carry while we -// scroll), so the entire view is dimmed first, and then the -// upper-most layer is drawn. -func (st *Stack) Draw(offset Coord, view View) { - // Draw bottom layers. - if 1 < len(st.Elems) { - for _, elem := range st.Elems[:len(st.Elems)-1] { - loffset := offset.Sub(elem.GetCoord()) - elem.Draw(loffset, view) - } - } - if 0 < len(st.Elems) { - last := st.Elems[len(st.Elems)-1] - loffset := offset.Sub(last.GetCoord()) - // Draw occlusion screen on view. - for y := 0; y < view.Bounds.Height; y++ { - for x := 0; x < view.Bounds.Width; x++ { - vcell := view.GetCell(x, y) - inBounds := IsInBounds(x, y, - loffset.Neg(), - last.GetSize()) - if inBounds { - // Reset unsets residual "occluded", - // "cursor", and other attributes from the - // previous layer which are no longer - // relevant. - vcell.Reset() - } else { - vcell.SetIsOccluded(true) - } - } - } - // Draw last (top) layer. - last.Draw(loffset, view) - } else { - // Draw occlusion screen on view. - for y := 0; y < view.Bounds.Height; y++ { - for x := 0; x < view.Bounds.Width; x++ { - vcell := view.GetCell(x, y) - vcell.SetIsOccluded(true) - } - } - } -} - -func (st *Stack) ProcessEventKey(ev *EventKey) bool { - // An empty *Stack is inert. - if len(st.Page.Elems) == 0 { - return false - } - // Try to let the last layer handle it. - last := st.Page.Elems[len(st.Page.Elems)-1] - if last.ProcessEventKey(ev) { - return true - } - // Maybe it's something for the stack. - switch ev.Key() { - case tcell.KeyEsc: - if 1 < len(st.Page.Elems) { - // Pop the last layer. - st.Elems = st.Elems[:len(st.Elems)-1] - st.Cursor-- - st.SetIsDirty(true) - return true - } else { - // Let the last layer stick around. - return false - } - default: - return false - } -} - -// Traverses the inclusive ancestors of elem and returns the -// first *Stack encountered. The purpose of this function is -// to find where to push new layers and modal elements for -// drawing. -func StackOf(elem Elem) *Stack { - for elem != nil { - fmt.Println("StackOf", elem) - if st, ok := elem.(*Stack); ok { - return st - } else { - elem = elem.GetParent() - } - } - return nil // no stack -} diff --git a/misc/logos/types.go b/misc/logos/types.go deleted file mode 100644 index 96e983992eb..00000000000 --- a/misc/logos/types.go +++ /dev/null @@ -1,1006 +0,0 @@ -package logos - -import ( - "fmt" - "strings" - - "github.com/gdamore/tcell/v2" -) - -// ---------------------------------------- -// Page - -// A Page has renderable Elem(ents). -type Page struct { - Coord // used by parent only. TODO document. - Size - *Style - Attrs - Elems []Elem - Cursor int // selected cursor element index, or -1. -} - -// An elem is something that can draw a portion of itself onto -// a view. It has a relative coord and a size. Before it is -// drawn, it is rendered. Measure will update its size, while -// GetSize() returns the cached size. ProcessEventKey() -// returns true if event was consumed. -type Elem interface { - GetParent() Elem - SetParent(Elem) - GetCoord() Coord - SetCoord(Coord) - GetStyle() *Style - SetStyle(*Style) - GetAttrs() *Attrs - GetIsCursor() bool - SetIsCursor(bool) - GetIsDirty() bool - SetIsDirty(bool) - GetIsOccluded() bool - SetIsOccluded(bool) - GetSize() Size - Measure() Size - Render() bool - Draw(offset Coord, dst View) - ProcessEventKey(*EventKey) bool - String() string - StringIndented(indent string) string - // NOTE: SetSize(Size) isn't an elem interface, as - // containers in general can't force elements to be of a - // certain size, but rather prefers drawing out of - // bounds; this opinion may distinguishes Logos from - // other most gui frameworks. -} - -var ( - _ Elem = &Page{} - _ Elem = &BufferedElemView{} - _ Elem = &TextElem{} - _ Elem = &Stack{} -) - -// produces a page from a string. -// width is the width of the page. -// if isCode, width is ignored. -func NewPage(s string, width int, isCode bool, style *Style) *Page { - page := &Page{ - Size: Size{ - Width: width, - Height: -1, // not set - }, - Style: style, - Elems: nil, // will set - Cursor: -1, - } - elems := []Elem{} - if s != "" { - pad := style.GetPadding() - ypos := 0 + pad.Top - xpos := 0 + pad.Left - lines := splitLines(s) - if isCode { - for _, line := range lines { - te := NewTextElem(line, style) - te.SetParent(page) - te.SetCoord(Coord{X: xpos, Y: ypos}) - elems = append(elems, te) - ypos++ - xpos = 0 + pad.Left - } - } else { - for _, line := range lines { - words := splitSpaces(line) - for _, word := range words { - wd := widthOf(word) - if width < xpos+wd+pad.Left+pad.Right { - if xpos != 0+pad.Left { - ypos++ - xpos = 0 + pad.Left - } - } - te := NewTextElem(word, style) - te.SetParent(page) - te.SetCoord(Coord{X: xpos, Y: ypos}) - elems = append(elems, te) - xpos += te.Width // size of word - xpos += 1 // space after each word (not written) - } - ypos++ - xpos = 0 + pad.Left - } - } - } - page.Elems = elems - page.Measure() - page.SetIsDirty(true) - return page -} - -func (pg *Page) StringIndented(indent string) string { - elines := []string{} - eindent := indent + " " - for _, elem := range pg.Elems { - elines = append(elines, eindent+elem.StringIndented(eindent)) - } - return fmt.Sprintf("Page%v@%p\n%s", - pg.Size, - pg, - strings.Join(elines, "\n")) -} - -func (pg *Page) String() string { - return fmt.Sprintf("Page%v{%d}@%p", - pg.Size, len(pg.Elems), pg) -} - -func (pg *Page) NextCoord() Coord { - if len(pg.Elems) == 0 { - return Coord{X: pg.GetPadding().Left, Y: pg.GetPadding().Top} - } else { - last := pg.Elems[len(pg.Elems)-1] - last.Measure() - lcoord := last.GetCoord() - lsize := last.GetSize() - return Coord{ - X: pg.GetPadding().Left, - Y: lcoord.Y + lsize.Height, // no spacers by spec. - } - } -} - -func (pg *Page) SetStyle(style *Style) { - pg.Style = style -} - -// Measures the size of elem and appends to page below the last element, -// or if empty, the top-leftmost coordinate exclusive of padding cells. -func (pg *Page) AppendElem(elem Elem) { - ncoord := pg.NextCoord() - elem.SetParent(pg) - elem.SetCoord(ncoord) - pg.Elems = append(pg.Elems, elem) - pg.SetIsDirty(true) -} - -// Assumes page starts at 0,0. -func (pg *Page) Measure() Size { - pad := pg.GetPadding() - maxX := pad.Left - maxY := pad.Top - for _, view := range pg.Elems { - coord := view.GetCoord() - size := view.GetSize() - if maxX < coord.X+size.Width { - maxX = coord.X + size.Width - } - if maxY < coord.Y+size.Height { - maxY = coord.Y + size.Height - } - } - size := Size{ - Width: maxX + pad.Right, - Height: maxY + pad.Bottom, - } - pg.Size = size - return size -} - -/* - Page draw logic: - Let's say we want to draw a Page. We want to draw it onto - some buffer, or more specially some "view" of a buffer (as - a slice of an array is a view into an array buffer). - - Page virtual bounds: - 0 - - - - - - - - - - + - :\ : - : \ (3,3) : - : @-----------+ : - : |View | : - : | | : - : +-----------+ : - : : - + - - - - - - - - - - + - - 0 is the origin point for the Page. - @ is an offset within the page. @ here is (3,3). - It is where the View is conceptually placed, but - otherwise the View isn't aware where @ is. - This offset is passed in as an argument 'offset'. - - NOTE: Offset is relative in the base page. To offset the - drawing position in the view (e.g. to only write on the - right half of the buffer view), derive another view from - the original. - - The View is associated with an underlying (base) buffer. - - Page virtual bounds: - 0 - - - - - - - - - - + - +=:=====================:===+ <-- underlying Buffer - | : : | - | : @-------------+ : | - | : |View | : | - | : |.Offset=(5,2)| : | - | : +-------------+ : | - | : : | - | + - - - - - - - - - - + | - +===========================+ - - Each element must be drawn onto the buffer view with the - right offset algebra applied. Here is a related diagram - showing the buffer in relation to page elements. - - Page virtual bounds: - 0 - - - - - - - - - - - + - :elem 1 |elem 2 : - : @------------+ : - : |View | : - + - - - | - E - - - -|- + - :elem 3 | |elem 4 | : - : +------------+ : - : | : - + - - - - - - - - - - - + - - In this example the page is composed of four element tiles. - E is elem-4's offset relative to 0, the page's origin. To - draw the top-left portion of elem-4 onto the buffer slice - as shown, the element is drawn with an offset of @-E, which - is negative and indicates that the element should be drawn - offset positively (right and bottom) from @. -*/ - -// Unlike TextElem or BufferedElemView, a Page doesn't keep -// its own buffer. Its render function calls the elements' -// render functions, and the element buffers are combined -// during Draw(). There is a need for distinction because -// Draw() can't be too slow, so Render() is about optimizing -// Draw() calls. The distinction between *Page and -// BufferedElemView gives the user more flexibility. -func (pg *Page) Render() (updated bool) { - if !pg.GetIsDirty() { - return - } else { - defer pg.SetIsDirty(false) - } - for _, elem := range pg.Elems { - elem.Render() - } - return true -} - -// Draw the rendered page elements onto the view. -func (pg *Page) Draw(offset Coord, view View) { - style := pg.GetStyle() - border := style.GetBorder() - minX, maxX, minY, maxY := computeIntersection(pg.Size, offset, view.Bounds) - // First, draw page background style. - for y := minY; y < maxY; y++ { - for x := minX; x < maxX; x++ { - xo, yo := x-offset.X, y-offset.Y - vcell := view.GetCell(xo, yo) - // Draw area and border. - if x == 0 { - if y == pg.Size.Height-1 { - // handle this case first so if height is 1, - // this corner is preferred. - vcell.SetValue(border.BLCorner(), 1, style, pg) - } else if y == 0 { - vcell.SetValue(border.TLCorner(), 1, style, pg) - } else { - vcell.SetValue(border.LeftBorder(y), 1, style, pg) - } - } else if x == pg.Size.Width-1 { - if y == pg.Size.Height-1 { - // ditto for future left-right language support. - vcell.SetValue(border.BRCorner(), 1, style, pg) - } else if y == 0 { - vcell.SetValue(border.TRCorner(), 1, style, pg) - } else { - vcell.SetValue(border.RightBorder(y), 1, style, pg) - } - } else if y == 0 { - vcell.SetValue(border.TopBorder(x), 1, style, pg) - } else if y == pg.Size.Height-1 { - vcell.SetValue(border.BottomBorder(x), 1, style, pg) - } else { // Draw area. - vcell.SetValue(" ", 1, style, pg) - } - } - } - // Then, draw elems. - for _, elem := range pg.Elems { - eoffset := offset.Sub(elem.GetCoord()) - elem.Draw(eoffset, view) - } -} - -type EventKey = tcell.EventKey - -func (pg *Page) ProcessEventKey(ev *EventKey) bool { - switch ev.Key() { - case tcell.KeyEsc: - return false - case tcell.KeyUp: - pg.DecCursor(true) - case tcell.KeyDown: - pg.IncCursor(true) - case tcell.KeyLeft: - pg.DecCursor(false) - case tcell.KeyRight: - pg.IncCursor(false) - case tcell.KeyEnter: - if pg.Cursor == -1 { - // as if pressed down - pg.IncCursor(true) - return true - } - // XXX this is a test. - st := StackOf(pg) - celem := pg.Elems[pg.Cursor] - coord := AbsCoord(celem).Sub(AbsCoord(st)) - page := NewPage("this is a test", 80, false, pg.Style) - coord.Y += 1 - coord.X += 2 - page.SetCoord(coord) - st.PushLayer(page) - default: - return false - } - // Leave as true for convenience in cases above. - // If a key event wasn't consumed, return false. - return true -} - -func (pg *Page) IncCursor(isVertical bool) { - if pg.Cursor == -1 { - if len(pg.Elems) == 0 { - // nothing to select. - } else { - pg.Cursor = 0 - pg.Elems[pg.Cursor].SetIsCursor(true) - } - } else { - pg.Elems[pg.Cursor].SetIsCursor(false) - pg.Cursor++ - if pg.Cursor == len(pg.Elems) { - pg.Cursor = 0 // roll back. - } - pg.Elems[pg.Cursor].SetIsCursor(true) - } -} - -func (pg *Page) DecCursor(isVertical bool) { - if pg.Cursor == -1 { - if len(pg.Elems) == 0 { - // nothing to select. - } else { - pg.Cursor = len(pg.Elems) - 1 - pg.Elems[pg.Cursor].SetIsCursor(true) - } - } else { - pg.Elems[pg.Cursor].SetIsCursor(false) - pg.Cursor-- - if pg.Cursor == -1 { - pg.Cursor = len(pg.Elems) - 1 // roll forward. - } - pg.Elems[pg.Cursor].SetIsCursor(true) - } -} - -// ---------------------------------------- -// TextElem - -type TextElem struct { - Coord - Size - *Style // ignores padding. - Attrs - Text string - *Buffer -} - -func NewTextElem(text string, style *Style) *TextElem { - te := &TextElem{ - Style: style, - Text: text, - Buffer: NewBuffer(Size{ - Height: 1, - Width: widthOf(text), - }), - } - te.Measure() - te.SetIsDirty(true) - return te -} - -func (tel *TextElem) SetStyle(style *Style) { - tel.Style = style -} - -func (tel *TextElem) StringIndented(indent string) string { - return tel.String() -} - -func (tel *TextElem) String() string { - return fmt.Sprintf("Text{%q}", tel.Text) -} - -func (tel *TextElem) Measure() Size { - size := Size{ - Height: 1, - Width: widthOf(tel.Text), - } - tel.Size = size - return size -} - -func (tel *TextElem) Render() (updated bool) { - if tel.Height != 1 { - panic("should not happen") - } - if !tel.GetIsDirty() { - return - } else { - defer tel.SetIsDirty(false) - } - tel.Buffer.Reset() - style := tel.GetStyle() - runes := toRunes(tel.Text) - i := 0 - for 0 < len(runes) { - s, w, n := nextCharacter(runes) - if n == 0 { - panic(fmt.Sprintf( - "unexpected error reading next character from runes %v", - runes)) - } else { - runes = runes[n:] - } - cell := tel.Buffer.GetCell(i, 0) - cell.SetValue(s, w, style, tel) - for j := 1; j < w; j++ { - cell := tel.Buffer.GetCell(i+j, 0) - cell.SetValue("", 0, style, tel) // clear next cells - } - i += w - } - if i != tel.Buffer.Width { - panic(fmt.Sprintf( - "wrote %d cells but there are %d in buffer with text %q", - i, tel.Buffer.Width, tel.Text)) - } - return true -} - -func (tel *TextElem) Draw(offset Coord, view View) { - minX, maxX, minY, maxY := computeIntersection(tel.Size, offset, view.Bounds) - for y := minY; y < maxY; y++ { - if minY != 0 { - panic("should not happen") - } - for x := minX; x < maxX; x++ { - bcell := tel.Buffer.GetCell(x, y) - vcell := view.GetCell(x-offset.X, y-offset.Y) - vcell.SetValueFromCell(bcell) - } - } -} - -func (tel *TextElem) ProcessEventKey(ev *EventKey) bool { - return false // TODO: clipboard. -} - -// ---------------------------------------- -// misc. - -type Color = tcell.Color - -// Style is purely visual and has no side effects. -// It is generally referred to by pointer; you may need to copy before -// modifying. -type Style struct { - Foreground Color - Background Color - Padding Padding - Border Border - StyleFlags - Other []KVPair - CursorStyle *Style -} - -func DefaultStyle() *Style { - return &Style{ - Foreground: gDefaultForeground, - Background: gDefaultBackground, - CursorStyle: &Style{ - Background: tcell.ColorYellow, - }, - } -} - -var ( - gDefaultStyle = DefaultStyle() - gDefaultForeground = tcell.ColorBlack - gDefaultBackground = tcell.ColorLightBlue -) - -func (st *Style) Copy() *Style { - st2 := *st - return &st2 -} - -func (st *Style) GetStyle() *Style { - return st -} - -func (st *Style) GetForeground() Color { - if st == nil { - return gDefaultStyle.Foreground - } else { - return st.Foreground - } -} - -func (st *Style) GetBackground() Color { - if st == nil { - return gDefaultStyle.Background - } else { - return st.Background - } -} - -func (st *Style) GetPadding() Padding { - if st == nil { - return gDefaultStyle.Padding - } else { - return st.Padding - } -} - -func (st *Style) GetBorder() *Border { - if st == nil { - return &gDefaultStyle.Border - } else { - return &st.Border - } -} - -func (st *Style) GetCursorStyle() *Style { - if st == nil { - return gDefaultStyle.CursorStyle - } else if st.CursorStyle == nil { - return st - } else { - return st.CursorStyle - } -} - -// NOTE: this should only be called during the last step when -// writing to screen. The receiver must not be nil and must -// not be modified, and the result is a value, not the style -// of any particular element. -func (st *Style) WithAttrs(attrs *Attrs) (res Style) { - if st == nil { - panic("unexpected nil style") - } - if attrs.GetIsCursor() { - res = *st.GetCursorStyle() - } else { - res = *st - } - if attrs.GetIsOccluded() { - res.SetIsShaded(true) - } - return -} - -func (st Style) GetTStyle() (tst tcell.Style) { - if st.Foreground.Valid() { - tst = tst.Foreground(st.Foreground) - } else { - tst = tst.Foreground(gDefaultForeground) - } - if st.Background.Valid() { - tst = tst.Background(st.Background) - } else { - tst = tst.Background(gDefaultBackground) - } - if st.GetIsShaded() { - tst = tst.Dim(true) - tst = tst.Background(tcell.ColorGray) - } - // TODO StyleFlags - return tst -} - -type StyleFlags uint32 - -func (sf StyleFlags) GetIsDim() bool { - return (sf & StyleFlagDim) != 0 -} - -func (sf *StyleFlags) SetIsDim(id bool) { - if id { - *sf |= StyleFlagDim - } else { - *sf &= ^StyleFlagDim - } -} - -func (sf StyleFlags) GetIsShaded() bool { - return (sf & StyleFlagShaded) != 0 -} - -func (sf *StyleFlags) SetIsShaded(id bool) { - if id { - *sf |= StyleFlagShaded - } else { - *sf &= ^StyleFlagShaded - } -} - -const StyleFlagNone StyleFlags = 0 - -const ( - StyleFlagBold StyleFlags = 1 << iota - StyleFlagDim - StyleFlagShaded - StyleFlagBlink - StyleFlagUnderline - StyleFlagItalic - StyleFlagStrikeThrough -) - -// Attrs have side effects in the Logos system; -// for example, the lone cursor element (one with AttrFlagIsCursor set) -// is where most key events are sent to. -type Attrs struct { - Parent Elem - AttrFlags - Other []KVPair -} - -func (tt *Attrs) GetAttrs() *Attrs { - return tt -} - -func (tt *Attrs) GetParent() Elem { - return tt.Parent -} - -func (tt *Attrs) SetParent(p Elem) { - if tt.Parent != nil && tt.Parent != p { - panic("parent already set") - } - tt.Parent = p -} - -func (tt *Attrs) GetIsCursor() bool { - return (tt.AttrFlags & AttrFlagIsCursor) != 0 -} - -func (tt *Attrs) SetIsCursor(ic bool) { - if ic { - tt.AttrFlags |= AttrFlagIsCursor - } else { - tt.AttrFlags &= ^AttrFlagIsCursor - } - tt.SetIsDirty(true) -} - -func (tt *Attrs) GetIsDirty() bool { - return (tt.AttrFlags & AttrFlagIsDirty) != 0 -} - -func (tt *Attrs) SetIsDirty(id bool) { - if id { - tt.AttrFlags |= AttrFlagIsDirty - if tt.Parent != nil { - tt.Parent.SetIsDirty(true) - } - } else { - tt.AttrFlags &= ^AttrFlagIsDirty - } -} - -func (tt *Attrs) GetIsOccluded() bool { - return (tt.AttrFlags & AttrFlagIsOccluded) != 0 -} - -func (tt *Attrs) SetIsOccluded(ic bool) { - if ic { - tt.AttrFlags |= AttrFlagIsOccluded - } else { - tt.AttrFlags &= ^AttrFlagIsOccluded - } - tt.SetIsDirty(true) -} - -func (tt *Attrs) Merge(ot *Attrs) { - if ot.Parent != nil { - tt.Parent = ot.Parent - } - tt.AttrFlags |= ot.AttrFlags - tt.Other = ot.Other // TODO merge by key. -} - -// ---------------------------------------- -// AttrFlags - -// NOTE: AttrFlags are merged with a simple or-assign op. -type AttrFlags uint32 - -func (af AttrFlags) GetAttrFlags() AttrFlags { - return af -} - -const AttrFlagNone AttrFlags = 0 - -const ( - AttrFlagIsCursor AttrFlags = 1 << iota // is current cursor - AttrFlagIsSelected // is selected (among possibly others) - AttrFlagIsOccluded // is hidden due to stack - AttrFlagIsDirty // is dirty (not yet used) -) - -type KVPair struct { - Key string - Value interface{} -} - -// ---------------------------------------- -// computeIntersection() - -// els: element size -// elo: offset within element -// vws: view size -// minX,maxX,minY,maxY are relative to el. -// maxX and maxY are exclusive. -func computeIntersection(els Size, elo Coord, vws Size) (minX, maxX, minY, maxY int) { - if elo.X < 0 { - /* - View - +----------+ - | [Elem__|____] - +----------+ - x 0 - */ - minX = 0 - } else { - /* - View - +----------+ - [____|__Elem] | - +----------+ - 0 x - */ - minX = elo.X - } - if els.Width <= vws.Width+elo.X { - /* - View - +----------+ - [____|__Elem] | - +----------+ - W w+x - */ - maxX = els.Width - } else { - /* - View - +----------+ - | [Elem__|____] - +----------+ - w+x W - */ - maxX = vws.Width + elo.X - } - if elo.Y < 0 { - minY = 0 - } else { - minY = elo.Y - } - if els.Height <= vws.Height+elo.Y { - maxY = els.Height - } else { - maxY = vws.Height + elo.Y - } - return -} - -// ---------------------------------------- -// Misc simple types - -type Padding struct { - Left int - Top int - Right int - Bottom int -} - -func (pd Padding) GetPadding() Padding { - return pd -} - -// A border can only have width 0 or 1, and is part of the padding. -// Each string should represent a character of width 1. -type Border struct { - Corners [4]string // starts upper-left and clockwise, "" draws no corner. - TopLine []string // nil if no top border. - BotLine []string // nil if no bottom border. - LeftLine []string // nil if no left border. - RightLine []string // nil if no right border. -} - -func DefaultBorder() Border { - return Border{ - Corners: [4]string{ - string(tcell.RuneULCorner), - string(tcell.RuneURCorner), - string(tcell.RuneLRCorner), - string(tcell.RuneLLCorner), - }, - TopLine: []string{string(tcell.RuneHLine)}, - BotLine: []string{string(tcell.RuneHLine)}, - LeftLine: []string{string(tcell.RuneVLine)}, - RightLine: []string{string(tcell.RuneVLine)}, - } -} - -func LeftBorder() Border { - return Border{ - Corners: [4]string{ - string("\u2553"), - "", - "", - string("\u2559"), - }, - LeftLine: []string{ - string("\u2551"), - }, - } -} - -func orSpace(chr string) string { - if chr == "" { - return " " - } else { - return chr - } -} - -func (br *Border) GetCorner(i int) string { - if br == nil { - return " " - } else { - return orSpace(br.Corners[i]) - } -} - -func (br *Border) TLCorner() string { - return br.GetCorner(0) -} - -func (br *Border) TRCorner() string { - return br.GetCorner(1) -} - -func (br *Border) BRCorner() string { - return br.GetCorner(2) -} - -func (br *Border) BLCorner() string { - return br.GetCorner(3) -} - -func (br *Border) TopBorder(x int) string { - if br == nil || br.TopLine == nil { - return " " - } else { - return br.TopLine[x%len(br.TopLine)] - } -} - -func (br *Border) BottomBorder(x int) string { - if br == nil || br.BotLine == nil { - return " " - } else { - return br.BotLine[x%len(br.BotLine)] - } -} - -func (br *Border) LeftBorder(y int) string { - if br == nil || br.LeftLine == nil { - return " " - } else { - return br.LeftLine[y%len(br.LeftLine)] - } -} - -func (br *Border) RightBorder(y int) string { - if br == nil || br.RightLine == nil { - return " " - } else { - return br.RightLine[y%len(br.RightLine)] - } -} - -type Size struct { - Width int - Height int // -1 if not set. -} - -func (sz Size) String() string { - return fmt.Sprintf("{%d,%d}", sz.Width, sz.Height) -} - -func (sz Size) IsZero() bool { - return sz.Width == 0 && sz.Height == 0 -} - -func (sz Size) GetSize() Size { - return sz -} - -// zero widths or heights are valid. -func (sz Size) IsValid() bool { - return 0 <= sz.Width && 0 <= sz.Height -} - -func (sz Size) IsPositive() bool { - return 0 < sz.Width && 0 < sz.Height -} - -func (sz Size) SubCoord(crd Coord) Size { - if !crd.IsNonNegative() { - panic("should not happen") - } - sz2 := Size{ - Width: sz.Width - crd.X, - Height: sz.Height - crd.Y, - } - if !sz2.IsValid() { - panic("should not happen") - } - return sz2 -} - -type Coord struct { - X int - Y int -} - -func (crd Coord) GetCoord() Coord { - return crd -} - -func (crd *Coord) SetCoord(nc Coord) { - *crd = nc -} - -func (crd Coord) IsNonNegative() bool { - return 0 <= crd.X && 0 <= crd.Y -} - -func (crd Coord) Neg() Coord { - return Coord{ - X: -crd.X, - Y: -crd.Y, - } -} - -func (crd Coord) Add(crd2 Coord) Coord { - return Coord{ - X: crd.X + crd2.X, - Y: crd.Y + crd2.Y, - } -} - -func (crd Coord) Sub(crd2 Coord) Coord { - return Coord{ - X: crd.X - crd2.X, - Y: crd.Y - crd2.Y, - } -} diff --git a/misc/logos/types_test.go b/misc/logos/types_test.go deleted file mode 100644 index 5960783dc34..00000000000 --- a/misc/logos/types_test.go +++ /dev/null @@ -1,47 +0,0 @@ -package logos - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func TestNewPage1(t *testing.T) { - page := NewPage("this is a new string", 40, false, nil) - require.NotNil(t, page) - size := page.Size - require.Equal(t, Size{Width: 20, Height: 1}, size) -} - -func TestNewPage2(t *testing.T) { - page := NewPage("this is a new string", 10, false, nil) - require.NotNil(t, page) - size := page.Size - /* - 0123456789 - this is a - new string - */ - require.Equal(t, Size{Width: 10, Height: 2}, size) - require.Equal(t, Coord{0, 0}, page.Elems[0].GetCoord()) - require.Equal(t, Coord{5, 0}, page.Elems[1].GetCoord()) - require.Equal(t, Coord{8, 0}, page.Elems[2].GetCoord()) - require.Equal(t, Coord{0, 1}, page.Elems[3].GetCoord()) - require.Equal(t, Coord{4, 1}, page.Elems[4].GetCoord()) - require.Equal(t, 5, len(page.Elems)) -} - -func TestNewPageSprint(t *testing.T) { - t.Skip("test failing") - page := NewPage("this is a new string", 10, false, nil) - require.NotNil(t, page) - /* - 0123456789 - this is a - new string - */ - bpv := NewBufferedElemView(page, Size{}) - bpv.Render() - out := bpv.Sprint() - require.Equal(t, "this is a \nnew string", out) -} diff --git a/misc/logos/unicode.go b/misc/logos/unicode.go deleted file mode 100644 index 924edecc2c5..00000000000 --- a/misc/logos/unicode.go +++ /dev/null @@ -1,86 +0,0 @@ -package logos - -func isCombining(r rune) bool { - return inTable(r, combining) -} - -// ---------------------------------------- -// from https://github.com/mattn/go-runewidth -// runewidth doesn't expose whether a character is combining or not. -// TODO might as well fork both runewidth and tcell. - -var combining = table{ - {0x0300, 0x036F}, - {0x0483, 0x0489}, - {0x07EB, 0x07F3}, - {0x0C00, 0x0C00}, - {0x0C04, 0x0C04}, - {0x0D00, 0x0D01}, - {0x135D, 0x135F}, - {0x1A7F, 0x1A7F}, - {0x1AB0, 0x1AC0}, - {0x1B6B, 0x1B73}, - {0x1DC0, 0x1DF9}, - {0x1DFB, 0x1DFF}, - {0x20D0, 0x20F0}, - {0x2CEF, 0x2CF1}, - {0x2DE0, 0x2DFF}, - {0x3099, 0x309A}, - {0xA66F, 0xA672}, - {0xA674, 0xA67D}, - {0xA69E, 0xA69F}, - {0xA6F0, 0xA6F1}, - {0xA8E0, 0xA8F1}, - {0xFE20, 0xFE2F}, - {0x101FD, 0x101FD}, - {0x10376, 0x1037A}, - {0x10EAB, 0x10EAC}, - {0x10F46, 0x10F50}, - {0x11300, 0x11301}, - {0x1133B, 0x1133C}, - {0x11366, 0x1136C}, - {0x11370, 0x11374}, - {0x16AF0, 0x16AF4}, - {0x1D165, 0x1D169}, - {0x1D16D, 0x1D172}, - {0x1D17B, 0x1D182}, - {0x1D185, 0x1D18B}, - {0x1D1AA, 0x1D1AD}, - {0x1D242, 0x1D244}, - {0x1E000, 0x1E006}, - {0x1E008, 0x1E018}, - {0x1E01B, 0x1E021}, - {0x1E023, 0x1E024}, - {0x1E026, 0x1E02A}, - {0x1E8D0, 0x1E8D6}, -} - -type interval struct { - first rune - last rune -} - -type table []interval - -func inTable(r rune, t table) bool { - if r < t[0].first { - return false - } - - bot := 0 - top := len(t) - 1 - for top >= bot { - mid := (bot + top) >> 1 - - switch { - case t[mid].last < r: - bot = mid + 1 - case t[mid].first > r: - top = mid - 1 - default: - return true - } - } - - return false -} diff --git a/misc/loop/Dockerfile b/misc/loop/Dockerfile deleted file mode 100644 index 219a47927db..00000000000 --- a/misc/loop/Dockerfile +++ /dev/null @@ -1,19 +0,0 @@ -FROM golang:alpine AS builder - -COPY . /go/src/github.com/gnolang/gno/misc/loop - -WORKDIR /go/src/github.com/gnolang/gno/misc/loop - -RUN --mount=type=cache,target=/root/.cache/go-build \ - --mount=type=cache,target=/root/go/pkg/mod \ - go build -o /build/portalloopd ./cmd - -# Final image for portalloopd -FROM docker AS portalloopd - -RUN apk add bash curl jq - -COPY --from=builder /build/portalloopd /usr/bin/portalloopd - -ENTRYPOINT [ "/usr/bin/portalloopd" ] -CMD [ "serve" ] diff --git a/misc/loop/cmd/snapshotter.go b/misc/loop/cmd/snapshotter.go index 8ace34c7ba6..06562e2c5c5 100644 --- a/misc/loop/cmd/snapshotter.go +++ b/misc/loop/cmd/snapshotter.go @@ -19,7 +19,7 @@ import ( "github.com/docker/go-connections/nat" "github.com/gnolang/tx-archive/backup" "github.com/gnolang/tx-archive/backup/client/http" - "github.com/gnolang/tx-archive/backup/writer/legacy" + "github.com/gnolang/tx-archive/backup/writer/standard" ) const ( @@ -204,7 +204,7 @@ func (s snapshotter) backupTXs(ctx context.Context, rpcURL string) error { } defer instanceBackupFile.Close() - w := legacy.NewWriter(instanceBackupFile) + w := standard.NewWriter(instanceBackupFile) // Create the tx-archive backup service c, err := http.NewClient(rpcURL) diff --git a/misc/loop/docker-compose.yml b/misc/loop/docker-compose.yml index eba0f55e787..ed2fe7192f5 100644 --- a/misc/loop/docker-compose.yml +++ b/misc/loop/docker-compose.yml @@ -68,7 +68,7 @@ services: portalloopd: build: - context: . + context: ../.. target: portalloopd restart: unless-stopped volumes: diff --git a/misc/loop/go.mod b/misc/loop/go.mod index be37c21f5c9..9fc5bfb2d57 100644 --- a/misc/loop/go.mod +++ b/misc/loop/go.mod @@ -7,22 +7,23 @@ toolchain go1.22.4 require ( github.com/docker/docker v24.0.7+incompatible github.com/docker/go-connections v0.4.0 - github.com/gnolang/gno v0.1.0-nightly.20240707 - github.com/gnolang/tx-archive v0.3.0 + github.com/gnolang/gno v0.1.0-nightly.20240627 + github.com/gnolang/tx-archive v0.4.0 github.com/prometheus/client_golang v1.17.0 github.com/sirupsen/logrus v1.9.3 ) +replace github.com/gnolang/gno => ../.. + require ( - dario.cat/mergo v1.0.0 // indirect + dario.cat/mergo v1.0.1 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/btcsuite/btcd/btcec/v2 v2.3.3 // indirect - github.com/btcsuite/btcd/btcutil v1.1.5 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/btcsuite/btcd/btcutil v1.1.6 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cockroachdb/apd/v3 v3.2.1 // indirect - github.com/cosmos/ledger-cosmos-go v0.13.3 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect github.com/distribution/reference v0.5.0 // indirect @@ -35,8 +36,8 @@ require ( github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/gorilla/websocket v1.5.1 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect + github.com/gorilla/websocket v1.5.3 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/moby/term v0.5.0 // indirect @@ -50,37 +51,35 @@ require ( github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect github.com/prometheus/common v0.44.0 // indirect github.com/prometheus/procfs v0.11.1 // indirect - github.com/rs/cors v1.11.0 // indirect - github.com/rs/xid v1.5.0 // indirect + github.com/rs/cors v1.11.1 // indirect + github.com/rs/xid v1.6.0 // indirect github.com/stretchr/testify v1.9.0 // indirect github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect - github.com/zondax/hid v0.9.2 // indirect - github.com/zondax/ledger-go v0.14.3 // indirect - go.etcd.io/bbolt v1.3.9 // indirect - go.opentelemetry.io/otel v1.28.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.28.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.28.0 // indirect - go.opentelemetry.io/otel/metric v1.28.0 // indirect - go.opentelemetry.io/otel/sdk v1.28.0 // indirect - go.opentelemetry.io/otel/sdk/metric v1.28.0 // indirect - go.opentelemetry.io/otel/trace v1.28.0 // indirect + go.etcd.io/bbolt v1.3.11 // indirect + go.opentelemetry.io/otel v1.29.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.29.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.29.0 // indirect + go.opentelemetry.io/otel/metric v1.29.0 // indirect + go.opentelemetry.io/otel/sdk v1.29.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.29.0 // indirect + go.opentelemetry.io/otel/trace v1.29.0 // indirect go.opentelemetry.io/proto/otlp v1.3.1 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect go.uber.org/zap/exp v0.2.0 // indirect - golang.org/x/crypto v0.25.0 // indirect + golang.org/x/crypto v0.26.0 // indirect golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 // indirect - golang.org/x/mod v0.19.0 // indirect - golang.org/x/net v0.27.0 // indirect - golang.org/x/sys v0.22.0 // indirect - golang.org/x/term v0.22.0 // indirect - golang.org/x/text v0.16.0 // indirect + golang.org/x/mod v0.20.0 // indirect + golang.org/x/net v0.28.0 // indirect + golang.org/x/sys v0.24.0 // indirect + golang.org/x/term v0.23.0 // indirect + golang.org/x/text v0.17.0 // indirect golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.22.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect + golang.org/x/tools v0.24.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd // indirect google.golang.org/grpc v1.65.0 // indirect - google.golang.org/protobuf v1.34.2 // indirect + google.golang.org/protobuf v1.35.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gotest.tools/v3 v3.5.1 // indirect ) diff --git a/misc/loop/go.sum b/misc/loop/go.sum index 2ad488a5f25..27ed94fecae 100644 --- a/misc/loop/go.sum +++ b/misc/loop/go.sum @@ -1,5 +1,5 @@ -dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= -dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= +dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= @@ -9,16 +9,18 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/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.5-0.20231215221805-96c9fd8078fd h1:js1gPwhcFflTZ7Nzl7WHaOTlTr5hIrR4n1NM4v9n4Kw= github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= +github.com/btcsuite/btcd v0.24.2 h1:aLmxPguqxza+4ag8R1I2nnJjSu2iFn/kqtHTIImswcY= +github.com/btcsuite/btcd v0.24.2/go.mod h1:5C8ChTkl5ejr3WHj8tkQSCmydiMEPB0ZhQhehpq7Dgg= github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= -github.com/btcsuite/btcd/btcec/v2 v2.3.3 h1:6+iXlDKE8RMtKsvK0gshlXIuPbyWM/h84Ensb7o3sC0= -github.com/btcsuite/btcd/btcec/v2 v2.3.3/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= -github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8= github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= +github.com/btcsuite/btcd/btcutil v1.1.6 h1:zFL2+c3Lb9gEgqKNzowKUPQNb8jV7v5Oaodi/AYFd6c= +github.com/btcsuite/btcd/btcutil v1.1.6/go.mod h1:9dFymx8HpuLqBnsPELrImQeTQfKBQqzqGbbV3jK55aE= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= @@ -66,12 +68,10 @@ github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHqu github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/gnolang/gno v0.1.0-nightly.20240707 h1:ez1BtiwRuqRHRxvqyKDbUbNtUBYEjXwSHqRu6m347os= -github.com/gnolang/gno v0.1.0-nightly.20240707/go.mod h1:BTaBNeaoY/W95NN6QA4RCoQ6Z7mi8M+Zb1I1wMWGg2w= github.com/gnolang/overflow v0.0.0-20170615021017-4d914c927216 h1:GKvsK3oLWG9B1GL7WP/VqwM6C92j5tIvB844oggL9Lk= github.com/gnolang/overflow v0.0.0-20170615021017-4d914c927216/go.mod h1:xJhtEL7ahjM1WJipt89gel8tHzfIl/LyMY+lCYh38d8= -github.com/gnolang/tx-archive v0.3.0 h1:5Fr39yAT7nnAPKvcmKmBT+oPiBhMhA0aUAIEeXrYG4I= -github.com/gnolang/tx-archive v0.3.0/go.mod h1:WDgxSZibE7LkGdiVjkU/lhA35xyXjrSkZp6kwuTvSSw= +github.com/gnolang/tx-archive v0.4.0 h1:+1Rgo0U0HjLQLq/xqeGdJwtAzo9xWj09t1oZLvrL3bU= +github.com/gnolang/tx-archive v0.4.0/go.mod h1:seKHGnvxUnDgH/mSsCEdwG0dHY/FrpbUm6Hd0+KMd9w= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -100,10 +100,10 @@ github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 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= @@ -160,14 +160,19 @@ github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwa github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= -github.com/rs/cors v1.11.0 h1:0B9GE/r9Bc2UxRMMtymBkHTenPkHDv0CW4Y98GBY+po= -github.com/rs/cors v1.11.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= -github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc= -github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= +github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU= +github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= @@ -178,22 +183,22 @@ github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw= github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI= -go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI= -go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE= -go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= -go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.28.0 h1:U2guen0GhqH8o/G2un8f/aG/y++OuW6MyCo6hT9prXk= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.28.0/go.mod h1:yeGZANgEcpdx/WK0IvvRFC+2oLiMS2u4L/0Rj2M2Qr0= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.28.0 h1:aLmmtjRke7LPDQ3lvpFz+kNEH43faFhzW7v8BFIEydg= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.28.0/go.mod h1:TC1pyCt6G9Sjb4bQpShH+P5R53pO6ZuGnHuuln9xMeE= -go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= -go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= -go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= -go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= -go.opentelemetry.io/otel/sdk/metric v1.28.0 h1:OkuaKgKrgAbYrrY0t92c+cC+2F6hsFNnCQArXCKlg08= -go.opentelemetry.io/otel/sdk/metric v1.28.0/go.mod h1:cWPjykihLAPvXKi4iZc1dpER3Jdq2Z0YLse3moQUCpg= -go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= -go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= +go.etcd.io/bbolt v1.3.11 h1:yGEzV1wPz2yVCLsD8ZAiGHhHVlczyC9d1rP43/VCRJ0= +go.etcd.io/bbolt v1.3.11/go.mod h1:dksAq7YMXoljX0xu6VF5DMZGbhYYoLUalEiSySYAS4I= +go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw= +go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.29.0 h1:k6fQVDQexDE+3jG2SfCQjnHS7OamcP73YMoxEVq5B6k= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.29.0/go.mod h1:t4BrYLHU450Zo9fnydWlIuswB1bm7rM8havDpWOJeDo= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.29.0 h1:xvhQxJ/C9+RTnAj5DpTg7LSM1vbbMTiXt7e9hsfqHNw= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.29.0/go.mod h1:Fcvs2Bz1jkDM+Wf5/ozBGmi3tQ/c9zPKLnsipnfhGAo= +go.opentelemetry.io/otel/metric v1.29.0 h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc= +go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8= +go.opentelemetry.io/otel/sdk v1.29.0 h1:vkqKjk7gwhS8VaWb0POZKmIEDimRCMsopNYnriHyryo= +go.opentelemetry.io/otel/sdk v1.29.0/go.mod h1:pM8Dx5WKnvxLCb+8lG1PRNIDxu9g9b9g59Qr7hfAAok= +go.opentelemetry.io/otel/sdk/metric v1.29.0 h1:K2CfmJohnRgvZ9UAj2/FhIf/okdWcNdBwe1m8xFXiSY= +go.opentelemetry.io/otel/sdk/metric v1.29.0/go.mod h1:6zZLdCl2fkauYoZIOn/soQIDSWFmNSRcICarHfuhNJQ= +go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt39JTi4= +go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ= go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -208,14 +213,14 @@ golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= -golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= +golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= +golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY= golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= -golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -224,15 +229,15 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -244,32 +249,32 @@ golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= -golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= +golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= +golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= +golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= -golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0= -google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094/go.mod h1:fJ/e3If/Q67Mj99hin0hMhiNyCRmt6BQ2aWIJshUSJw= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= +google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd h1:BBOTEWLuuEGQy9n1y9MhVJ9Qt0BDu21X8qZs71/uPZo= +google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:fO8wJzT2zbQbAjbIoos1285VfEIYKDDY+Dt+WpTkh6g= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd h1:6TEm2ZxXoQmFWFlt1vNxvVOa1Q0dXFQD1m/rYjXmS0E= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -278,8 +283,8 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/tm2/README.md b/tm2/README.md index 0f6e0052933..2addfe8f550 100644 --- a/tm2/README.md +++ b/tm2/README.md @@ -35,7 +35,7 @@ - MISSION: be the basis for improving the encoding standard from proto3, because proto3 length-prefixing is slow, and we need "proto4" or "amino2". - LOOK at the auto-generated proto files! - https://github.com/gnolang/gno/blob/master/pkgs/bft/consensus/types/cstypes.proto + https://github.com/gnolang/gno/blob/master/tm2/pkg/bft/consensus/types/cstypes.proto for example. - There was work to remove this from the CosmosSDK because Amino wasn't ready, but now that it is, it makes sense to incorporate it into diff --git a/tm2/pkg/amino/amino.go b/tm2/pkg/amino/amino.go index ecff955a582..262f5d9a54e 100644 --- a/tm2/pkg/amino/amino.go +++ b/tm2/pkg/amino/amino.go @@ -130,7 +130,7 @@ func UnmarshalAnySized(bz []byte, ptr interface{}) error { } func MarshalJSON(o interface{}) ([]byte, error) { - return gcdc.MarshalJSON(o) + return gcdc.JSONMarshal(o) } func MarshalJSONAny(o interface{}) ([]byte, error) { @@ -146,7 +146,7 @@ func MustMarshalJSONAny(o interface{}) []byte { } func UnmarshalJSON(bz []byte, ptr interface{}) error { - return gcdc.UnmarshalJSON(bz, ptr) + return gcdc.JSONUnmarshal(bz, ptr) } func MustUnmarshalJSON(bz []byte, ptr interface{}) { @@ -756,11 +756,11 @@ func (cdc *Codec) MustUnmarshalAny(bz []byte, ptr interface{}) { return } -func (cdc *Codec) MarshalJSON(o interface{}) ([]byte, error) { +func (cdc *Codec) JSONMarshal(o interface{}) ([]byte, error) { cdc.doAutoseal() rv := reflect.ValueOf(o) - if rv.Kind() == reflect.Invalid { + if !rv.IsValid() { return []byte("null"), nil } rt := rv.Type() @@ -814,7 +814,7 @@ func (cdc *Codec) MarshalJSONAny(o interface{}) ([]byte, error) { // MustMarshalJSON panics if an error occurs. Besides tha behaves exactly like MarshalJSON. func (cdc *Codec) MustMarshalJSON(o interface{}) []byte { - bz, err := cdc.MarshalJSON(o) + bz, err := cdc.JSONMarshal(o) if err != nil { panic(err) } @@ -830,7 +830,7 @@ func (cdc *Codec) MustMarshalJSONAny(o interface{}) []byte { return bz } -func (cdc *Codec) UnmarshalJSON(bz []byte, ptr interface{}) error { +func (cdc *Codec) JSONUnmarshal(bz []byte, ptr interface{}) error { cdc.doAutoseal() if len(bz) == 0 { return errors.New("cannot decode empty bytes") @@ -851,7 +851,7 @@ func (cdc *Codec) UnmarshalJSON(bz []byte, ptr interface{}) error { // MustUnmarshalJSON panics if an error occurs. Besides tha behaves exactly like UnmarshalJSON. func (cdc *Codec) MustUnmarshalJSON(bz []byte, ptr interface{}) { - if err := cdc.UnmarshalJSON(bz, ptr); err != nil { + if err := cdc.JSONUnmarshal(bz, ptr); err != nil { panic(err) } } @@ -859,7 +859,7 @@ func (cdc *Codec) MustUnmarshalJSON(bz []byte, ptr interface{}) { // MarshalJSONIndent calls json.Indent on the output of cdc.MarshalJSON // using the given prefix and indent string. func (cdc *Codec) MarshalJSONIndent(o interface{}, prefix, indent string) ([]byte, error) { - bz, err := cdc.MarshalJSON(o) + bz, err := cdc.JSONMarshal(o) if err != nil { return nil, err } diff --git a/tm2/pkg/amino/benchmark_test.go b/tm2/pkg/amino/benchmark_test.go index 1edeb8d6fa9..a1489b36b44 100644 --- a/tm2/pkg/amino/benchmark_test.go +++ b/tm2/pkg/amino/benchmark_test.go @@ -103,7 +103,7 @@ func _benchmarkBinary(b *testing.B, cdc *amino.Codec, rt reflect.Type, codecType case "binary": bz, err = cdc.Marshal(ptr) case "json": - bz, err = cdc.MarshalJSON(ptr) + bz, err = cdc.JSONMarshal(ptr) case "binary_pb": bz, err = pbcdc.Marshal(ptr) case "binary_pb_translate_only": @@ -129,7 +129,7 @@ func _benchmarkBinary(b *testing.B, cdc *amino.Codec, rt reflect.Type, codecType case "binary": err = cdc.Unmarshal(bz, ptr2) case "json": - err = cdc.UnmarshalJSON(bz, ptr2) + err = cdc.JSONUnmarshal(bz, ptr2) case "binary_pb": err = pbcdc.Unmarshal(bz, ptr2) case "binary_pb_translate_only": diff --git a/tm2/pkg/amino/cmd/aminoscan/colors.go b/tm2/pkg/amino/cmd/aminoscan/colors.go index 8dee9aed1f2..89f05a6a0cb 100644 --- a/tm2/pkg/amino/cmd/aminoscan/colors.go +++ b/tm2/pkg/amino/cmd/aminoscan/colors.go @@ -28,7 +28,7 @@ func treat(s string, color string) string { } func treatAll(color string, args ...interface{}) string { - parts := make([]string, len(args)) + parts := make([]string, 0, len(args)) for _, arg := range args { parts = append(parts, treat(fmt.Sprintf("%v", arg), color)) } diff --git a/tm2/pkg/amino/json_test.go b/tm2/pkg/amino/json_test.go index e3f7d413fcb..e749522218a 100644 --- a/tm2/pkg/amino/json_test.go +++ b/tm2/pkg/amino/json_test.go @@ -12,8 +12,10 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "google.golang.org/protobuf/types/known/durationpb" + "google.golang.org/protobuf/types/known/timestamppb" - amino "github.com/gnolang/gno/tm2/pkg/amino" + "github.com/gnolang/gno/tm2/pkg/amino" "github.com/gnolang/gno/tm2/pkg/amino/pkg" ) @@ -112,7 +114,7 @@ func TestMarshalJSON(t *testing.T) { for i, tt := range cases { t.Logf("Trying case #%v", i) - blob, err := cdc.MarshalJSON(tt.in) + blob, err := cdc.JSONMarshal(tt.in) if tt.wantErr != "" { if err == nil || !strings.Contains(err.Error(), tt.wantErr) { t.Errorf("#%d:\ngot:\n\t%v\nwant non-nil error containing\n\t%q", i, @@ -149,11 +151,36 @@ func TestMarshalJSONTime(t *testing.T) { Time: time.Now().Round(0).UTC(), // strip monotonic. } - b, err := cdc.MarshalJSON(s) + b, err := cdc.JSONMarshal(s) assert.Nil(t, err) var s2 SimpleStruct - err = cdc.UnmarshalJSON(b, &s2) + err = cdc.JSONUnmarshal(b, &s2) + assert.Nil(t, err) + assert.Equal(t, s, s2) +} + +func TestMarshalJSONPBTime(t *testing.T) { + t.Parallel() + + cdc := amino.NewCodec() + registerTransports(cdc) + + type SimpleStruct struct { + Timestamp *timestamppb.Timestamp + Duration *durationpb.Duration + } + + s := SimpleStruct{ + Timestamp: ×tamppb.Timestamp{Seconds: 1296012345, Nanos: 940483}, + Duration: &durationpb.Duration{Seconds: 100}, + } + + b, err := cdc.JSONMarshal(s) + assert.Nil(t, err) + + var s2 SimpleStruct + err = cdc.JSONUnmarshal(b, &s2) assert.Nil(t, err) assert.Equal(t, s, s2) } @@ -190,15 +217,15 @@ func TestUnmarshalMap(t *testing.T) { obj := new(map[string]int) cdc := amino.NewCodec() assert.Panics(t, func() { - err := cdc.UnmarshalJSON(jsonBytes, &obj) + err := cdc.JSONUnmarshal(jsonBytes, &obj) assert.Fail(t, "should have panicked but got err: %v", err) }) assert.Panics(t, func() { - err := cdc.UnmarshalJSON(jsonBytes, obj) + err := cdc.JSONUnmarshal(jsonBytes, obj) assert.Fail(t, "should have panicked but got err: %v", err) }) assert.Panics(t, func() { - bz, err := cdc.MarshalJSON(obj) + bz, err := cdc.JSONMarshal(obj) assert.Fail(t, "should have panicked but got bz: %X err: %v", bz, err) }) } @@ -210,22 +237,22 @@ func TestUnmarshalFunc(t *testing.T) { obj := func() {} cdc := amino.NewCodec() assert.Panics(t, func() { - err := cdc.UnmarshalJSON(jsonBytes, &obj) + err := cdc.JSONUnmarshal(jsonBytes, &obj) assert.Fail(t, "should have panicked but got err: %v", err) }) - err := cdc.UnmarshalJSON(jsonBytes, obj) - // UnmarshalJSON expects a pointer + err := cdc.JSONUnmarshal(jsonBytes, obj) + // JSONUnmarshal expects a pointer assert.Error(t, err) // ... nor encoding it. assert.Panics(t, func() { - bz, err := cdc.MarshalJSON(obj) + bz, err := cdc.JSONMarshal(obj) assert.Fail(t, "should have panicked but got bz: %X err: %v", bz, err) }) } -func TestUnmarshalJSON(t *testing.T) { +func TestJSONUnmarshal(t *testing.T) { t.Parallel() cdc := amino.NewCodec() @@ -296,7 +323,7 @@ func TestUnmarshalJSON(t *testing.T) { } for i, tt := range cases { - err := cdc.UnmarshalJSON([]byte(tt.blob), tt.in) + err := cdc.JSONUnmarshal([]byte(tt.blob), tt.in) if tt.wantErr != "" { if err == nil || !strings.Contains(err.Error(), tt.wantErr) { t.Errorf("#%d:\ngot:\n\t%q\nwant non-nil error containing\n\t%q", i, @@ -363,7 +390,7 @@ func TestJSONCodecRoundTrip(t *testing.T) { } for i, tt := range cases { - mBlob, err := cdc.MarshalJSON(tt.in) + mBlob, err := cdc.JSONMarshal(tt.in) if tt.wantErr != "" { if err == nil || !strings.Contains(err.Error(), tt.wantErr) { t.Errorf("#%d:\ngot:\n\t%q\nwant non-nil error containing\n\t%q", i, @@ -373,27 +400,27 @@ func TestJSONCodecRoundTrip(t *testing.T) { } if err != nil { - t.Errorf("#%d: unexpected error after MarshalJSON: %v", i, err) + t.Errorf("#%d: unexpected error after JSONMarshal: %v", i, err) continue } - if err = cdc.UnmarshalJSON(mBlob, tt.out); err != nil { - t.Errorf("#%d: unexpected error after UnmarshalJSON: %v\nmBlob: %s", i, err, mBlob) + if err = cdc.JSONUnmarshal(mBlob, tt.out); err != nil { + t.Errorf("#%d: unexpected error after JSONUnmarshal: %v\nmBlob: %s", i, err, mBlob) continue } // Now check that the input is exactly equal to the output - uBlob, err := cdc.MarshalJSON(tt.out) + uBlob, err := cdc.JSONMarshal(tt.out) assert.NoError(t, err) - if err := cdc.UnmarshalJSON(mBlob, tt.out); err != nil { - t.Errorf("#%d: unexpected error after second MarshalJSON: %v", i, err) + if err := cdc.JSONUnmarshal(mBlob, tt.out); err != nil { + t.Errorf("#%d: unexpected error after second JSONMarshal: %v", i, err) continue } if !reflect.DeepEqual(tt.want, tt.out) { - t.Errorf("#%d: After roundtrip UnmarshalJSON\ngot: \t%v\nwant:\t%v", i, tt.out, tt.want) + t.Errorf("#%d: After roundtrip JSONUnmarshal\ngot: \t%v\nwant:\t%v", i, tt.out, tt.want) } if !bytes.Equal(mBlob, uBlob) { - t.Errorf("#%d: After roundtrip MarshalJSON\ngot: \t%s\nwant:\t%s", i, uBlob, mBlob) + t.Errorf("#%d: After roundtrip JSONMarshal\ngot: \t%s\nwant:\t%s", i, uBlob, mBlob) } } } @@ -499,10 +526,10 @@ func TestAminoJSONTimeEncodeDecodeRoundTrip(t *testing.T) { din := time.Date(2008, 9, 15, 14, 13, 12, 11109876, loc).Round(time.Millisecond).UTC() cdc := amino.NewCodec() - blobAmino, err := cdc.MarshalJSON(din) - require.Nil(t, err, "amino.Codec.MarshalJSON should succeed") + blobAmino, err := cdc.JSONMarshal(din) + require.Nil(t, err, "amino.Codec.JSONMarshal should succeed") var tAminoOut time.Time - require.Nil(t, cdc.UnmarshalJSON(blobAmino, &tAminoOut), "amino.Codec.UnmarshalJSON should succeed") + require.Nil(t, cdc.JSONUnmarshal(blobAmino, &tAminoOut), "amino.Codec.JSONUnmarshal should succeed") require.NotEqual(t, tAminoOut, time.Time{}, "amino.marshaled definitely isn't equal to zero time") require.Equal(t, tAminoOut, din, "expecting marshaled in to be equal to marshaled out") diff --git a/tm2/pkg/amino/reflect_test.go b/tm2/pkg/amino/reflect_test.go index bd815c8b9a6..475930e540c 100644 --- a/tm2/pkg/amino/reflect_test.go +++ b/tm2/pkg/amino/reflect_test.go @@ -120,7 +120,7 @@ func _testCodec(t *testing.T, rt reflect.Type, codecType string) { case "binary": bz, err = cdc.Marshal(ptr) case "json": - bz, err = cdc.MarshalJSON(ptr) + bz, err = cdc.JSONMarshal(ptr) default: panic("should not happen") } @@ -133,7 +133,7 @@ func _testCodec(t *testing.T, rt reflect.Type, codecType string) { case "binary": err = cdc.Unmarshal(bz, ptr2) case "json": - err = cdc.UnmarshalJSON(bz, ptr2) + err = cdc.JSONUnmarshal(bz, ptr2) default: panic("should not happen") } @@ -427,7 +427,7 @@ func TestCodecJSONRoundtripNonNilRegisteredTypeDef(t *testing.T) { "ConcreteTypeDef incorrectly serialized") var i1 tests.Interface1 - err = cdc.UnmarshalJSON(bz, &i1) + err = cdc.JSONUnmarshal(bz, &i1) assert.Nil(t, err) assert.Equal(t, c3, i1) } diff --git a/tm2/pkg/amino/repr_test.go b/tm2/pkg/amino/repr_test.go index 4be50b5d93d..e9162d2883e 100644 --- a/tm2/pkg/amino/repr_test.go +++ b/tm2/pkg/amino/repr_test.go @@ -91,13 +91,13 @@ func TestMarshalAminoJSON(t *testing.T) { c: []*Foo{nil, nil, nil}, D: "J", } - bz, err := cdc.MarshalJSON(f) + bz, err := cdc.JSONMarshal(f) assert.Nil(t, err) t.Logf("bz %X", bz) var f2 Foo - err = cdc.UnmarshalJSON(bz, &f2) + err = cdc.JSONUnmarshal(bz, &f2) assert.Nil(t, err) assert.Equal(t, f, f2) diff --git a/tm2/pkg/amino/tests/fuzz/json/debug/main.go b/tm2/pkg/amino/tests/fuzz/json/debug/main.go index 892ff943381..8eb41cd0b30 100644 --- a/tm2/pkg/amino/tests/fuzz/json/debug/main.go +++ b/tm2/pkg/amino/tests/fuzz/json/debug/main.go @@ -13,6 +13,6 @@ func main() { bz := []byte("TODO") cdc := amino.NewCodec() cst := tests.ComplexSt{} - err := cdc.UnmarshalJSON(bz, &cst) + err := cdc.JSONUnmarshal(bz, &cst) fmt.Printf("Expected a panic but did not. (err: %v)", err) } diff --git a/tm2/pkg/amino/tests/fuzz/json/json.go b/tm2/pkg/amino/tests/fuzz/json/json.go index b214bd7498b..4c3afe16fd3 100644 --- a/tm2/pkg/amino/tests/fuzz/json/json.go +++ b/tm2/pkg/amino/tests/fuzz/json/json.go @@ -13,7 +13,7 @@ import ( func Fuzz(data []byte) int { cdc := amino.NewCodec() cst := tests.ComplexSt{} - err := cdc.UnmarshalJSON(data, &cst) + err := cdc.JSONUnmarshal(data, &cst) if err != nil { return 0 } diff --git a/tm2/pkg/amino/tests/pb/tests.pb.go b/tm2/pkg/amino/tests/pb/tests.pb.go deleted file mode 100644 index 6776f5ecb57..00000000000 --- a/tm2/pkg/amino/tests/pb/tests.pb.go +++ /dev/null @@ -1,5582 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.31.0 -// protoc v4.24.3 -// source: tests.proto - -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" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// messages -type EmptyStruct struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *EmptyStruct) Reset() { - *x = EmptyStruct{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *EmptyStruct) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*EmptyStruct) ProtoMessage() {} - -func (x *EmptyStruct) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use EmptyStruct.ProtoReflect.Descriptor instead. -func (*EmptyStruct) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{0} -} - -type PrimitivesStruct struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Int8 int32 `protobuf:"zigzag32,1,opt,name=int8,json=Int8,proto3" json:"int8,omitempty"` - Int16 int32 `protobuf:"zigzag32,2,opt,name=int16,json=Int16,proto3" json:"int16,omitempty"` - Int32 int32 `protobuf:"zigzag32,3,opt,name=int32,json=Int32,proto3" json:"int32,omitempty"` - Int32Fixed int32 `protobuf:"fixed32,4,opt,name=int32_fixed,json=Int32Fixed,proto3" json:"int32_fixed,omitempty"` - Int64 int64 `protobuf:"zigzag64,5,opt,name=int64,json=Int64,proto3" json:"int64,omitempty"` - Int64Fixed int64 `protobuf:"fixed64,6,opt,name=int64_fixed,json=Int64Fixed,proto3" json:"int64_fixed,omitempty"` - Int int64 `protobuf:"zigzag64,7,opt,name=int,json=Int,proto3" json:"int,omitempty"` - Byte uint32 `protobuf:"varint,8,opt,name=byte,json=Byte,proto3" json:"byte,omitempty"` - Uint8 uint32 `protobuf:"varint,9,opt,name=uint8,json=Uint8,proto3" json:"uint8,omitempty"` - Uint16 uint32 `protobuf:"varint,10,opt,name=uint16,json=Uint16,proto3" json:"uint16,omitempty"` - Uint32 uint32 `protobuf:"varint,11,opt,name=uint32,json=Uint32,proto3" json:"uint32,omitempty"` - Uint32Fixed uint32 `protobuf:"fixed32,12,opt,name=uint32_fixed,json=Uint32Fixed,proto3" json:"uint32_fixed,omitempty"` - Uint64 uint64 `protobuf:"varint,13,opt,name=uint64,json=Uint64,proto3" json:"uint64,omitempty"` - Uint64Fixed uint64 `protobuf:"fixed64,14,opt,name=uint64_fixed,json=Uint64Fixed,proto3" json:"uint64_fixed,omitempty"` - Uint uint64 `protobuf:"varint,15,opt,name=uint,json=Uint,proto3" json:"uint,omitempty"` - Str string `protobuf:"bytes,16,opt,name=str,json=Str,proto3" json:"str,omitempty"` - Bytes []byte `protobuf:"bytes,17,opt,name=bytes,json=Bytes,proto3" json:"bytes,omitempty"` - Time *timestamppb.Timestamp `protobuf:"bytes,18,opt,name=time,json=Time,proto3" json:"time,omitempty"` - Duration *durationpb.Duration `protobuf:"bytes,19,opt,name=duration,json=Duration,proto3" json:"duration,omitempty"` - Empty *EmptyStruct `protobuf:"bytes,20,opt,name=empty,json=Empty,proto3" json:"empty,omitempty"` -} - -func (x *PrimitivesStruct) Reset() { - *x = PrimitivesStruct{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PrimitivesStruct) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PrimitivesStruct) ProtoMessage() {} - -func (x *PrimitivesStruct) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PrimitivesStruct.ProtoReflect.Descriptor instead. -func (*PrimitivesStruct) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{1} -} - -func (x *PrimitivesStruct) GetInt8() int32 { - if x != nil { - return x.Int8 - } - return 0 -} - -func (x *PrimitivesStruct) GetInt16() int32 { - if x != nil { - return x.Int16 - } - return 0 -} - -func (x *PrimitivesStruct) GetInt32() int32 { - if x != nil { - return x.Int32 - } - return 0 -} - -func (x *PrimitivesStruct) GetInt32Fixed() int32 { - if x != nil { - return x.Int32Fixed - } - return 0 -} - -func (x *PrimitivesStruct) GetInt64() int64 { - if x != nil { - return x.Int64 - } - return 0 -} - -func (x *PrimitivesStruct) GetInt64Fixed() int64 { - if x != nil { - return x.Int64Fixed - } - return 0 -} - -func (x *PrimitivesStruct) GetInt() int64 { - if x != nil { - return x.Int - } - return 0 -} - -func (x *PrimitivesStruct) GetByte() uint32 { - if x != nil { - return x.Byte - } - return 0 -} - -func (x *PrimitivesStruct) GetUint8() uint32 { - if x != nil { - return x.Uint8 - } - return 0 -} - -func (x *PrimitivesStruct) GetUint16() uint32 { - if x != nil { - return x.Uint16 - } - return 0 -} - -func (x *PrimitivesStruct) GetUint32() uint32 { - if x != nil { - return x.Uint32 - } - return 0 -} - -func (x *PrimitivesStruct) GetUint32Fixed() uint32 { - if x != nil { - return x.Uint32Fixed - } - return 0 -} - -func (x *PrimitivesStruct) GetUint64() uint64 { - if x != nil { - return x.Uint64 - } - return 0 -} - -func (x *PrimitivesStruct) GetUint64Fixed() uint64 { - if x != nil { - return x.Uint64Fixed - } - return 0 -} - -func (x *PrimitivesStruct) GetUint() uint64 { - if x != nil { - return x.Uint - } - return 0 -} - -func (x *PrimitivesStruct) GetStr() string { - if x != nil { - return x.Str - } - return "" -} - -func (x *PrimitivesStruct) GetBytes() []byte { - if x != nil { - return x.Bytes - } - return nil -} - -func (x *PrimitivesStruct) GetTime() *timestamppb.Timestamp { - if x != nil { - return x.Time - } - return nil -} - -func (x *PrimitivesStruct) GetDuration() *durationpb.Duration { - if x != nil { - return x.Duration - } - return nil -} - -func (x *PrimitivesStruct) GetEmpty() *EmptyStruct { - if x != nil { - return x.Empty - } - return nil -} - -type ShortArraysStruct struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - TimeAr []*timestamppb.Timestamp `protobuf:"bytes,1,rep,name=time_ar,json=TimeAr,proto3" json:"time_ar,omitempty"` - DurationAr []*durationpb.Duration `protobuf:"bytes,2,rep,name=duration_ar,json=DurationAr,proto3" json:"duration_ar,omitempty"` -} - -func (x *ShortArraysStruct) Reset() { - *x = ShortArraysStruct{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ShortArraysStruct) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ShortArraysStruct) ProtoMessage() {} - -func (x *ShortArraysStruct) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ShortArraysStruct.ProtoReflect.Descriptor instead. -func (*ShortArraysStruct) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{2} -} - -func (x *ShortArraysStruct) GetTimeAr() []*timestamppb.Timestamp { - if x != nil { - return x.TimeAr - } - return nil -} - -func (x *ShortArraysStruct) GetDurationAr() []*durationpb.Duration { - if x != nil { - return x.DurationAr - } - return nil -} - -type ArraysStruct struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Int8Ar []int32 `protobuf:"zigzag32,1,rep,packed,name=int8_ar,json=Int8Ar,proto3" json:"int8_ar,omitempty"` - Int16Ar []int32 `protobuf:"zigzag32,2,rep,packed,name=int16_ar,json=Int16Ar,proto3" json:"int16_ar,omitempty"` - Int32Ar []int32 `protobuf:"zigzag32,3,rep,packed,name=int32_ar,json=Int32Ar,proto3" json:"int32_ar,omitempty"` - Int32FixedAr []int32 `protobuf:"fixed32,4,rep,packed,name=int32_fixed_ar,json=Int32FixedAr,proto3" json:"int32_fixed_ar,omitempty"` - Int64Ar []int64 `protobuf:"zigzag64,5,rep,packed,name=int64_ar,json=Int64Ar,proto3" json:"int64_ar,omitempty"` - Int64FixedAr []int64 `protobuf:"fixed64,6,rep,packed,name=int64_fixed_ar,json=Int64FixedAr,proto3" json:"int64_fixed_ar,omitempty"` - IntAr []int64 `protobuf:"zigzag64,7,rep,packed,name=int_ar,json=IntAr,proto3" json:"int_ar,omitempty"` - ByteAr []byte `protobuf:"bytes,8,opt,name=byte_ar,json=ByteAr,proto3" json:"byte_ar,omitempty"` - Uint8Ar []byte `protobuf:"bytes,9,opt,name=uint8_ar,json=Uint8Ar,proto3" json:"uint8_ar,omitempty"` - Uint16Ar []uint32 `protobuf:"varint,10,rep,packed,name=uint16_ar,json=Uint16Ar,proto3" json:"uint16_ar,omitempty"` - Uint32Ar []uint32 `protobuf:"varint,11,rep,packed,name=uint32_ar,json=Uint32Ar,proto3" json:"uint32_ar,omitempty"` - Uint32FixedAr []uint32 `protobuf:"fixed32,12,rep,packed,name=uint32_fixed_ar,json=Uint32FixedAr,proto3" json:"uint32_fixed_ar,omitempty"` - Uint64Ar []uint64 `protobuf:"varint,13,rep,packed,name=uint64_ar,json=Uint64Ar,proto3" json:"uint64_ar,omitempty"` - Uint64FixedAr []uint64 `protobuf:"fixed64,14,rep,packed,name=uint64_fixed_ar,json=Uint64FixedAr,proto3" json:"uint64_fixed_ar,omitempty"` - UintAr []uint64 `protobuf:"varint,15,rep,packed,name=uint_ar,json=UintAr,proto3" json:"uint_ar,omitempty"` - StrAr []string `protobuf:"bytes,16,rep,name=str_ar,json=StrAr,proto3" json:"str_ar,omitempty"` - BytesAr [][]byte `protobuf:"bytes,17,rep,name=bytes_ar,json=BytesAr,proto3" json:"bytes_ar,omitempty"` - TimeAr []*timestamppb.Timestamp `protobuf:"bytes,18,rep,name=time_ar,json=TimeAr,proto3" json:"time_ar,omitempty"` - DurationAr []*durationpb.Duration `protobuf:"bytes,19,rep,name=duration_ar,json=DurationAr,proto3" json:"duration_ar,omitempty"` - EmptyAr []*EmptyStruct `protobuf:"bytes,20,rep,name=empty_ar,json=EmptyAr,proto3" json:"empty_ar,omitempty"` -} - -func (x *ArraysStruct) Reset() { - *x = ArraysStruct{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ArraysStruct) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ArraysStruct) ProtoMessage() {} - -func (x *ArraysStruct) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ArraysStruct.ProtoReflect.Descriptor instead. -func (*ArraysStruct) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{3} -} - -func (x *ArraysStruct) GetInt8Ar() []int32 { - if x != nil { - return x.Int8Ar - } - return nil -} - -func (x *ArraysStruct) GetInt16Ar() []int32 { - if x != nil { - return x.Int16Ar - } - return nil -} - -func (x *ArraysStruct) GetInt32Ar() []int32 { - if x != nil { - return x.Int32Ar - } - return nil -} - -func (x *ArraysStruct) GetInt32FixedAr() []int32 { - if x != nil { - return x.Int32FixedAr - } - return nil -} - -func (x *ArraysStruct) GetInt64Ar() []int64 { - if x != nil { - return x.Int64Ar - } - return nil -} - -func (x *ArraysStruct) GetInt64FixedAr() []int64 { - if x != nil { - return x.Int64FixedAr - } - return nil -} - -func (x *ArraysStruct) GetIntAr() []int64 { - if x != nil { - return x.IntAr - } - return nil -} - -func (x *ArraysStruct) GetByteAr() []byte { - if x != nil { - return x.ByteAr - } - return nil -} - -func (x *ArraysStruct) GetUint8Ar() []byte { - if x != nil { - return x.Uint8Ar - } - return nil -} - -func (x *ArraysStruct) GetUint16Ar() []uint32 { - if x != nil { - return x.Uint16Ar - } - return nil -} - -func (x *ArraysStruct) GetUint32Ar() []uint32 { - if x != nil { - return x.Uint32Ar - } - return nil -} - -func (x *ArraysStruct) GetUint32FixedAr() []uint32 { - if x != nil { - return x.Uint32FixedAr - } - return nil -} - -func (x *ArraysStruct) GetUint64Ar() []uint64 { - if x != nil { - return x.Uint64Ar - } - return nil -} - -func (x *ArraysStruct) GetUint64FixedAr() []uint64 { - if x != nil { - return x.Uint64FixedAr - } - return nil -} - -func (x *ArraysStruct) GetUintAr() []uint64 { - if x != nil { - return x.UintAr - } - return nil -} - -func (x *ArraysStruct) GetStrAr() []string { - if x != nil { - return x.StrAr - } - return nil -} - -func (x *ArraysStruct) GetBytesAr() [][]byte { - if x != nil { - return x.BytesAr - } - return nil -} - -func (x *ArraysStruct) GetTimeAr() []*timestamppb.Timestamp { - if x != nil { - return x.TimeAr - } - return nil -} - -func (x *ArraysStruct) GetDurationAr() []*durationpb.Duration { - if x != nil { - return x.DurationAr - } - return nil -} - -func (x *ArraysStruct) GetEmptyAr() []*EmptyStruct { - if x != nil { - return x.EmptyAr - } - return nil -} - -type ArraysArraysStruct struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Int8ArAr []*TESTS_Int8List `protobuf:"bytes,1,rep,name=int8_ar_ar,json=Int8ArAr,proto3" json:"int8_ar_ar,omitempty"` - Int16ArAr []*TESTS_Int16List `protobuf:"bytes,2,rep,name=int16_ar_ar,json=Int16ArAr,proto3" json:"int16_ar_ar,omitempty"` - Int32ArAr []*TESTS_Int32ValueList `protobuf:"bytes,3,rep,name=int32_ar_ar,json=Int32ArAr,proto3" json:"int32_ar_ar,omitempty"` - Int32FixedArAr []*TESTS_Fixed32Int32ValueList `protobuf:"bytes,4,rep,name=int32_fixed_ar_ar,json=Int32FixedArAr,proto3" json:"int32_fixed_ar_ar,omitempty"` - Int64ArAr []*TESTS_Int64ValueList `protobuf:"bytes,5,rep,name=int64_ar_ar,json=Int64ArAr,proto3" json:"int64_ar_ar,omitempty"` - Int64FixedArAr []*TESTS_Fixed64Int64ValueList `protobuf:"bytes,6,rep,name=int64_fixed_ar_ar,json=Int64FixedArAr,proto3" json:"int64_fixed_ar_ar,omitempty"` - IntArAr []*TESTS_Int64ValueList `protobuf:"bytes,7,rep,name=int_ar_ar,json=IntArAr,proto3" json:"int_ar_ar,omitempty"` - ByteArAr [][]byte `protobuf:"bytes,8,rep,name=byte_ar_ar,json=ByteArAr,proto3" json:"byte_ar_ar,omitempty"` - Uint8ArAr [][]byte `protobuf:"bytes,9,rep,name=uint8_ar_ar,json=Uint8ArAr,proto3" json:"uint8_ar_ar,omitempty"` - Uint16ArAr []*TESTS_UInt16List `protobuf:"bytes,10,rep,name=uint16_ar_ar,json=Uint16ArAr,proto3" json:"uint16_ar_ar,omitempty"` - Uint32ArAr []*TESTS_UInt32ValueList `protobuf:"bytes,11,rep,name=uint32_ar_ar,json=Uint32ArAr,proto3" json:"uint32_ar_ar,omitempty"` - Uint32FixedArAr []*TESTS_Fixed32UInt32ValueList `protobuf:"bytes,12,rep,name=uint32_fixed_ar_ar,json=Uint32FixedArAr,proto3" json:"uint32_fixed_ar_ar,omitempty"` - Uint64ArAr []*TESTS_UInt64ValueList `protobuf:"bytes,13,rep,name=uint64_ar_ar,json=Uint64ArAr,proto3" json:"uint64_ar_ar,omitempty"` - Uint64FixedArAr []*TESTS_Fixed64UInt64ValueList `protobuf:"bytes,14,rep,name=uint64_fixed_ar_ar,json=Uint64FixedArAr,proto3" json:"uint64_fixed_ar_ar,omitempty"` - UintArAr []*TESTS_UInt64ValueList `protobuf:"bytes,15,rep,name=uint_ar_ar,json=UintArAr,proto3" json:"uint_ar_ar,omitempty"` - StrArAr []*TESTS_StringValueList `protobuf:"bytes,16,rep,name=str_ar_ar,json=StrArAr,proto3" json:"str_ar_ar,omitempty"` - BytesArAr []*TESTS_BytesList `protobuf:"bytes,17,rep,name=bytes_ar_ar,json=BytesArAr,proto3" json:"bytes_ar_ar,omitempty"` - TimeArAr []*TESTS_TimestampList `protobuf:"bytes,18,rep,name=time_ar_ar,json=TimeArAr,proto3" json:"time_ar_ar,omitempty"` - DurationArAr []*TESTS_DurationList `protobuf:"bytes,19,rep,name=duration_ar_ar,json=DurationArAr,proto3" json:"duration_ar_ar,omitempty"` - EmptyArAr []*TESTS_EmptyStructList `protobuf:"bytes,20,rep,name=empty_ar_ar,json=EmptyArAr,proto3" json:"empty_ar_ar,omitempty"` -} - -func (x *ArraysArraysStruct) Reset() { - *x = ArraysArraysStruct{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ArraysArraysStruct) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ArraysArraysStruct) ProtoMessage() {} - -func (x *ArraysArraysStruct) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ArraysArraysStruct.ProtoReflect.Descriptor instead. -func (*ArraysArraysStruct) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{4} -} - -func (x *ArraysArraysStruct) GetInt8ArAr() []*TESTS_Int8List { - if x != nil { - return x.Int8ArAr - } - return nil -} - -func (x *ArraysArraysStruct) GetInt16ArAr() []*TESTS_Int16List { - if x != nil { - return x.Int16ArAr - } - return nil -} - -func (x *ArraysArraysStruct) GetInt32ArAr() []*TESTS_Int32ValueList { - if x != nil { - return x.Int32ArAr - } - return nil -} - -func (x *ArraysArraysStruct) GetInt32FixedArAr() []*TESTS_Fixed32Int32ValueList { - if x != nil { - return x.Int32FixedArAr - } - return nil -} - -func (x *ArraysArraysStruct) GetInt64ArAr() []*TESTS_Int64ValueList { - if x != nil { - return x.Int64ArAr - } - return nil -} - -func (x *ArraysArraysStruct) GetInt64FixedArAr() []*TESTS_Fixed64Int64ValueList { - if x != nil { - return x.Int64FixedArAr - } - return nil -} - -func (x *ArraysArraysStruct) GetIntArAr() []*TESTS_Int64ValueList { - if x != nil { - return x.IntArAr - } - return nil -} - -func (x *ArraysArraysStruct) GetByteArAr() [][]byte { - if x != nil { - return x.ByteArAr - } - return nil -} - -func (x *ArraysArraysStruct) GetUint8ArAr() [][]byte { - if x != nil { - return x.Uint8ArAr - } - return nil -} - -func (x *ArraysArraysStruct) GetUint16ArAr() []*TESTS_UInt16List { - if x != nil { - return x.Uint16ArAr - } - return nil -} - -func (x *ArraysArraysStruct) GetUint32ArAr() []*TESTS_UInt32ValueList { - if x != nil { - return x.Uint32ArAr - } - return nil -} - -func (x *ArraysArraysStruct) GetUint32FixedArAr() []*TESTS_Fixed32UInt32ValueList { - if x != nil { - return x.Uint32FixedArAr - } - return nil -} - -func (x *ArraysArraysStruct) GetUint64ArAr() []*TESTS_UInt64ValueList { - if x != nil { - return x.Uint64ArAr - } - return nil -} - -func (x *ArraysArraysStruct) GetUint64FixedArAr() []*TESTS_Fixed64UInt64ValueList { - if x != nil { - return x.Uint64FixedArAr - } - return nil -} - -func (x *ArraysArraysStruct) GetUintArAr() []*TESTS_UInt64ValueList { - if x != nil { - return x.UintArAr - } - return nil -} - -func (x *ArraysArraysStruct) GetStrArAr() []*TESTS_StringValueList { - if x != nil { - return x.StrArAr - } - return nil -} - -func (x *ArraysArraysStruct) GetBytesArAr() []*TESTS_BytesList { - if x != nil { - return x.BytesArAr - } - return nil -} - -func (x *ArraysArraysStruct) GetTimeArAr() []*TESTS_TimestampList { - if x != nil { - return x.TimeArAr - } - return nil -} - -func (x *ArraysArraysStruct) GetDurationArAr() []*TESTS_DurationList { - if x != nil { - return x.DurationArAr - } - return nil -} - -func (x *ArraysArraysStruct) GetEmptyArAr() []*TESTS_EmptyStructList { - if x != nil { - return x.EmptyArAr - } - return nil -} - -type SlicesStruct struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Int8Sl []int32 `protobuf:"zigzag32,1,rep,packed,name=int8_sl,json=Int8Sl,proto3" json:"int8_sl,omitempty"` - Int16Sl []int32 `protobuf:"zigzag32,2,rep,packed,name=int16_sl,json=Int16Sl,proto3" json:"int16_sl,omitempty"` - Int32Sl []int32 `protobuf:"zigzag32,3,rep,packed,name=int32_sl,json=Int32Sl,proto3" json:"int32_sl,omitempty"` - Int32FixedSl []int32 `protobuf:"fixed32,4,rep,packed,name=int32_fixed_sl,json=Int32FixedSl,proto3" json:"int32_fixed_sl,omitempty"` - Int64Sl []int64 `protobuf:"zigzag64,5,rep,packed,name=int64_sl,json=Int64Sl,proto3" json:"int64_sl,omitempty"` - Int64FixedSl []int64 `protobuf:"fixed64,6,rep,packed,name=int64_fixed_sl,json=Int64FixedSl,proto3" json:"int64_fixed_sl,omitempty"` - IntSl []int64 `protobuf:"zigzag64,7,rep,packed,name=int_sl,json=IntSl,proto3" json:"int_sl,omitempty"` - ByteSl []byte `protobuf:"bytes,8,opt,name=byte_sl,json=ByteSl,proto3" json:"byte_sl,omitempty"` - Uint8Sl []byte `protobuf:"bytes,9,opt,name=uint8_sl,json=Uint8Sl,proto3" json:"uint8_sl,omitempty"` - Uint16Sl []uint32 `protobuf:"varint,10,rep,packed,name=uint16_sl,json=Uint16Sl,proto3" json:"uint16_sl,omitempty"` - Uint32Sl []uint32 `protobuf:"varint,11,rep,packed,name=uint32_sl,json=Uint32Sl,proto3" json:"uint32_sl,omitempty"` - Uint32FixedSl []uint32 `protobuf:"fixed32,12,rep,packed,name=uint32_fixed_sl,json=Uint32FixedSl,proto3" json:"uint32_fixed_sl,omitempty"` - Uint64Sl []uint64 `protobuf:"varint,13,rep,packed,name=uint64_sl,json=Uint64Sl,proto3" json:"uint64_sl,omitempty"` - Uint64FixedSl []uint64 `protobuf:"fixed64,14,rep,packed,name=uint64_fixed_sl,json=Uint64FixedSl,proto3" json:"uint64_fixed_sl,omitempty"` - UintSl []uint64 `protobuf:"varint,15,rep,packed,name=uint_sl,json=UintSl,proto3" json:"uint_sl,omitempty"` - StrSl []string `protobuf:"bytes,16,rep,name=str_sl,json=StrSl,proto3" json:"str_sl,omitempty"` - BytesSl [][]byte `protobuf:"bytes,17,rep,name=bytes_sl,json=BytesSl,proto3" json:"bytes_sl,omitempty"` - TimeSl []*timestamppb.Timestamp `protobuf:"bytes,18,rep,name=time_sl,json=TimeSl,proto3" json:"time_sl,omitempty"` - DurationSl []*durationpb.Duration `protobuf:"bytes,19,rep,name=duration_sl,json=DurationSl,proto3" json:"duration_sl,omitempty"` - EmptySl []*EmptyStruct `protobuf:"bytes,20,rep,name=empty_sl,json=EmptySl,proto3" json:"empty_sl,omitempty"` -} - -func (x *SlicesStruct) Reset() { - *x = SlicesStruct{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SlicesStruct) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SlicesStruct) ProtoMessage() {} - -func (x *SlicesStruct) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SlicesStruct.ProtoReflect.Descriptor instead. -func (*SlicesStruct) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{5} -} - -func (x *SlicesStruct) GetInt8Sl() []int32 { - if x != nil { - return x.Int8Sl - } - return nil -} - -func (x *SlicesStruct) GetInt16Sl() []int32 { - if x != nil { - return x.Int16Sl - } - return nil -} - -func (x *SlicesStruct) GetInt32Sl() []int32 { - if x != nil { - return x.Int32Sl - } - return nil -} - -func (x *SlicesStruct) GetInt32FixedSl() []int32 { - if x != nil { - return x.Int32FixedSl - } - return nil -} - -func (x *SlicesStruct) GetInt64Sl() []int64 { - if x != nil { - return x.Int64Sl - } - return nil -} - -func (x *SlicesStruct) GetInt64FixedSl() []int64 { - if x != nil { - return x.Int64FixedSl - } - return nil -} - -func (x *SlicesStruct) GetIntSl() []int64 { - if x != nil { - return x.IntSl - } - return nil -} - -func (x *SlicesStruct) GetByteSl() []byte { - if x != nil { - return x.ByteSl - } - return nil -} - -func (x *SlicesStruct) GetUint8Sl() []byte { - if x != nil { - return x.Uint8Sl - } - return nil -} - -func (x *SlicesStruct) GetUint16Sl() []uint32 { - if x != nil { - return x.Uint16Sl - } - return nil -} - -func (x *SlicesStruct) GetUint32Sl() []uint32 { - if x != nil { - return x.Uint32Sl - } - return nil -} - -func (x *SlicesStruct) GetUint32FixedSl() []uint32 { - if x != nil { - return x.Uint32FixedSl - } - return nil -} - -func (x *SlicesStruct) GetUint64Sl() []uint64 { - if x != nil { - return x.Uint64Sl - } - return nil -} - -func (x *SlicesStruct) GetUint64FixedSl() []uint64 { - if x != nil { - return x.Uint64FixedSl - } - return nil -} - -func (x *SlicesStruct) GetUintSl() []uint64 { - if x != nil { - return x.UintSl - } - return nil -} - -func (x *SlicesStruct) GetStrSl() []string { - if x != nil { - return x.StrSl - } - return nil -} - -func (x *SlicesStruct) GetBytesSl() [][]byte { - if x != nil { - return x.BytesSl - } - return nil -} - -func (x *SlicesStruct) GetTimeSl() []*timestamppb.Timestamp { - if x != nil { - return x.TimeSl - } - return nil -} - -func (x *SlicesStruct) GetDurationSl() []*durationpb.Duration { - if x != nil { - return x.DurationSl - } - return nil -} - -func (x *SlicesStruct) GetEmptySl() []*EmptyStruct { - if x != nil { - return x.EmptySl - } - return nil -} - -type SlicesSlicesStruct struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Int8SlSl []*TESTS_Int8List `protobuf:"bytes,1,rep,name=int8_sl_sl,json=Int8SlSl,proto3" json:"int8_sl_sl,omitempty"` - Int16SlSl []*TESTS_Int16List `protobuf:"bytes,2,rep,name=int16_sl_sl,json=Int16SlSl,proto3" json:"int16_sl_sl,omitempty"` - Int32SlSl []*TESTS_Int32ValueList `protobuf:"bytes,3,rep,name=int32_sl_sl,json=Int32SlSl,proto3" json:"int32_sl_sl,omitempty"` - Int32FixedSlSl []*TESTS_Fixed32Int32ValueList `protobuf:"bytes,4,rep,name=int32_fixed_sl_sl,json=Int32FixedSlSl,proto3" json:"int32_fixed_sl_sl,omitempty"` - Int64SlSl []*TESTS_Int64ValueList `protobuf:"bytes,5,rep,name=int64_sl_sl,json=Int64SlSl,proto3" json:"int64_sl_sl,omitempty"` - Int64FixedSlSl []*TESTS_Fixed64Int64ValueList `protobuf:"bytes,6,rep,name=int64_fixed_sl_sl,json=Int64FixedSlSl,proto3" json:"int64_fixed_sl_sl,omitempty"` - IntSlSl []*TESTS_Int64ValueList `protobuf:"bytes,7,rep,name=int_sl_sl,json=IntSlSl,proto3" json:"int_sl_sl,omitempty"` - ByteSlSl [][]byte `protobuf:"bytes,8,rep,name=byte_sl_sl,json=ByteSlSl,proto3" json:"byte_sl_sl,omitempty"` - Uint8SlSl [][]byte `protobuf:"bytes,9,rep,name=uint8_sl_sl,json=Uint8SlSl,proto3" json:"uint8_sl_sl,omitempty"` - Uint16SlSl []*TESTS_UInt16List `protobuf:"bytes,10,rep,name=uint16_sl_sl,json=Uint16SlSl,proto3" json:"uint16_sl_sl,omitempty"` - Uint32SlSl []*TESTS_UInt32ValueList `protobuf:"bytes,11,rep,name=uint32_sl_sl,json=Uint32SlSl,proto3" json:"uint32_sl_sl,omitempty"` - Uint32FixedSlSl []*TESTS_Fixed32UInt32ValueList `protobuf:"bytes,12,rep,name=uint32_fixed_sl_sl,json=Uint32FixedSlSl,proto3" json:"uint32_fixed_sl_sl,omitempty"` - Uint64SlSl []*TESTS_UInt64ValueList `protobuf:"bytes,13,rep,name=uint64_sl_sl,json=Uint64SlSl,proto3" json:"uint64_sl_sl,omitempty"` - Uint64FixedSlSl []*TESTS_Fixed64UInt64ValueList `protobuf:"bytes,14,rep,name=uint64_fixed_sl_sl,json=Uint64FixedSlSl,proto3" json:"uint64_fixed_sl_sl,omitempty"` - UintSlSl []*TESTS_UInt64ValueList `protobuf:"bytes,15,rep,name=uint_sl_sl,json=UintSlSl,proto3" json:"uint_sl_sl,omitempty"` - StrSlSl []*TESTS_StringValueList `protobuf:"bytes,16,rep,name=str_sl_sl,json=StrSlSl,proto3" json:"str_sl_sl,omitempty"` - BytesSlSl []*TESTS_BytesList `protobuf:"bytes,17,rep,name=bytes_sl_sl,json=BytesSlSl,proto3" json:"bytes_sl_sl,omitempty"` - TimeSlSl []*TESTS_TimestampList `protobuf:"bytes,18,rep,name=time_sl_sl,json=TimeSlSl,proto3" json:"time_sl_sl,omitempty"` - DurationSlSl []*TESTS_DurationList `protobuf:"bytes,19,rep,name=duration_sl_sl,json=DurationSlSl,proto3" json:"duration_sl_sl,omitempty"` - EmptySlSl []*TESTS_EmptyStructList `protobuf:"bytes,20,rep,name=empty_sl_sl,json=EmptySlSl,proto3" json:"empty_sl_sl,omitempty"` -} - -func (x *SlicesSlicesStruct) Reset() { - *x = SlicesSlicesStruct{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SlicesSlicesStruct) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SlicesSlicesStruct) ProtoMessage() {} - -func (x *SlicesSlicesStruct) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SlicesSlicesStruct.ProtoReflect.Descriptor instead. -func (*SlicesSlicesStruct) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{6} -} - -func (x *SlicesSlicesStruct) GetInt8SlSl() []*TESTS_Int8List { - if x != nil { - return x.Int8SlSl - } - return nil -} - -func (x *SlicesSlicesStruct) GetInt16SlSl() []*TESTS_Int16List { - if x != nil { - return x.Int16SlSl - } - return nil -} - -func (x *SlicesSlicesStruct) GetInt32SlSl() []*TESTS_Int32ValueList { - if x != nil { - return x.Int32SlSl - } - return nil -} - -func (x *SlicesSlicesStruct) GetInt32FixedSlSl() []*TESTS_Fixed32Int32ValueList { - if x != nil { - return x.Int32FixedSlSl - } - return nil -} - -func (x *SlicesSlicesStruct) GetInt64SlSl() []*TESTS_Int64ValueList { - if x != nil { - return x.Int64SlSl - } - return nil -} - -func (x *SlicesSlicesStruct) GetInt64FixedSlSl() []*TESTS_Fixed64Int64ValueList { - if x != nil { - return x.Int64FixedSlSl - } - return nil -} - -func (x *SlicesSlicesStruct) GetIntSlSl() []*TESTS_Int64ValueList { - if x != nil { - return x.IntSlSl - } - return nil -} - -func (x *SlicesSlicesStruct) GetByteSlSl() [][]byte { - if x != nil { - return x.ByteSlSl - } - return nil -} - -func (x *SlicesSlicesStruct) GetUint8SlSl() [][]byte { - if x != nil { - return x.Uint8SlSl - } - return nil -} - -func (x *SlicesSlicesStruct) GetUint16SlSl() []*TESTS_UInt16List { - if x != nil { - return x.Uint16SlSl - } - return nil -} - -func (x *SlicesSlicesStruct) GetUint32SlSl() []*TESTS_UInt32ValueList { - if x != nil { - return x.Uint32SlSl - } - return nil -} - -func (x *SlicesSlicesStruct) GetUint32FixedSlSl() []*TESTS_Fixed32UInt32ValueList { - if x != nil { - return x.Uint32FixedSlSl - } - return nil -} - -func (x *SlicesSlicesStruct) GetUint64SlSl() []*TESTS_UInt64ValueList { - if x != nil { - return x.Uint64SlSl - } - return nil -} - -func (x *SlicesSlicesStruct) GetUint64FixedSlSl() []*TESTS_Fixed64UInt64ValueList { - if x != nil { - return x.Uint64FixedSlSl - } - return nil -} - -func (x *SlicesSlicesStruct) GetUintSlSl() []*TESTS_UInt64ValueList { - if x != nil { - return x.UintSlSl - } - return nil -} - -func (x *SlicesSlicesStruct) GetStrSlSl() []*TESTS_StringValueList { - if x != nil { - return x.StrSlSl - } - return nil -} - -func (x *SlicesSlicesStruct) GetBytesSlSl() []*TESTS_BytesList { - if x != nil { - return x.BytesSlSl - } - return nil -} - -func (x *SlicesSlicesStruct) GetTimeSlSl() []*TESTS_TimestampList { - if x != nil { - return x.TimeSlSl - } - return nil -} - -func (x *SlicesSlicesStruct) GetDurationSlSl() []*TESTS_DurationList { - if x != nil { - return x.DurationSlSl - } - return nil -} - -func (x *SlicesSlicesStruct) GetEmptySlSl() []*TESTS_EmptyStructList { - if x != nil { - return x.EmptySlSl - } - return nil -} - -type PointersStruct struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Int8Pt int32 `protobuf:"zigzag32,1,opt,name=int8_pt,json=Int8Pt,proto3" json:"int8_pt,omitempty"` - Int16Pt int32 `protobuf:"zigzag32,2,opt,name=int16_pt,json=Int16Pt,proto3" json:"int16_pt,omitempty"` - Int32Pt int32 `protobuf:"zigzag32,3,opt,name=int32_pt,json=Int32Pt,proto3" json:"int32_pt,omitempty"` - Int32FixedPt int32 `protobuf:"fixed32,4,opt,name=int32_fixed_pt,json=Int32FixedPt,proto3" json:"int32_fixed_pt,omitempty"` - Int64Pt int64 `protobuf:"zigzag64,5,opt,name=int64_pt,json=Int64Pt,proto3" json:"int64_pt,omitempty"` - Int64FixedPt int64 `protobuf:"fixed64,6,opt,name=int64_fixed_pt,json=Int64FixedPt,proto3" json:"int64_fixed_pt,omitempty"` - IntPt int64 `protobuf:"zigzag64,7,opt,name=int_pt,json=IntPt,proto3" json:"int_pt,omitempty"` - BytePt uint32 `protobuf:"varint,8,opt,name=byte_pt,json=BytePt,proto3" json:"byte_pt,omitempty"` - Uint8Pt uint32 `protobuf:"varint,9,opt,name=uint8_pt,json=Uint8Pt,proto3" json:"uint8_pt,omitempty"` - Uint16Pt uint32 `protobuf:"varint,10,opt,name=uint16_pt,json=Uint16Pt,proto3" json:"uint16_pt,omitempty"` - Uint32Pt uint32 `protobuf:"varint,11,opt,name=uint32_pt,json=Uint32Pt,proto3" json:"uint32_pt,omitempty"` - Uint32FixedPt uint32 `protobuf:"fixed32,12,opt,name=uint32_fixed_pt,json=Uint32FixedPt,proto3" json:"uint32_fixed_pt,omitempty"` - Uint64Pt uint64 `protobuf:"varint,13,opt,name=uint64_pt,json=Uint64Pt,proto3" json:"uint64_pt,omitempty"` - Uint64FixedPt uint64 `protobuf:"fixed64,14,opt,name=uint64_fixed_pt,json=Uint64FixedPt,proto3" json:"uint64_fixed_pt,omitempty"` - UintPt uint64 `protobuf:"varint,15,opt,name=uint_pt,json=UintPt,proto3" json:"uint_pt,omitempty"` - StrPt string `protobuf:"bytes,16,opt,name=str_pt,json=StrPt,proto3" json:"str_pt,omitempty"` - BytesPt []byte `protobuf:"bytes,17,opt,name=bytes_pt,json=BytesPt,proto3" json:"bytes_pt,omitempty"` - TimePt *timestamppb.Timestamp `protobuf:"bytes,18,opt,name=time_pt,json=TimePt,proto3" json:"time_pt,omitempty"` - DurationPt *durationpb.Duration `protobuf:"bytes,19,opt,name=duration_pt,json=DurationPt,proto3" json:"duration_pt,omitempty"` - EmptyPt *EmptyStruct `protobuf:"bytes,20,opt,name=empty_pt,json=EmptyPt,proto3" json:"empty_pt,omitempty"` -} - -func (x *PointersStruct) Reset() { - *x = PointersStruct{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PointersStruct) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PointersStruct) ProtoMessage() {} - -func (x *PointersStruct) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PointersStruct.ProtoReflect.Descriptor instead. -func (*PointersStruct) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{7} -} - -func (x *PointersStruct) GetInt8Pt() int32 { - if x != nil { - return x.Int8Pt - } - return 0 -} - -func (x *PointersStruct) GetInt16Pt() int32 { - if x != nil { - return x.Int16Pt - } - return 0 -} - -func (x *PointersStruct) GetInt32Pt() int32 { - if x != nil { - return x.Int32Pt - } - return 0 -} - -func (x *PointersStruct) GetInt32FixedPt() int32 { - if x != nil { - return x.Int32FixedPt - } - return 0 -} - -func (x *PointersStruct) GetInt64Pt() int64 { - if x != nil { - return x.Int64Pt - } - return 0 -} - -func (x *PointersStruct) GetInt64FixedPt() int64 { - if x != nil { - return x.Int64FixedPt - } - return 0 -} - -func (x *PointersStruct) GetIntPt() int64 { - if x != nil { - return x.IntPt - } - return 0 -} - -func (x *PointersStruct) GetBytePt() uint32 { - if x != nil { - return x.BytePt - } - return 0 -} - -func (x *PointersStruct) GetUint8Pt() uint32 { - if x != nil { - return x.Uint8Pt - } - return 0 -} - -func (x *PointersStruct) GetUint16Pt() uint32 { - if x != nil { - return x.Uint16Pt - } - return 0 -} - -func (x *PointersStruct) GetUint32Pt() uint32 { - if x != nil { - return x.Uint32Pt - } - return 0 -} - -func (x *PointersStruct) GetUint32FixedPt() uint32 { - if x != nil { - return x.Uint32FixedPt - } - return 0 -} - -func (x *PointersStruct) GetUint64Pt() uint64 { - if x != nil { - return x.Uint64Pt - } - return 0 -} - -func (x *PointersStruct) GetUint64FixedPt() uint64 { - if x != nil { - return x.Uint64FixedPt - } - return 0 -} - -func (x *PointersStruct) GetUintPt() uint64 { - if x != nil { - return x.UintPt - } - return 0 -} - -func (x *PointersStruct) GetStrPt() string { - if x != nil { - return x.StrPt - } - return "" -} - -func (x *PointersStruct) GetBytesPt() []byte { - if x != nil { - return x.BytesPt - } - return nil -} - -func (x *PointersStruct) GetTimePt() *timestamppb.Timestamp { - if x != nil { - return x.TimePt - } - return nil -} - -func (x *PointersStruct) GetDurationPt() *durationpb.Duration { - if x != nil { - return x.DurationPt - } - return nil -} - -func (x *PointersStruct) GetEmptyPt() *EmptyStruct { - if x != nil { - return x.EmptyPt - } - return nil -} - -type PointerSlicesStruct struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Int8PtSl []int32 `protobuf:"zigzag32,1,rep,packed,name=int8_pt_sl,json=Int8PtSl,proto3" json:"int8_pt_sl,omitempty"` - Int16PtSl []int32 `protobuf:"zigzag32,2,rep,packed,name=int16_pt_sl,json=Int16PtSl,proto3" json:"int16_pt_sl,omitempty"` - Int32PtSl []int32 `protobuf:"zigzag32,3,rep,packed,name=int32_pt_sl,json=Int32PtSl,proto3" json:"int32_pt_sl,omitempty"` - Int32FixedPtSl []int32 `protobuf:"fixed32,4,rep,packed,name=int32_fixed_pt_sl,json=Int32FixedPtSl,proto3" json:"int32_fixed_pt_sl,omitempty"` - Int64PtSl []int64 `protobuf:"zigzag64,5,rep,packed,name=int64_pt_sl,json=Int64PtSl,proto3" json:"int64_pt_sl,omitempty"` - Int64FixedPtSl []int64 `protobuf:"fixed64,6,rep,packed,name=int64_fixed_pt_sl,json=Int64FixedPtSl,proto3" json:"int64_fixed_pt_sl,omitempty"` - IntPtSl []int64 `protobuf:"zigzag64,7,rep,packed,name=int_pt_sl,json=IntPtSl,proto3" json:"int_pt_sl,omitempty"` - BytePtSl []byte `protobuf:"bytes,8,opt,name=byte_pt_sl,json=BytePtSl,proto3" json:"byte_pt_sl,omitempty"` - Uint8PtSl []byte `protobuf:"bytes,9,opt,name=uint8_pt_sl,json=Uint8PtSl,proto3" json:"uint8_pt_sl,omitempty"` - Uint16PtSl []uint32 `protobuf:"varint,10,rep,packed,name=uint16_pt_sl,json=Uint16PtSl,proto3" json:"uint16_pt_sl,omitempty"` - Uint32PtSl []uint32 `protobuf:"varint,11,rep,packed,name=uint32_pt_sl,json=Uint32PtSl,proto3" json:"uint32_pt_sl,omitempty"` - Uint32FixedPtSl []uint32 `protobuf:"fixed32,12,rep,packed,name=uint32_fixed_pt_sl,json=Uint32FixedPtSl,proto3" json:"uint32_fixed_pt_sl,omitempty"` - Uint64PtSl []uint64 `protobuf:"varint,13,rep,packed,name=uint64_pt_sl,json=Uint64PtSl,proto3" json:"uint64_pt_sl,omitempty"` - Uint64FixedPtSl []uint64 `protobuf:"fixed64,14,rep,packed,name=uint64_fixed_pt_sl,json=Uint64FixedPtSl,proto3" json:"uint64_fixed_pt_sl,omitempty"` - UintPtSl []uint64 `protobuf:"varint,15,rep,packed,name=uint_pt_sl,json=UintPtSl,proto3" json:"uint_pt_sl,omitempty"` - StrPtSl []string `protobuf:"bytes,16,rep,name=str_pt_sl,json=StrPtSl,proto3" json:"str_pt_sl,omitempty"` - BytesPtSl [][]byte `protobuf:"bytes,17,rep,name=bytes_pt_sl,json=BytesPtSl,proto3" json:"bytes_pt_sl,omitempty"` - TimePtSl []*timestamppb.Timestamp `protobuf:"bytes,18,rep,name=time_pt_sl,json=TimePtSl,proto3" json:"time_pt_sl,omitempty"` - DurationPtSl []*durationpb.Duration `protobuf:"bytes,19,rep,name=duration_pt_sl,json=DurationPtSl,proto3" json:"duration_pt_sl,omitempty"` - EmptyPtSl []*EmptyStruct `protobuf:"bytes,20,rep,name=empty_pt_sl,json=EmptyPtSl,proto3" json:"empty_pt_sl,omitempty"` -} - -func (x *PointerSlicesStruct) Reset() { - *x = PointerSlicesStruct{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PointerSlicesStruct) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PointerSlicesStruct) ProtoMessage() {} - -func (x *PointerSlicesStruct) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PointerSlicesStruct.ProtoReflect.Descriptor instead. -func (*PointerSlicesStruct) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{8} -} - -func (x *PointerSlicesStruct) GetInt8PtSl() []int32 { - if x != nil { - return x.Int8PtSl - } - return nil -} - -func (x *PointerSlicesStruct) GetInt16PtSl() []int32 { - if x != nil { - return x.Int16PtSl - } - return nil -} - -func (x *PointerSlicesStruct) GetInt32PtSl() []int32 { - if x != nil { - return x.Int32PtSl - } - return nil -} - -func (x *PointerSlicesStruct) GetInt32FixedPtSl() []int32 { - if x != nil { - return x.Int32FixedPtSl - } - return nil -} - -func (x *PointerSlicesStruct) GetInt64PtSl() []int64 { - if x != nil { - return x.Int64PtSl - } - return nil -} - -func (x *PointerSlicesStruct) GetInt64FixedPtSl() []int64 { - if x != nil { - return x.Int64FixedPtSl - } - return nil -} - -func (x *PointerSlicesStruct) GetIntPtSl() []int64 { - if x != nil { - return x.IntPtSl - } - return nil -} - -func (x *PointerSlicesStruct) GetBytePtSl() []byte { - if x != nil { - return x.BytePtSl - } - return nil -} - -func (x *PointerSlicesStruct) GetUint8PtSl() []byte { - if x != nil { - return x.Uint8PtSl - } - return nil -} - -func (x *PointerSlicesStruct) GetUint16PtSl() []uint32 { - if x != nil { - return x.Uint16PtSl - } - return nil -} - -func (x *PointerSlicesStruct) GetUint32PtSl() []uint32 { - if x != nil { - return x.Uint32PtSl - } - return nil -} - -func (x *PointerSlicesStruct) GetUint32FixedPtSl() []uint32 { - if x != nil { - return x.Uint32FixedPtSl - } - return nil -} - -func (x *PointerSlicesStruct) GetUint64PtSl() []uint64 { - if x != nil { - return x.Uint64PtSl - } - return nil -} - -func (x *PointerSlicesStruct) GetUint64FixedPtSl() []uint64 { - if x != nil { - return x.Uint64FixedPtSl - } - return nil -} - -func (x *PointerSlicesStruct) GetUintPtSl() []uint64 { - if x != nil { - return x.UintPtSl - } - return nil -} - -func (x *PointerSlicesStruct) GetStrPtSl() []string { - if x != nil { - return x.StrPtSl - } - return nil -} - -func (x *PointerSlicesStruct) GetBytesPtSl() [][]byte { - if x != nil { - return x.BytesPtSl - } - return nil -} - -func (x *PointerSlicesStruct) GetTimePtSl() []*timestamppb.Timestamp { - if x != nil { - return x.TimePtSl - } - return nil -} - -func (x *PointerSlicesStruct) GetDurationPtSl() []*durationpb.Duration { - if x != nil { - return x.DurationPtSl - } - return nil -} - -func (x *PointerSlicesStruct) GetEmptyPtSl() []*EmptyStruct { - if x != nil { - return x.EmptyPtSl - } - return nil -} - -type ComplexSt struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - PrField *PrimitivesStruct `protobuf:"bytes,1,opt,name=pr_field,json=PrField,proto3" json:"pr_field,omitempty"` - ArField *ArraysStruct `protobuf:"bytes,2,opt,name=ar_field,json=ArField,proto3" json:"ar_field,omitempty"` - SlField *SlicesStruct `protobuf:"bytes,3,opt,name=sl_field,json=SlField,proto3" json:"sl_field,omitempty"` - PtField *PointersStruct `protobuf:"bytes,4,opt,name=pt_field,json=PtField,proto3" json:"pt_field,omitempty"` -} - -func (x *ComplexSt) Reset() { - *x = ComplexSt{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ComplexSt) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ComplexSt) ProtoMessage() {} - -func (x *ComplexSt) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ComplexSt.ProtoReflect.Descriptor instead. -func (*ComplexSt) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{9} -} - -func (x *ComplexSt) GetPrField() *PrimitivesStruct { - if x != nil { - return x.PrField - } - return nil -} - -func (x *ComplexSt) GetArField() *ArraysStruct { - if x != nil { - return x.ArField - } - return nil -} - -func (x *ComplexSt) GetSlField() *SlicesStruct { - if x != nil { - return x.SlField - } - return nil -} - -func (x *ComplexSt) GetPtField() *PointersStruct { - if x != nil { - return x.PtField - } - return nil -} - -type EmbeddedSt1 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - PrimitivesStruct *PrimitivesStruct `protobuf:"bytes,1,opt,name=primitives_struct,json=PrimitivesStruct,proto3" json:"primitives_struct,omitempty"` -} - -func (x *EmbeddedSt1) Reset() { - *x = EmbeddedSt1{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *EmbeddedSt1) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*EmbeddedSt1) ProtoMessage() {} - -func (x *EmbeddedSt1) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[10] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use EmbeddedSt1.ProtoReflect.Descriptor instead. -func (*EmbeddedSt1) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{10} -} - -func (x *EmbeddedSt1) GetPrimitivesStruct() *PrimitivesStruct { - if x != nil { - return x.PrimitivesStruct - } - return nil -} - -type EmbeddedSt2 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - PrimitivesStruct *PrimitivesStruct `protobuf:"bytes,1,opt,name=primitives_struct,json=PrimitivesStruct,proto3" json:"primitives_struct,omitempty"` - ArraysStruct *ArraysStruct `protobuf:"bytes,2,opt,name=arrays_struct,json=ArraysStruct,proto3" json:"arrays_struct,omitempty"` - SlicesStruct *SlicesStruct `protobuf:"bytes,3,opt,name=slices_struct,json=SlicesStruct,proto3" json:"slices_struct,omitempty"` - PointersStruct *PointersStruct `protobuf:"bytes,4,opt,name=pointers_struct,json=PointersStruct,proto3" json:"pointers_struct,omitempty"` -} - -func (x *EmbeddedSt2) Reset() { - *x = EmbeddedSt2{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *EmbeddedSt2) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*EmbeddedSt2) ProtoMessage() {} - -func (x *EmbeddedSt2) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[11] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use EmbeddedSt2.ProtoReflect.Descriptor instead. -func (*EmbeddedSt2) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{11} -} - -func (x *EmbeddedSt2) GetPrimitivesStruct() *PrimitivesStruct { - if x != nil { - return x.PrimitivesStruct - } - return nil -} - -func (x *EmbeddedSt2) GetArraysStruct() *ArraysStruct { - if x != nil { - return x.ArraysStruct - } - return nil -} - -func (x *EmbeddedSt2) GetSlicesStruct() *SlicesStruct { - if x != nil { - return x.SlicesStruct - } - return nil -} - -func (x *EmbeddedSt2) GetPointersStruct() *PointersStruct { - if x != nil { - return x.PointersStruct - } - return nil -} - -type EmbeddedSt3 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - PrimitivesStruct *PrimitivesStruct `protobuf:"bytes,1,opt,name=primitives_struct,json=PrimitivesStruct,proto3" json:"primitives_struct,omitempty"` - ArraysStruct *ArraysStruct `protobuf:"bytes,2,opt,name=arrays_struct,json=ArraysStruct,proto3" json:"arrays_struct,omitempty"` - SlicesStruct *SlicesStruct `protobuf:"bytes,3,opt,name=slices_struct,json=SlicesStruct,proto3" json:"slices_struct,omitempty"` - PointersStruct *PointersStruct `protobuf:"bytes,4,opt,name=pointers_struct,json=PointersStruct,proto3" json:"pointers_struct,omitempty"` - EmptyStruct *EmptyStruct `protobuf:"bytes,5,opt,name=empty_struct,json=EmptyStruct,proto3" json:"empty_struct,omitempty"` -} - -func (x *EmbeddedSt3) Reset() { - *x = EmbeddedSt3{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *EmbeddedSt3) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*EmbeddedSt3) ProtoMessage() {} - -func (x *EmbeddedSt3) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[12] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use EmbeddedSt3.ProtoReflect.Descriptor instead. -func (*EmbeddedSt3) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{12} -} - -func (x *EmbeddedSt3) GetPrimitivesStruct() *PrimitivesStruct { - if x != nil { - return x.PrimitivesStruct - } - return nil -} - -func (x *EmbeddedSt3) GetArraysStruct() *ArraysStruct { - if x != nil { - return x.ArraysStruct - } - return nil -} - -func (x *EmbeddedSt3) GetSlicesStruct() *SlicesStruct { - if x != nil { - return x.SlicesStruct - } - return nil -} - -func (x *EmbeddedSt3) GetPointersStruct() *PointersStruct { - if x != nil { - return x.PointersStruct - } - return nil -} - -func (x *EmbeddedSt3) GetEmptyStruct() *EmptyStruct { - if x != nil { - return x.EmptyStruct - } - return nil -} - -type EmbeddedSt4 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Foo1 int64 `protobuf:"zigzag64,1,opt,name=foo1,json=Foo1,proto3" json:"foo1,omitempty"` - PrimitivesStruct *PrimitivesStruct `protobuf:"bytes,2,opt,name=primitives_struct,json=PrimitivesStruct,proto3" json:"primitives_struct,omitempty"` - Foo2 string `protobuf:"bytes,3,opt,name=foo2,json=Foo2,proto3" json:"foo2,omitempty"` - ArraysStructField *ArraysStruct `protobuf:"bytes,4,opt,name=arrays_struct_field,json=ArraysStructField,proto3" json:"arrays_struct_field,omitempty"` - Foo3 []byte `protobuf:"bytes,5,opt,name=foo3,json=Foo3,proto3" json:"foo3,omitempty"` - SlicesStruct *SlicesStruct `protobuf:"bytes,6,opt,name=slices_struct,json=SlicesStruct,proto3" json:"slices_struct,omitempty"` - Foo4 bool `protobuf:"varint,7,opt,name=foo4,json=Foo4,proto3" json:"foo4,omitempty"` - PointersStructField *PointersStruct `protobuf:"bytes,8,opt,name=pointers_struct_field,json=PointersStructField,proto3" json:"pointers_struct_field,omitempty"` - Foo5 uint64 `protobuf:"varint,9,opt,name=foo5,json=Foo5,proto3" json:"foo5,omitempty"` -} - -func (x *EmbeddedSt4) Reset() { - *x = EmbeddedSt4{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[13] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *EmbeddedSt4) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*EmbeddedSt4) ProtoMessage() {} - -func (x *EmbeddedSt4) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[13] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use EmbeddedSt4.ProtoReflect.Descriptor instead. -func (*EmbeddedSt4) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{13} -} - -func (x *EmbeddedSt4) GetFoo1() int64 { - if x != nil { - return x.Foo1 - } - return 0 -} - -func (x *EmbeddedSt4) GetPrimitivesStruct() *PrimitivesStruct { - if x != nil { - return x.PrimitivesStruct - } - return nil -} - -func (x *EmbeddedSt4) GetFoo2() string { - if x != nil { - return x.Foo2 - } - return "" -} - -func (x *EmbeddedSt4) GetArraysStructField() *ArraysStruct { - if x != nil { - return x.ArraysStructField - } - return nil -} - -func (x *EmbeddedSt4) GetFoo3() []byte { - if x != nil { - return x.Foo3 - } - return nil -} - -func (x *EmbeddedSt4) GetSlicesStruct() *SlicesStruct { - if x != nil { - return x.SlicesStruct - } - return nil -} - -func (x *EmbeddedSt4) GetFoo4() bool { - if x != nil { - return x.Foo4 - } - return false -} - -func (x *EmbeddedSt4) GetPointersStructField() *PointersStruct { - if x != nil { - return x.PointersStructField - } - return nil -} - -func (x *EmbeddedSt4) GetFoo5() uint64 { - if x != nil { - return x.Foo5 - } - return 0 -} - -type EmbeddedSt5NameOverride struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Foo1 int64 `protobuf:"zigzag64,1,opt,name=foo1,json=Foo1,proto3" json:"foo1,omitempty"` - PrimitivesStruct *PrimitivesStruct `protobuf:"bytes,2,opt,name=primitives_struct,json=PrimitivesStruct,proto3" json:"primitives_struct,omitempty"` - Foo2 string `protobuf:"bytes,3,opt,name=foo2,json=Foo2,proto3" json:"foo2,omitempty"` - ArraysStructField *ArraysStruct `protobuf:"bytes,4,opt,name=arrays_struct_field,json=ArraysStructField,proto3" json:"arrays_struct_field,omitempty"` - Foo3 []byte `protobuf:"bytes,5,opt,name=foo3,json=Foo3,proto3" json:"foo3,omitempty"` - SlicesStruct *SlicesStruct `protobuf:"bytes,6,opt,name=slices_struct,json=SlicesStruct,proto3" json:"slices_struct,omitempty"` - Foo4 bool `protobuf:"varint,7,opt,name=foo4,json=Foo4,proto3" json:"foo4,omitempty"` - PointersStructField *PointersStruct `protobuf:"bytes,8,opt,name=pointers_struct_field,json=PointersStructField,proto3" json:"pointers_struct_field,omitempty"` - Foo5 uint64 `protobuf:"varint,9,opt,name=foo5,json=Foo5,proto3" json:"foo5,omitempty"` -} - -func (x *EmbeddedSt5NameOverride) Reset() { - *x = EmbeddedSt5NameOverride{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[14] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *EmbeddedSt5NameOverride) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*EmbeddedSt5NameOverride) ProtoMessage() {} - -func (x *EmbeddedSt5NameOverride) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[14] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use EmbeddedSt5NameOverride.ProtoReflect.Descriptor instead. -func (*EmbeddedSt5NameOverride) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{14} -} - -func (x *EmbeddedSt5NameOverride) GetFoo1() int64 { - if x != nil { - return x.Foo1 - } - return 0 -} - -func (x *EmbeddedSt5NameOverride) GetPrimitivesStruct() *PrimitivesStruct { - if x != nil { - return x.PrimitivesStruct - } - return nil -} - -func (x *EmbeddedSt5NameOverride) GetFoo2() string { - if x != nil { - return x.Foo2 - } - return "" -} - -func (x *EmbeddedSt5NameOverride) GetArraysStructField() *ArraysStruct { - if x != nil { - return x.ArraysStructField - } - return nil -} - -func (x *EmbeddedSt5NameOverride) GetFoo3() []byte { - if x != nil { - return x.Foo3 - } - return nil -} - -func (x *EmbeddedSt5NameOverride) GetSlicesStruct() *SlicesStruct { - if x != nil { - return x.SlicesStruct - } - return nil -} - -func (x *EmbeddedSt5NameOverride) GetFoo4() bool { - if x != nil { - return x.Foo4 - } - return false -} - -func (x *EmbeddedSt5NameOverride) GetPointersStructField() *PointersStruct { - if x != nil { - return x.PointersStructField - } - return nil -} - -func (x *EmbeddedSt5NameOverride) GetFoo5() uint64 { - if x != nil { - return x.Foo5 - } - return 0 -} - -type AminoMarshalerStruct1 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - C int64 `protobuf:"zigzag64,1,opt,name=c,json=C,proto3" json:"c,omitempty"` - D int64 `protobuf:"zigzag64,2,opt,name=d,json=D,proto3" json:"d,omitempty"` -} - -func (x *AminoMarshalerStruct1) Reset() { - *x = AminoMarshalerStruct1{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[15] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AminoMarshalerStruct1) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AminoMarshalerStruct1) ProtoMessage() {} - -func (x *AminoMarshalerStruct1) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[15] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AminoMarshalerStruct1.ProtoReflect.Descriptor instead. -func (*AminoMarshalerStruct1) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{15} -} - -func (x *AminoMarshalerStruct1) GetC() int64 { - if x != nil { - return x.C - } - return 0 -} - -func (x *AminoMarshalerStruct1) GetD() int64 { - if x != nil { - return x.D - } - return 0 -} - -type ReprStruct1 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - C int64 `protobuf:"zigzag64,1,opt,name=c,json=C,proto3" json:"c,omitempty"` - D int64 `protobuf:"zigzag64,2,opt,name=d,json=D,proto3" json:"d,omitempty"` -} - -func (x *ReprStruct1) Reset() { - *x = ReprStruct1{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[16] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ReprStruct1) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ReprStruct1) ProtoMessage() {} - -func (x *ReprStruct1) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[16] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ReprStruct1.ProtoReflect.Descriptor instead. -func (*ReprStruct1) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{16} -} - -func (x *ReprStruct1) GetC() int64 { - if x != nil { - return x.C - } - return 0 -} - -func (x *ReprStruct1) GetD() int64 { - if x != nil { - return x.D - } - return 0 -} - -type AminoMarshalerStruct2 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []*ReprElem2 `protobuf:"bytes,1,rep,name=value,proto3" json:"value,omitempty"` -} - -func (x *AminoMarshalerStruct2) Reset() { - *x = AminoMarshalerStruct2{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[17] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AminoMarshalerStruct2) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AminoMarshalerStruct2) ProtoMessage() {} - -func (x *AminoMarshalerStruct2) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[17] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AminoMarshalerStruct2.ProtoReflect.Descriptor instead. -func (*AminoMarshalerStruct2) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{17} -} - -func (x *AminoMarshalerStruct2) GetValue() []*ReprElem2 { - if x != nil { - return x.Value - } - return nil -} - -type ReprElem2 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Key string `protobuf:"bytes,1,opt,name=key,json=Key,proto3" json:"key,omitempty"` - Value *anypb.Any `protobuf:"bytes,2,opt,name=value,json=Value,proto3" json:"value,omitempty"` -} - -func (x *ReprElem2) Reset() { - *x = ReprElem2{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[18] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ReprElem2) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ReprElem2) ProtoMessage() {} - -func (x *ReprElem2) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[18] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ReprElem2.ProtoReflect.Descriptor instead. -func (*ReprElem2) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{18} -} - -func (x *ReprElem2) GetKey() string { - if x != nil { - return x.Key - } - return "" -} - -func (x *ReprElem2) GetValue() *anypb.Any { - if x != nil { - return x.Value - } - return nil -} - -type AminoMarshalerStruct3 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value int32 `protobuf:"zigzag32,1,opt,name=value,proto3" json:"value,omitempty"` -} - -func (x *AminoMarshalerStruct3) Reset() { - *x = AminoMarshalerStruct3{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[19] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AminoMarshalerStruct3) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AminoMarshalerStruct3) ProtoMessage() {} - -func (x *AminoMarshalerStruct3) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[19] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AminoMarshalerStruct3.ProtoReflect.Descriptor instead. -func (*AminoMarshalerStruct3) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{19} -} - -func (x *AminoMarshalerStruct3) GetValue() int32 { - if x != nil { - return x.Value - } - return 0 -} - -type AminoMarshalerInt4 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - A int32 `protobuf:"zigzag32,1,opt,name=a,json=A,proto3" json:"a,omitempty"` -} - -func (x *AminoMarshalerInt4) Reset() { - *x = AminoMarshalerInt4{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[20] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AminoMarshalerInt4) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AminoMarshalerInt4) ProtoMessage() {} - -func (x *AminoMarshalerInt4) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[20] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AminoMarshalerInt4.ProtoReflect.Descriptor instead. -func (*AminoMarshalerInt4) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{20} -} - -func (x *AminoMarshalerInt4) GetA() int32 { - if x != nil { - return x.A - } - return 0 -} - -type AminoMarshalerInt5 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` -} - -func (x *AminoMarshalerInt5) Reset() { - *x = AminoMarshalerInt5{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[21] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AminoMarshalerInt5) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AminoMarshalerInt5) ProtoMessage() {} - -func (x *AminoMarshalerInt5) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[21] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AminoMarshalerInt5.ProtoReflect.Descriptor instead. -func (*AminoMarshalerInt5) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{21} -} - -func (x *AminoMarshalerInt5) GetValue() string { - if x != nil { - return x.Value - } - return "" -} - -type AminoMarshalerStruct6 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []*AminoMarshalerStruct1 `protobuf:"bytes,1,rep,name=value,proto3" json:"value,omitempty"` -} - -func (x *AminoMarshalerStruct6) Reset() { - *x = AminoMarshalerStruct6{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[22] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AminoMarshalerStruct6) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AminoMarshalerStruct6) ProtoMessage() {} - -func (x *AminoMarshalerStruct6) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[22] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AminoMarshalerStruct6.ProtoReflect.Descriptor instead. -func (*AminoMarshalerStruct6) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{22} -} - -func (x *AminoMarshalerStruct6) GetValue() []*AminoMarshalerStruct1 { - if x != nil { - return x.Value - } - return nil -} - -type AminoMarshalerStruct7 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []byte `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` -} - -func (x *AminoMarshalerStruct7) Reset() { - *x = AminoMarshalerStruct7{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[23] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AminoMarshalerStruct7) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AminoMarshalerStruct7) ProtoMessage() {} - -func (x *AminoMarshalerStruct7) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[23] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AminoMarshalerStruct7.ProtoReflect.Descriptor instead. -func (*AminoMarshalerStruct7) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{23} -} - -func (x *AminoMarshalerStruct7) GetValue() []byte { - if x != nil { - return x.Value - } - return nil -} - -type ReprElem7 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value uint32 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"` -} - -func (x *ReprElem7) Reset() { - *x = ReprElem7{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[24] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ReprElem7) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ReprElem7) ProtoMessage() {} - -func (x *ReprElem7) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[24] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ReprElem7.ProtoReflect.Descriptor instead. -func (*ReprElem7) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{24} -} - -func (x *ReprElem7) GetValue() uint32 { - if x != nil { - return x.Value - } - return 0 -} - -type IntDef struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value int64 `protobuf:"zigzag64,1,opt,name=value,proto3" json:"value,omitempty"` -} - -func (x *IntDef) Reset() { - *x = IntDef{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[25] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *IntDef) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*IntDef) ProtoMessage() {} - -func (x *IntDef) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[25] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use IntDef.ProtoReflect.Descriptor instead. -func (*IntDef) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{25} -} - -func (x *IntDef) GetValue() int64 { - if x != nil { - return x.Value - } - return 0 -} - -type IntAr struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []int64 `protobuf:"zigzag64,1,rep,packed,name=value,proto3" json:"value,omitempty"` -} - -func (x *IntAr) Reset() { - *x = IntAr{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[26] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *IntAr) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*IntAr) ProtoMessage() {} - -func (x *IntAr) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[26] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use IntAr.ProtoReflect.Descriptor instead. -func (*IntAr) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{26} -} - -func (x *IntAr) GetValue() []int64 { - if x != nil { - return x.Value - } - return nil -} - -type IntSl struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []int64 `protobuf:"zigzag64,1,rep,packed,name=value,proto3" json:"value,omitempty"` -} - -func (x *IntSl) Reset() { - *x = IntSl{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[27] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *IntSl) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*IntSl) ProtoMessage() {} - -func (x *IntSl) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[27] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use IntSl.ProtoReflect.Descriptor instead. -func (*IntSl) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{27} -} - -func (x *IntSl) GetValue() []int64 { - if x != nil { - return x.Value - } - return nil -} - -type ByteAr struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []byte `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` -} - -func (x *ByteAr) Reset() { - *x = ByteAr{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[28] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ByteAr) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ByteAr) ProtoMessage() {} - -func (x *ByteAr) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[28] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ByteAr.ProtoReflect.Descriptor instead. -func (*ByteAr) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{28} -} - -func (x *ByteAr) GetValue() []byte { - if x != nil { - return x.Value - } - return nil -} - -type ByteSl struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []byte `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` -} - -func (x *ByteSl) Reset() { - *x = ByteSl{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[29] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ByteSl) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ByteSl) ProtoMessage() {} - -func (x *ByteSl) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[29] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ByteSl.ProtoReflect.Descriptor instead. -func (*ByteSl) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{29} -} - -func (x *ByteSl) GetValue() []byte { - if x != nil { - return x.Value - } - return nil -} - -type PrimitivesStructDef struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Int8 int32 `protobuf:"zigzag32,1,opt,name=int8,json=Int8,proto3" json:"int8,omitempty"` - Int16 int32 `protobuf:"zigzag32,2,opt,name=int16,json=Int16,proto3" json:"int16,omitempty"` - Int32 int32 `protobuf:"zigzag32,3,opt,name=int32,json=Int32,proto3" json:"int32,omitempty"` - Int32Fixed int32 `protobuf:"fixed32,4,opt,name=int32_fixed,json=Int32Fixed,proto3" json:"int32_fixed,omitempty"` - Int64 int64 `protobuf:"zigzag64,5,opt,name=int64,json=Int64,proto3" json:"int64,omitempty"` - Int64Fixed int64 `protobuf:"fixed64,6,opt,name=int64_fixed,json=Int64Fixed,proto3" json:"int64_fixed,omitempty"` - Int int64 `protobuf:"zigzag64,7,opt,name=int,json=Int,proto3" json:"int,omitempty"` - Byte uint32 `protobuf:"varint,8,opt,name=byte,json=Byte,proto3" json:"byte,omitempty"` - Uint8 uint32 `protobuf:"varint,9,opt,name=uint8,json=Uint8,proto3" json:"uint8,omitempty"` - Uint16 uint32 `protobuf:"varint,10,opt,name=uint16,json=Uint16,proto3" json:"uint16,omitempty"` - Uint32 uint32 `protobuf:"varint,11,opt,name=uint32,json=Uint32,proto3" json:"uint32,omitempty"` - Uint32Fixed uint32 `protobuf:"fixed32,12,opt,name=uint32_fixed,json=Uint32Fixed,proto3" json:"uint32_fixed,omitempty"` - Uint64 uint64 `protobuf:"varint,13,opt,name=uint64,json=Uint64,proto3" json:"uint64,omitempty"` - Uint64Fixed uint64 `protobuf:"fixed64,14,opt,name=uint64_fixed,json=Uint64Fixed,proto3" json:"uint64_fixed,omitempty"` - Uint uint64 `protobuf:"varint,15,opt,name=uint,json=Uint,proto3" json:"uint,omitempty"` - Str string `protobuf:"bytes,16,opt,name=str,json=Str,proto3" json:"str,omitempty"` - Bytes []byte `protobuf:"bytes,17,opt,name=bytes,json=Bytes,proto3" json:"bytes,omitempty"` - Time *timestamppb.Timestamp `protobuf:"bytes,18,opt,name=time,json=Time,proto3" json:"time,omitempty"` - Duration *durationpb.Duration `protobuf:"bytes,19,opt,name=duration,json=Duration,proto3" json:"duration,omitempty"` - Empty *EmptyStruct `protobuf:"bytes,20,opt,name=empty,json=Empty,proto3" json:"empty,omitempty"` -} - -func (x *PrimitivesStructDef) Reset() { - *x = PrimitivesStructDef{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[30] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PrimitivesStructDef) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PrimitivesStructDef) ProtoMessage() {} - -func (x *PrimitivesStructDef) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[30] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PrimitivesStructDef.ProtoReflect.Descriptor instead. -func (*PrimitivesStructDef) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{30} -} - -func (x *PrimitivesStructDef) GetInt8() int32 { - if x != nil { - return x.Int8 - } - return 0 -} - -func (x *PrimitivesStructDef) GetInt16() int32 { - if x != nil { - return x.Int16 - } - return 0 -} - -func (x *PrimitivesStructDef) GetInt32() int32 { - if x != nil { - return x.Int32 - } - return 0 -} - -func (x *PrimitivesStructDef) GetInt32Fixed() int32 { - if x != nil { - return x.Int32Fixed - } - return 0 -} - -func (x *PrimitivesStructDef) GetInt64() int64 { - if x != nil { - return x.Int64 - } - return 0 -} - -func (x *PrimitivesStructDef) GetInt64Fixed() int64 { - if x != nil { - return x.Int64Fixed - } - return 0 -} - -func (x *PrimitivesStructDef) GetInt() int64 { - if x != nil { - return x.Int - } - return 0 -} - -func (x *PrimitivesStructDef) GetByte() uint32 { - if x != nil { - return x.Byte - } - return 0 -} - -func (x *PrimitivesStructDef) GetUint8() uint32 { - if x != nil { - return x.Uint8 - } - return 0 -} - -func (x *PrimitivesStructDef) GetUint16() uint32 { - if x != nil { - return x.Uint16 - } - return 0 -} - -func (x *PrimitivesStructDef) GetUint32() uint32 { - if x != nil { - return x.Uint32 - } - return 0 -} - -func (x *PrimitivesStructDef) GetUint32Fixed() uint32 { - if x != nil { - return x.Uint32Fixed - } - return 0 -} - -func (x *PrimitivesStructDef) GetUint64() uint64 { - if x != nil { - return x.Uint64 - } - return 0 -} - -func (x *PrimitivesStructDef) GetUint64Fixed() uint64 { - if x != nil { - return x.Uint64Fixed - } - return 0 -} - -func (x *PrimitivesStructDef) GetUint() uint64 { - if x != nil { - return x.Uint - } - return 0 -} - -func (x *PrimitivesStructDef) GetStr() string { - if x != nil { - return x.Str - } - return "" -} - -func (x *PrimitivesStructDef) GetBytes() []byte { - if x != nil { - return x.Bytes - } - return nil -} - -func (x *PrimitivesStructDef) GetTime() *timestamppb.Timestamp { - if x != nil { - return x.Time - } - return nil -} - -func (x *PrimitivesStructDef) GetDuration() *durationpb.Duration { - if x != nil { - return x.Duration - } - return nil -} - -func (x *PrimitivesStructDef) GetEmpty() *EmptyStruct { - if x != nil { - return x.Empty - } - return nil -} - -type PrimitivesStructSl struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []*PrimitivesStruct `protobuf:"bytes,1,rep,name=value,proto3" json:"value,omitempty"` -} - -func (x *PrimitivesStructSl) Reset() { - *x = PrimitivesStructSl{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[31] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PrimitivesStructSl) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PrimitivesStructSl) ProtoMessage() {} - -func (x *PrimitivesStructSl) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[31] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PrimitivesStructSl.ProtoReflect.Descriptor instead. -func (*PrimitivesStructSl) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{31} -} - -func (x *PrimitivesStructSl) GetValue() []*PrimitivesStruct { - if x != nil { - return x.Value - } - return nil -} - -type PrimitivesStructAr struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []*PrimitivesStruct `protobuf:"bytes,1,rep,name=value,proto3" json:"value,omitempty"` -} - -func (x *PrimitivesStructAr) Reset() { - *x = PrimitivesStructAr{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[32] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PrimitivesStructAr) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PrimitivesStructAr) ProtoMessage() {} - -func (x *PrimitivesStructAr) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[32] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PrimitivesStructAr.ProtoReflect.Descriptor instead. -func (*PrimitivesStructAr) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{32} -} - -func (x *PrimitivesStructAr) GetValue() []*PrimitivesStruct { - if x != nil { - return x.Value - } - return nil -} - -type Concrete1 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *Concrete1) Reset() { - *x = Concrete1{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[33] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Concrete1) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Concrete1) ProtoMessage() {} - -func (x *Concrete1) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[33] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Concrete1.ProtoReflect.Descriptor instead. -func (*Concrete1) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{33} -} - -type Concrete2 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *Concrete2) Reset() { - *x = Concrete2{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[34] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Concrete2) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Concrete2) ProtoMessage() {} - -func (x *Concrete2) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[34] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Concrete2.ProtoReflect.Descriptor instead. -func (*Concrete2) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{34} -} - -type ConcreteTypeDef struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []byte `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` -} - -func (x *ConcreteTypeDef) Reset() { - *x = ConcreteTypeDef{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[35] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ConcreteTypeDef) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ConcreteTypeDef) ProtoMessage() {} - -func (x *ConcreteTypeDef) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[35] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ConcreteTypeDef.ProtoReflect.Descriptor instead. -func (*ConcreteTypeDef) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{35} -} - -func (x *ConcreteTypeDef) GetValue() []byte { - if x != nil { - return x.Value - } - return nil -} - -type ConcreteWrappedBytes struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []byte `protobuf:"bytes,1,opt,name=value,json=Value,proto3" json:"value,omitempty"` -} - -func (x *ConcreteWrappedBytes) Reset() { - *x = ConcreteWrappedBytes{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[36] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ConcreteWrappedBytes) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ConcreteWrappedBytes) ProtoMessage() {} - -func (x *ConcreteWrappedBytes) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[36] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ConcreteWrappedBytes.ProtoReflect.Descriptor instead. -func (*ConcreteWrappedBytes) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{36} -} - -func (x *ConcreteWrappedBytes) GetValue() []byte { - if x != nil { - return x.Value - } - return nil -} - -type InterfaceFieldsStruct struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - F1 *anypb.Any `protobuf:"bytes,1,opt,name=f1,json=F1,proto3" json:"f1,omitempty"` - F2 *anypb.Any `protobuf:"bytes,2,opt,name=f2,json=F2,proto3" json:"f2,omitempty"` - F3 *anypb.Any `protobuf:"bytes,3,opt,name=f3,json=F3,proto3" json:"f3,omitempty"` - F4 *anypb.Any `protobuf:"bytes,4,opt,name=f4,json=F4,proto3" json:"f4,omitempty"` -} - -func (x *InterfaceFieldsStruct) Reset() { - *x = InterfaceFieldsStruct{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[37] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *InterfaceFieldsStruct) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*InterfaceFieldsStruct) ProtoMessage() {} - -func (x *InterfaceFieldsStruct) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[37] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use InterfaceFieldsStruct.ProtoReflect.Descriptor instead. -func (*InterfaceFieldsStruct) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{37} -} - -func (x *InterfaceFieldsStruct) GetF1() *anypb.Any { - if x != nil { - return x.F1 - } - return nil -} - -func (x *InterfaceFieldsStruct) GetF2() *anypb.Any { - if x != nil { - return x.F2 - } - return nil -} - -func (x *InterfaceFieldsStruct) GetF3() *anypb.Any { - if x != nil { - return x.F3 - } - return nil -} - -func (x *InterfaceFieldsStruct) GetF4() *anypb.Any { - if x != nil { - return x.F4 - } - return nil -} - -type TESTS_BytesList struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value [][]byte `protobuf:"bytes,1,rep,name=Value,proto3" json:"Value,omitempty"` -} - -func (x *TESTS_BytesList) Reset() { - *x = TESTS_BytesList{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[38] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TESTS_BytesList) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TESTS_BytesList) ProtoMessage() {} - -func (x *TESTS_BytesList) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[38] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TESTS_BytesList.ProtoReflect.Descriptor instead. -func (*TESTS_BytesList) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{38} -} - -func (x *TESTS_BytesList) GetValue() [][]byte { - if x != nil { - return x.Value - } - return nil -} - -type TESTS_BytesListList struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []*TESTS_BytesList `protobuf:"bytes,1,rep,name=Value,proto3" json:"Value,omitempty"` -} - -func (x *TESTS_BytesListList) Reset() { - *x = TESTS_BytesListList{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[39] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TESTS_BytesListList) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TESTS_BytesListList) ProtoMessage() {} - -func (x *TESTS_BytesListList) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[39] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TESTS_BytesListList.ProtoReflect.Descriptor instead. -func (*TESTS_BytesListList) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{39} -} - -func (x *TESTS_BytesListList) GetValue() []*TESTS_BytesList { - if x != nil { - return x.Value - } - return nil -} - -type TESTS_DurationList struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []*durationpb.Duration `protobuf:"bytes,1,rep,name=Value,proto3" json:"Value,omitempty"` -} - -func (x *TESTS_DurationList) Reset() { - *x = TESTS_DurationList{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[40] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TESTS_DurationList) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TESTS_DurationList) ProtoMessage() {} - -func (x *TESTS_DurationList) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[40] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TESTS_DurationList.ProtoReflect.Descriptor instead. -func (*TESTS_DurationList) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{40} -} - -func (x *TESTS_DurationList) GetValue() []*durationpb.Duration { - if x != nil { - return x.Value - } - return nil -} - -type TESTS_EmptyStructList struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []*EmptyStruct `protobuf:"bytes,1,rep,name=Value,proto3" json:"Value,omitempty"` -} - -func (x *TESTS_EmptyStructList) Reset() { - *x = TESTS_EmptyStructList{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[41] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TESTS_EmptyStructList) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TESTS_EmptyStructList) ProtoMessage() {} - -func (x *TESTS_EmptyStructList) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[41] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TESTS_EmptyStructList.ProtoReflect.Descriptor instead. -func (*TESTS_EmptyStructList) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{41} -} - -func (x *TESTS_EmptyStructList) GetValue() []*EmptyStruct { - if x != nil { - return x.Value - } - return nil -} - -type TESTS_Fixed32Int32ValueList struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []int32 `protobuf:"fixed32,1,rep,packed,name=Value,proto3" json:"Value,omitempty"` -} - -func (x *TESTS_Fixed32Int32ValueList) Reset() { - *x = TESTS_Fixed32Int32ValueList{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[42] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TESTS_Fixed32Int32ValueList) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TESTS_Fixed32Int32ValueList) ProtoMessage() {} - -func (x *TESTS_Fixed32Int32ValueList) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[42] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TESTS_Fixed32Int32ValueList.ProtoReflect.Descriptor instead. -func (*TESTS_Fixed32Int32ValueList) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{42} -} - -func (x *TESTS_Fixed32Int32ValueList) GetValue() []int32 { - if x != nil { - return x.Value - } - return nil -} - -type TESTS_Fixed32UInt32ValueList struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []uint32 `protobuf:"fixed32,1,rep,packed,name=Value,proto3" json:"Value,omitempty"` -} - -func (x *TESTS_Fixed32UInt32ValueList) Reset() { - *x = TESTS_Fixed32UInt32ValueList{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[43] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TESTS_Fixed32UInt32ValueList) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TESTS_Fixed32UInt32ValueList) ProtoMessage() {} - -func (x *TESTS_Fixed32UInt32ValueList) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[43] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TESTS_Fixed32UInt32ValueList.ProtoReflect.Descriptor instead. -func (*TESTS_Fixed32UInt32ValueList) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{43} -} - -func (x *TESTS_Fixed32UInt32ValueList) GetValue() []uint32 { - if x != nil { - return x.Value - } - return nil -} - -type TESTS_Fixed64Int64ValueList struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []int64 `protobuf:"fixed64,1,rep,packed,name=Value,proto3" json:"Value,omitempty"` -} - -func (x *TESTS_Fixed64Int64ValueList) Reset() { - *x = TESTS_Fixed64Int64ValueList{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[44] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TESTS_Fixed64Int64ValueList) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TESTS_Fixed64Int64ValueList) ProtoMessage() {} - -func (x *TESTS_Fixed64Int64ValueList) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[44] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TESTS_Fixed64Int64ValueList.ProtoReflect.Descriptor instead. -func (*TESTS_Fixed64Int64ValueList) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{44} -} - -func (x *TESTS_Fixed64Int64ValueList) GetValue() []int64 { - if x != nil { - return x.Value - } - return nil -} - -type TESTS_Fixed64UInt64ValueList struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []uint64 `protobuf:"fixed64,1,rep,packed,name=Value,proto3" json:"Value,omitempty"` -} - -func (x *TESTS_Fixed64UInt64ValueList) Reset() { - *x = TESTS_Fixed64UInt64ValueList{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[45] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TESTS_Fixed64UInt64ValueList) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TESTS_Fixed64UInt64ValueList) ProtoMessage() {} - -func (x *TESTS_Fixed64UInt64ValueList) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[45] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TESTS_Fixed64UInt64ValueList.ProtoReflect.Descriptor instead. -func (*TESTS_Fixed64UInt64ValueList) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{45} -} - -func (x *TESTS_Fixed64UInt64ValueList) GetValue() []uint64 { - if x != nil { - return x.Value - } - return nil -} - -type TESTS_Int16List struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []int32 `protobuf:"zigzag32,1,rep,packed,name=Value,proto3" json:"Value,omitempty"` -} - -func (x *TESTS_Int16List) Reset() { - *x = TESTS_Int16List{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[46] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TESTS_Int16List) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TESTS_Int16List) ProtoMessage() {} - -func (x *TESTS_Int16List) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[46] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TESTS_Int16List.ProtoReflect.Descriptor instead. -func (*TESTS_Int16List) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{46} -} - -func (x *TESTS_Int16List) GetValue() []int32 { - if x != nil { - return x.Value - } - return nil -} - -type TESTS_Int32ValueList struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []int32 `protobuf:"zigzag32,1,rep,packed,name=Value,proto3" json:"Value,omitempty"` -} - -func (x *TESTS_Int32ValueList) Reset() { - *x = TESTS_Int32ValueList{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[47] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TESTS_Int32ValueList) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TESTS_Int32ValueList) ProtoMessage() {} - -func (x *TESTS_Int32ValueList) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[47] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TESTS_Int32ValueList.ProtoReflect.Descriptor instead. -func (*TESTS_Int32ValueList) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{47} -} - -func (x *TESTS_Int32ValueList) GetValue() []int32 { - if x != nil { - return x.Value - } - return nil -} - -type TESTS_Int64ValueList struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []int64 `protobuf:"zigzag64,1,rep,packed,name=Value,proto3" json:"Value,omitempty"` -} - -func (x *TESTS_Int64ValueList) Reset() { - *x = TESTS_Int64ValueList{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[48] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TESTS_Int64ValueList) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TESTS_Int64ValueList) ProtoMessage() {} - -func (x *TESTS_Int64ValueList) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[48] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TESTS_Int64ValueList.ProtoReflect.Descriptor instead. -func (*TESTS_Int64ValueList) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{48} -} - -func (x *TESTS_Int64ValueList) GetValue() []int64 { - if x != nil { - return x.Value - } - return nil -} - -type TESTS_Int8List struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []int32 `protobuf:"zigzag32,1,rep,packed,name=Value,proto3" json:"Value,omitempty"` -} - -func (x *TESTS_Int8List) Reset() { - *x = TESTS_Int8List{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[49] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TESTS_Int8List) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TESTS_Int8List) ProtoMessage() {} - -func (x *TESTS_Int8List) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[49] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TESTS_Int8List.ProtoReflect.Descriptor instead. -func (*TESTS_Int8List) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{49} -} - -func (x *TESTS_Int8List) GetValue() []int32 { - if x != nil { - return x.Value - } - return nil -} - -type TESTS_StringValueList struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []string `protobuf:"bytes,1,rep,name=Value,proto3" json:"Value,omitempty"` -} - -func (x *TESTS_StringValueList) Reset() { - *x = TESTS_StringValueList{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[50] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TESTS_StringValueList) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TESTS_StringValueList) ProtoMessage() {} - -func (x *TESTS_StringValueList) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[50] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TESTS_StringValueList.ProtoReflect.Descriptor instead. -func (*TESTS_StringValueList) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{50} -} - -func (x *TESTS_StringValueList) GetValue() []string { - if x != nil { - return x.Value - } - return nil -} - -type TESTS_TimestampList struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []*timestamppb.Timestamp `protobuf:"bytes,1,rep,name=Value,proto3" json:"Value,omitempty"` -} - -func (x *TESTS_TimestampList) Reset() { - *x = TESTS_TimestampList{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[51] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TESTS_TimestampList) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TESTS_TimestampList) ProtoMessage() {} - -func (x *TESTS_TimestampList) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[51] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TESTS_TimestampList.ProtoReflect.Descriptor instead. -func (*TESTS_TimestampList) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{51} -} - -func (x *TESTS_TimestampList) GetValue() []*timestamppb.Timestamp { - if x != nil { - return x.Value - } - return nil -} - -type TESTS_UInt16List struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []uint32 `protobuf:"varint,1,rep,packed,name=Value,proto3" json:"Value,omitempty"` -} - -func (x *TESTS_UInt16List) Reset() { - *x = TESTS_UInt16List{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[52] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TESTS_UInt16List) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TESTS_UInt16List) ProtoMessage() {} - -func (x *TESTS_UInt16List) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[52] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TESTS_UInt16List.ProtoReflect.Descriptor instead. -func (*TESTS_UInt16List) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{52} -} - -func (x *TESTS_UInt16List) GetValue() []uint32 { - if x != nil { - return x.Value - } - return nil -} - -type TESTS_UInt32ValueList struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []uint32 `protobuf:"varint,1,rep,packed,name=Value,proto3" json:"Value,omitempty"` -} - -func (x *TESTS_UInt32ValueList) Reset() { - *x = TESTS_UInt32ValueList{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[53] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TESTS_UInt32ValueList) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TESTS_UInt32ValueList) ProtoMessage() {} - -func (x *TESTS_UInt32ValueList) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[53] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TESTS_UInt32ValueList.ProtoReflect.Descriptor instead. -func (*TESTS_UInt32ValueList) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{53} -} - -func (x *TESTS_UInt32ValueList) GetValue() []uint32 { - if x != nil { - return x.Value - } - return nil -} - -type TESTS_UInt64ValueList struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value []uint64 `protobuf:"varint,1,rep,packed,name=Value,proto3" json:"Value,omitempty"` -} - -func (x *TESTS_UInt64ValueList) Reset() { - *x = TESTS_UInt64ValueList{} - if protoimpl.UnsafeEnabled { - mi := &file_tests_proto_msgTypes[54] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TESTS_UInt64ValueList) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TESTS_UInt64ValueList) ProtoMessage() {} - -func (x *TESTS_UInt64ValueList) ProtoReflect() protoreflect.Message { - mi := &file_tests_proto_msgTypes[54] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TESTS_UInt64ValueList.ProtoReflect.Descriptor instead. -func (*TESTS_UInt64ValueList) Descriptor() ([]byte, []int) { - return file_tests_proto_rawDescGZIP(), []int{54} -} - -func (x *TESTS_UInt64ValueList) GetValue() []uint64 { - if x != nil { - return x.Value - } - return nil -} - -var File_tests_proto protoreflect.FileDescriptor - -var file_tests_proto_rawDesc = []byte{ - 0x0a, 0x0b, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x74, - 0x65, 0x73, 0x74, 0x73, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x22, 0x0d, 0x0a, 0x0b, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x22, - 0xc1, 0x04, 0x0a, 0x10, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x53, 0x74, - 0x72, 0x75, 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x6e, 0x74, 0x38, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x11, 0x52, 0x04, 0x49, 0x6e, 0x74, 0x38, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x74, 0x31, - 0x36, 0x18, 0x02, 0x20, 0x01, 0x28, 0x11, 0x52, 0x05, 0x49, 0x6e, 0x74, 0x31, 0x36, 0x12, 0x14, - 0x0a, 0x05, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x18, 0x03, 0x20, 0x01, 0x28, 0x11, 0x52, 0x05, 0x49, - 0x6e, 0x74, 0x33, 0x32, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x66, 0x69, - 0x78, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0f, 0x52, 0x0a, 0x49, 0x6e, 0x74, 0x33, 0x32, - 0x46, 0x69, 0x78, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x12, 0x52, 0x05, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x12, 0x1f, 0x0a, 0x0b, 0x69, - 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x10, - 0x52, 0x0a, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x46, 0x69, 0x78, 0x65, 0x64, 0x12, 0x10, 0x0a, 0x03, - 0x69, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x12, 0x52, 0x03, 0x49, 0x6e, 0x74, 0x12, 0x12, - 0x0a, 0x04, 0x62, 0x79, 0x74, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x42, 0x79, - 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x18, 0x09, 0x20, 0x01, 0x28, - 0x0d, 0x52, 0x05, 0x55, 0x69, 0x6e, 0x74, 0x38, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x69, 0x6e, 0x74, - 0x31, 0x36, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x55, 0x69, 0x6e, 0x74, 0x31, 0x36, - 0x12, 0x16, 0x0a, 0x06, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0d, - 0x52, 0x06, 0x55, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x12, 0x21, 0x0a, 0x0c, 0x75, 0x69, 0x6e, 0x74, - 0x33, 0x32, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x07, 0x52, 0x0b, - 0x55, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x78, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x75, - 0x69, 0x6e, 0x74, 0x36, 0x34, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x55, 0x69, 0x6e, - 0x74, 0x36, 0x34, 0x12, 0x21, 0x0a, 0x0c, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x66, 0x69, - 0x78, 0x65, 0x64, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x06, 0x52, 0x0b, 0x55, 0x69, 0x6e, 0x74, 0x36, - 0x34, 0x46, 0x69, 0x78, 0x65, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x69, 0x6e, 0x74, 0x18, 0x0f, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x55, 0x69, 0x6e, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x74, - 0x72, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x53, 0x74, 0x72, 0x12, 0x14, 0x0a, 0x05, - 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x42, 0x79, 0x74, - 0x65, 0x73, 0x12, 0x2e, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x54, 0x69, - 0x6d, 0x65, 0x12, 0x35, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x13, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x08, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x05, 0x65, 0x6d, 0x70, - 0x74, 0x79, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x05, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x22, 0x84, 0x01, 0x0a, 0x11, 0x53, 0x68, 0x6f, 0x72, 0x74, 0x41, 0x72, 0x72, - 0x61, 0x79, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x12, 0x33, 0x0a, 0x07, 0x74, 0x69, 0x6d, - 0x65, 0x5f, 0x61, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x06, 0x54, 0x69, 0x6d, 0x65, 0x41, 0x72, 0x12, 0x3a, - 0x0a, 0x0b, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x72, 0x18, 0x02, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, - 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x72, 0x22, 0xa1, 0x05, 0x0a, 0x0c, 0x41, - 0x72, 0x72, 0x61, 0x79, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x69, - 0x6e, 0x74, 0x38, 0x5f, 0x61, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x11, 0x52, 0x06, 0x49, 0x6e, - 0x74, 0x38, 0x41, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x61, 0x72, - 0x18, 0x02, 0x20, 0x03, 0x28, 0x11, 0x52, 0x07, 0x49, 0x6e, 0x74, 0x31, 0x36, 0x41, 0x72, 0x12, - 0x19, 0x0a, 0x08, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x61, 0x72, 0x18, 0x03, 0x20, 0x03, 0x28, - 0x11, 0x52, 0x07, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x41, 0x72, 0x12, 0x24, 0x0a, 0x0e, 0x69, 0x6e, - 0x74, 0x33, 0x32, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x61, 0x72, 0x18, 0x04, 0x20, 0x03, - 0x28, 0x0f, 0x52, 0x0c, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x78, 0x65, 0x64, 0x41, 0x72, - 0x12, 0x19, 0x0a, 0x08, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x61, 0x72, 0x18, 0x05, 0x20, 0x03, - 0x28, 0x12, 0x52, 0x07, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x41, 0x72, 0x12, 0x24, 0x0a, 0x0e, 0x69, - 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x61, 0x72, 0x18, 0x06, 0x20, - 0x03, 0x28, 0x10, 0x52, 0x0c, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x46, 0x69, 0x78, 0x65, 0x64, 0x41, - 0x72, 0x12, 0x15, 0x0a, 0x06, 0x69, 0x6e, 0x74, 0x5f, 0x61, 0x72, 0x18, 0x07, 0x20, 0x03, 0x28, - 0x12, 0x52, 0x05, 0x49, 0x6e, 0x74, 0x41, 0x72, 0x12, 0x17, 0x0a, 0x07, 0x62, 0x79, 0x74, 0x65, - 0x5f, 0x61, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x42, 0x79, 0x74, 0x65, 0x41, - 0x72, 0x12, 0x19, 0x0a, 0x08, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x61, 0x72, 0x18, 0x09, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x07, 0x55, 0x69, 0x6e, 0x74, 0x38, 0x41, 0x72, 0x12, 0x1b, 0x0a, 0x09, - 0x75, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x61, 0x72, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0d, 0x52, - 0x08, 0x55, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x41, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x75, 0x69, 0x6e, - 0x74, 0x33, 0x32, 0x5f, 0x61, 0x72, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x08, 0x55, 0x69, - 0x6e, 0x74, 0x33, 0x32, 0x41, 0x72, 0x12, 0x26, 0x0a, 0x0f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, - 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x61, 0x72, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x07, 0x52, - 0x0d, 0x55, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x78, 0x65, 0x64, 0x41, 0x72, 0x12, 0x1b, - 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x61, 0x72, 0x18, 0x0d, 0x20, 0x03, 0x28, - 0x04, 0x52, 0x08, 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x41, 0x72, 0x12, 0x26, 0x0a, 0x0f, 0x75, - 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x61, 0x72, 0x18, 0x0e, - 0x20, 0x03, 0x28, 0x06, 0x52, 0x0d, 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x46, 0x69, 0x78, 0x65, - 0x64, 0x41, 0x72, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x69, 0x6e, 0x74, 0x5f, 0x61, 0x72, 0x18, 0x0f, - 0x20, 0x03, 0x28, 0x04, 0x52, 0x06, 0x55, 0x69, 0x6e, 0x74, 0x41, 0x72, 0x12, 0x15, 0x0a, 0x06, - 0x73, 0x74, 0x72, 0x5f, 0x61, 0x72, 0x18, 0x10, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x53, 0x74, - 0x72, 0x41, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x61, 0x72, 0x18, - 0x11, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x42, 0x79, 0x74, 0x65, 0x73, 0x41, 0x72, 0x12, 0x33, - 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x61, 0x72, 0x18, 0x12, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x06, 0x54, 0x69, 0x6d, - 0x65, 0x41, 0x72, 0x12, 0x3a, 0x0a, 0x0b, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, - 0x61, 0x72, 0x18, 0x13, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x72, 0x12, - 0x2d, 0x0a, 0x08, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x5f, 0x61, 0x72, 0x18, 0x14, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x12, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x53, - 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x07, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x41, 0x72, 0x22, 0xd6, - 0x09, 0x0a, 0x12, 0x41, 0x72, 0x72, 0x61, 0x79, 0x73, 0x41, 0x72, 0x72, 0x61, 0x79, 0x73, 0x53, - 0x74, 0x72, 0x75, 0x63, 0x74, 0x12, 0x33, 0x0a, 0x0a, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x61, 0x72, - 0x5f, 0x61, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x65, 0x73, 0x74, - 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x49, 0x6e, 0x74, 0x38, 0x4c, 0x69, 0x73, 0x74, - 0x52, 0x08, 0x49, 0x6e, 0x74, 0x38, 0x41, 0x72, 0x41, 0x72, 0x12, 0x36, 0x0a, 0x0b, 0x69, 0x6e, - 0x74, 0x31, 0x36, 0x5f, 0x61, 0x72, 0x5f, 0x61, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x16, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x49, 0x6e, - 0x74, 0x31, 0x36, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x09, 0x49, 0x6e, 0x74, 0x31, 0x36, 0x41, 0x72, - 0x41, 0x72, 0x12, 0x3b, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x61, 0x72, 0x5f, 0x61, - 0x72, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, - 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x4c, 0x69, 0x73, 0x74, 0x52, 0x09, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x41, 0x72, 0x41, 0x72, 0x12, - 0x4d, 0x0a, 0x11, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x61, - 0x72, 0x5f, 0x61, 0x72, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x73, - 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x46, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, - 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x0e, - 0x49, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x78, 0x65, 0x64, 0x41, 0x72, 0x41, 0x72, 0x12, 0x3b, - 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x61, 0x72, 0x5f, 0x61, 0x72, 0x18, 0x05, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, - 0x53, 0x5f, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, - 0x52, 0x09, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x41, 0x72, 0x41, 0x72, 0x12, 0x4d, 0x0a, 0x11, 0x69, - 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x61, 0x72, 0x5f, 0x61, 0x72, - 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, - 0x45, 0x53, 0x54, 0x53, 0x5f, 0x46, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x49, 0x6e, 0x74, 0x36, - 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x0e, 0x49, 0x6e, 0x74, 0x36, - 0x34, 0x46, 0x69, 0x78, 0x65, 0x64, 0x41, 0x72, 0x41, 0x72, 0x12, 0x37, 0x0a, 0x09, 0x69, 0x6e, - 0x74, 0x5f, 0x61, 0x72, 0x5f, 0x61, 0x72, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, - 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x49, 0x6e, 0x74, 0x36, - 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x07, 0x49, 0x6e, 0x74, 0x41, - 0x72, 0x41, 0x72, 0x12, 0x1c, 0x0a, 0x0a, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x61, 0x72, 0x5f, 0x61, - 0x72, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x08, 0x42, 0x79, 0x74, 0x65, 0x41, 0x72, 0x41, - 0x72, 0x12, 0x1e, 0x0a, 0x0b, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x61, 0x72, 0x5f, 0x61, 0x72, - 0x18, 0x09, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x09, 0x55, 0x69, 0x6e, 0x74, 0x38, 0x41, 0x72, 0x41, - 0x72, 0x12, 0x39, 0x0a, 0x0c, 0x75, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x61, 0x72, 0x5f, 0x61, - 0x72, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, - 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x55, 0x49, 0x6e, 0x74, 0x31, 0x36, 0x4c, 0x69, 0x73, 0x74, - 0x52, 0x0a, 0x55, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x41, 0x72, 0x41, 0x72, 0x12, 0x3e, 0x0a, 0x0c, - 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x61, 0x72, 0x5f, 0x61, 0x72, 0x18, 0x0b, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, - 0x5f, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, - 0x52, 0x0a, 0x55, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x41, 0x72, 0x41, 0x72, 0x12, 0x50, 0x0a, 0x12, - 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x61, 0x72, 0x5f, - 0x61, 0x72, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, - 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x46, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x55, 0x49, - 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x0f, 0x55, - 0x69, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x78, 0x65, 0x64, 0x41, 0x72, 0x41, 0x72, 0x12, 0x3e, - 0x0a, 0x0c, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x61, 0x72, 0x5f, 0x61, 0x72, 0x18, 0x0d, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, - 0x54, 0x53, 0x5f, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, - 0x73, 0x74, 0x52, 0x0a, 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x41, 0x72, 0x41, 0x72, 0x12, 0x50, - 0x0a, 0x12, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x61, - 0x72, 0x5f, 0x61, 0x72, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x74, 0x65, 0x73, - 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x46, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, - 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, - 0x0f, 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x46, 0x69, 0x78, 0x65, 0x64, 0x41, 0x72, 0x41, 0x72, - 0x12, 0x3a, 0x0a, 0x0a, 0x75, 0x69, 0x6e, 0x74, 0x5f, 0x61, 0x72, 0x5f, 0x61, 0x72, 0x18, 0x0f, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, - 0x54, 0x53, 0x5f, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, - 0x73, 0x74, 0x52, 0x08, 0x55, 0x69, 0x6e, 0x74, 0x41, 0x72, 0x41, 0x72, 0x12, 0x38, 0x0a, 0x09, - 0x73, 0x74, 0x72, 0x5f, 0x61, 0x72, 0x5f, 0x61, 0x72, 0x18, 0x10, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x1c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x53, 0x74, - 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x07, 0x53, - 0x74, 0x72, 0x41, 0x72, 0x41, 0x72, 0x12, 0x36, 0x0a, 0x0b, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, - 0x61, 0x72, 0x5f, 0x61, 0x72, 0x18, 0x11, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x74, 0x65, - 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x42, 0x79, 0x74, 0x65, 0x73, 0x4c, - 0x69, 0x73, 0x74, 0x52, 0x09, 0x42, 0x79, 0x74, 0x65, 0x73, 0x41, 0x72, 0x41, 0x72, 0x12, 0x38, - 0x0a, 0x0a, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x61, 0x72, 0x5f, 0x61, 0x72, 0x18, 0x12, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, - 0x5f, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x08, - 0x54, 0x69, 0x6d, 0x65, 0x41, 0x72, 0x41, 0x72, 0x12, 0x3f, 0x0a, 0x0e, 0x64, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x72, 0x5f, 0x61, 0x72, 0x18, 0x13, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x19, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x44, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x0c, 0x44, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x72, 0x41, 0x72, 0x12, 0x3c, 0x0a, 0x0b, 0x65, 0x6d, 0x70, - 0x74, 0x79, 0x5f, 0x61, 0x72, 0x5f, 0x61, 0x72, 0x18, 0x14, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, - 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x45, 0x6d, 0x70, - 0x74, 0x79, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x09, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x41, 0x72, 0x41, 0x72, 0x22, 0xa1, 0x05, 0x0a, 0x0c, 0x53, 0x6c, 0x69, 0x63, - 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x69, 0x6e, 0x74, 0x38, - 0x5f, 0x73, 0x6c, 0x18, 0x01, 0x20, 0x03, 0x28, 0x11, 0x52, 0x06, 0x49, 0x6e, 0x74, 0x38, 0x53, - 0x6c, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x73, 0x6c, 0x18, 0x02, 0x20, - 0x03, 0x28, 0x11, 0x52, 0x07, 0x49, 0x6e, 0x74, 0x31, 0x36, 0x53, 0x6c, 0x12, 0x19, 0x0a, 0x08, - 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x73, 0x6c, 0x18, 0x03, 0x20, 0x03, 0x28, 0x11, 0x52, 0x07, - 0x49, 0x6e, 0x74, 0x33, 0x32, 0x53, 0x6c, 0x12, 0x24, 0x0a, 0x0e, 0x69, 0x6e, 0x74, 0x33, 0x32, - 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x73, 0x6c, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0f, 0x52, - 0x0c, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x78, 0x65, 0x64, 0x53, 0x6c, 0x12, 0x19, 0x0a, - 0x08, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x73, 0x6c, 0x18, 0x05, 0x20, 0x03, 0x28, 0x12, 0x52, - 0x07, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x53, 0x6c, 0x12, 0x24, 0x0a, 0x0e, 0x69, 0x6e, 0x74, 0x36, - 0x34, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x73, 0x6c, 0x18, 0x06, 0x20, 0x03, 0x28, 0x10, - 0x52, 0x0c, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x46, 0x69, 0x78, 0x65, 0x64, 0x53, 0x6c, 0x12, 0x15, - 0x0a, 0x06, 0x69, 0x6e, 0x74, 0x5f, 0x73, 0x6c, 0x18, 0x07, 0x20, 0x03, 0x28, 0x12, 0x52, 0x05, - 0x49, 0x6e, 0x74, 0x53, 0x6c, 0x12, 0x17, 0x0a, 0x07, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x73, 0x6c, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x42, 0x79, 0x74, 0x65, 0x53, 0x6c, 0x12, 0x19, - 0x0a, 0x08, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x73, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x07, 0x55, 0x69, 0x6e, 0x74, 0x38, 0x53, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x75, 0x69, 0x6e, - 0x74, 0x31, 0x36, 0x5f, 0x73, 0x6c, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x08, 0x55, 0x69, - 0x6e, 0x74, 0x31, 0x36, 0x53, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, - 0x5f, 0x73, 0x6c, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x08, 0x55, 0x69, 0x6e, 0x74, 0x33, - 0x32, 0x53, 0x6c, 0x12, 0x26, 0x0a, 0x0f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x66, 0x69, - 0x78, 0x65, 0x64, 0x5f, 0x73, 0x6c, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x07, 0x52, 0x0d, 0x55, 0x69, - 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x78, 0x65, 0x64, 0x53, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x75, - 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x73, 0x6c, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x04, 0x52, 0x08, - 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x53, 0x6c, 0x12, 0x26, 0x0a, 0x0f, 0x75, 0x69, 0x6e, 0x74, - 0x36, 0x34, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x73, 0x6c, 0x18, 0x0e, 0x20, 0x03, 0x28, - 0x06, 0x52, 0x0d, 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x46, 0x69, 0x78, 0x65, 0x64, 0x53, 0x6c, - 0x12, 0x17, 0x0a, 0x07, 0x75, 0x69, 0x6e, 0x74, 0x5f, 0x73, 0x6c, 0x18, 0x0f, 0x20, 0x03, 0x28, - 0x04, 0x52, 0x06, 0x55, 0x69, 0x6e, 0x74, 0x53, 0x6c, 0x12, 0x15, 0x0a, 0x06, 0x73, 0x74, 0x72, - 0x5f, 0x73, 0x6c, 0x18, 0x10, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x53, 0x74, 0x72, 0x53, 0x6c, - 0x12, 0x19, 0x0a, 0x08, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x73, 0x6c, 0x18, 0x11, 0x20, 0x03, - 0x28, 0x0c, 0x52, 0x07, 0x42, 0x79, 0x74, 0x65, 0x73, 0x53, 0x6c, 0x12, 0x33, 0x0a, 0x07, 0x74, - 0x69, 0x6d, 0x65, 0x5f, 0x73, 0x6c, 0x18, 0x12, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, - 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x06, 0x54, 0x69, 0x6d, 0x65, 0x53, 0x6c, - 0x12, 0x3a, 0x0a, 0x0b, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x6c, 0x18, - 0x13, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x0a, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x6c, 0x12, 0x2d, 0x0a, 0x08, - 0x65, 0x6d, 0x70, 0x74, 0x79, 0x5f, 0x73, 0x6c, 0x18, 0x14, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, - 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x53, 0x74, 0x72, 0x75, - 0x63, 0x74, 0x52, 0x07, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x53, 0x6c, 0x22, 0xd6, 0x09, 0x0a, 0x12, - 0x53, 0x6c, 0x69, 0x63, 0x65, 0x73, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, - 0x63, 0x74, 0x12, 0x33, 0x0a, 0x0a, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x73, 0x6c, 0x5f, 0x73, 0x6c, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, - 0x45, 0x53, 0x54, 0x53, 0x5f, 0x49, 0x6e, 0x74, 0x38, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x08, 0x49, - 0x6e, 0x74, 0x38, 0x53, 0x6c, 0x53, 0x6c, 0x12, 0x36, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x31, 0x36, - 0x5f, 0x73, 0x6c, 0x5f, 0x73, 0x6c, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x74, - 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x49, 0x6e, 0x74, 0x31, 0x36, - 0x4c, 0x69, 0x73, 0x74, 0x52, 0x09, 0x49, 0x6e, 0x74, 0x31, 0x36, 0x53, 0x6c, 0x53, 0x6c, 0x12, - 0x3b, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x73, 0x6c, 0x5f, 0x73, 0x6c, 0x18, 0x03, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, - 0x54, 0x53, 0x5f, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, - 0x74, 0x52, 0x09, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x53, 0x6c, 0x53, 0x6c, 0x12, 0x4d, 0x0a, 0x11, - 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x73, 0x6c, 0x5f, 0x73, - 0x6c, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, - 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x46, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x49, 0x6e, 0x74, - 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x0e, 0x49, 0x6e, 0x74, - 0x33, 0x32, 0x46, 0x69, 0x78, 0x65, 0x64, 0x53, 0x6c, 0x53, 0x6c, 0x12, 0x3b, 0x0a, 0x0b, 0x69, - 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x73, 0x6c, 0x5f, 0x73, 0x6c, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x1b, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x49, - 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x09, 0x49, - 0x6e, 0x74, 0x36, 0x34, 0x53, 0x6c, 0x53, 0x6c, 0x12, 0x4d, 0x0a, 0x11, 0x69, 0x6e, 0x74, 0x36, - 0x34, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x73, 0x6c, 0x5f, 0x73, 0x6c, 0x18, 0x06, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, - 0x53, 0x5f, 0x46, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x0e, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x46, 0x69, - 0x78, 0x65, 0x64, 0x53, 0x6c, 0x53, 0x6c, 0x12, 0x37, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x5f, 0x73, - 0x6c, 0x5f, 0x73, 0x6c, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x65, 0x73, - 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x07, 0x49, 0x6e, 0x74, 0x53, 0x6c, 0x53, 0x6c, - 0x12, 0x1c, 0x0a, 0x0a, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x73, 0x6c, 0x5f, 0x73, 0x6c, 0x18, 0x08, - 0x20, 0x03, 0x28, 0x0c, 0x52, 0x08, 0x42, 0x79, 0x74, 0x65, 0x53, 0x6c, 0x53, 0x6c, 0x12, 0x1e, - 0x0a, 0x0b, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x73, 0x6c, 0x5f, 0x73, 0x6c, 0x18, 0x09, 0x20, - 0x03, 0x28, 0x0c, 0x52, 0x09, 0x55, 0x69, 0x6e, 0x74, 0x38, 0x53, 0x6c, 0x53, 0x6c, 0x12, 0x39, - 0x0a, 0x0c, 0x75, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x73, 0x6c, 0x5f, 0x73, 0x6c, 0x18, 0x0a, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, - 0x54, 0x53, 0x5f, 0x55, 0x49, 0x6e, 0x74, 0x31, 0x36, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x0a, 0x55, - 0x69, 0x6e, 0x74, 0x31, 0x36, 0x53, 0x6c, 0x53, 0x6c, 0x12, 0x3e, 0x0a, 0x0c, 0x75, 0x69, 0x6e, - 0x74, 0x33, 0x32, 0x5f, 0x73, 0x6c, 0x5f, 0x73, 0x6c, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x1c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x55, 0x49, - 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x0a, 0x55, - 0x69, 0x6e, 0x74, 0x33, 0x32, 0x53, 0x6c, 0x53, 0x6c, 0x12, 0x50, 0x0a, 0x12, 0x75, 0x69, 0x6e, - 0x74, 0x33, 0x32, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x73, 0x6c, 0x5f, 0x73, 0x6c, 0x18, - 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, - 0x53, 0x54, 0x53, 0x5f, 0x46, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x55, 0x49, 0x6e, 0x74, 0x33, - 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x0f, 0x55, 0x69, 0x6e, 0x74, - 0x33, 0x32, 0x46, 0x69, 0x78, 0x65, 0x64, 0x53, 0x6c, 0x53, 0x6c, 0x12, 0x3e, 0x0a, 0x0c, 0x75, - 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x73, 0x6c, 0x5f, 0x73, 0x6c, 0x18, 0x0d, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, - 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, - 0x0a, 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x53, 0x6c, 0x53, 0x6c, 0x12, 0x50, 0x0a, 0x12, 0x75, - 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x73, 0x6c, 0x5f, 0x73, - 0x6c, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, - 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x46, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x55, 0x49, 0x6e, - 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x0f, 0x55, 0x69, - 0x6e, 0x74, 0x36, 0x34, 0x46, 0x69, 0x78, 0x65, 0x64, 0x53, 0x6c, 0x53, 0x6c, 0x12, 0x3a, 0x0a, - 0x0a, 0x75, 0x69, 0x6e, 0x74, 0x5f, 0x73, 0x6c, 0x5f, 0x73, 0x6c, 0x18, 0x0f, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, - 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, - 0x08, 0x55, 0x69, 0x6e, 0x74, 0x53, 0x6c, 0x53, 0x6c, 0x12, 0x38, 0x0a, 0x09, 0x73, 0x74, 0x72, - 0x5f, 0x73, 0x6c, 0x5f, 0x73, 0x6c, 0x18, 0x10, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, - 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x53, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x07, 0x53, 0x74, 0x72, 0x53, - 0x6c, 0x53, 0x6c, 0x12, 0x36, 0x0a, 0x0b, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x73, 0x6c, 0x5f, - 0x73, 0x6c, 0x18, 0x11, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, - 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x42, 0x79, 0x74, 0x65, 0x73, 0x4c, 0x69, 0x73, 0x74, - 0x52, 0x09, 0x42, 0x79, 0x74, 0x65, 0x73, 0x53, 0x6c, 0x53, 0x6c, 0x12, 0x38, 0x0a, 0x0a, 0x74, - 0x69, 0x6d, 0x65, 0x5f, 0x73, 0x6c, 0x5f, 0x73, 0x6c, 0x18, 0x12, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x1a, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x54, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x08, 0x54, 0x69, 0x6d, - 0x65, 0x53, 0x6c, 0x53, 0x6c, 0x12, 0x3f, 0x0a, 0x0e, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x73, 0x6c, 0x5f, 0x73, 0x6c, 0x18, 0x13, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, - 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x44, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x0c, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x53, 0x6c, 0x53, 0x6c, 0x12, 0x3c, 0x0a, 0x0b, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x5f, - 0x73, 0x6c, 0x5f, 0x73, 0x6c, 0x18, 0x14, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x65, - 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x53, - 0x74, 0x72, 0x75, 0x63, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x09, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x53, 0x6c, 0x53, 0x6c, 0x22, 0xa3, 0x05, 0x0a, 0x0e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x69, 0x6e, 0x74, 0x38, 0x5f, - 0x70, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x11, 0x52, 0x06, 0x49, 0x6e, 0x74, 0x38, 0x50, 0x74, - 0x12, 0x19, 0x0a, 0x08, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x70, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x11, 0x52, 0x07, 0x49, 0x6e, 0x74, 0x31, 0x36, 0x50, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x69, - 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x70, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x11, 0x52, 0x07, 0x49, - 0x6e, 0x74, 0x33, 0x32, 0x50, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, - 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x70, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0f, 0x52, 0x0c, - 0x49, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x78, 0x65, 0x64, 0x50, 0x74, 0x12, 0x19, 0x0a, 0x08, - 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x70, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x12, 0x52, 0x07, - 0x49, 0x6e, 0x74, 0x36, 0x34, 0x50, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x69, 0x6e, 0x74, 0x36, 0x34, - 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x70, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x10, 0x52, - 0x0c, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x46, 0x69, 0x78, 0x65, 0x64, 0x50, 0x74, 0x12, 0x15, 0x0a, - 0x06, 0x69, 0x6e, 0x74, 0x5f, 0x70, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x12, 0x52, 0x05, 0x49, - 0x6e, 0x74, 0x50, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x70, 0x74, 0x18, - 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x42, 0x79, 0x74, 0x65, 0x50, 0x74, 0x12, 0x19, 0x0a, - 0x08, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x70, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0d, 0x52, - 0x07, 0x55, 0x69, 0x6e, 0x74, 0x38, 0x50, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, - 0x31, 0x36, 0x5f, 0x70, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x55, 0x69, 0x6e, - 0x74, 0x31, 0x36, 0x50, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, - 0x70, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x55, 0x69, 0x6e, 0x74, 0x33, 0x32, - 0x50, 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x66, 0x69, 0x78, - 0x65, 0x64, 0x5f, 0x70, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x07, 0x52, 0x0d, 0x55, 0x69, 0x6e, - 0x74, 0x33, 0x32, 0x46, 0x69, 0x78, 0x65, 0x64, 0x50, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x75, 0x69, - 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x70, 0x74, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x55, - 0x69, 0x6e, 0x74, 0x36, 0x34, 0x50, 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x75, 0x69, 0x6e, 0x74, 0x36, - 0x34, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x70, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x06, - 0x52, 0x0d, 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x46, 0x69, 0x78, 0x65, 0x64, 0x50, 0x74, 0x12, - 0x17, 0x0a, 0x07, 0x75, 0x69, 0x6e, 0x74, 0x5f, 0x70, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x06, 0x55, 0x69, 0x6e, 0x74, 0x50, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x73, 0x74, 0x72, 0x5f, - 0x70, 0x74, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x53, 0x74, 0x72, 0x50, 0x74, 0x12, - 0x19, 0x0a, 0x08, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x70, 0x74, 0x18, 0x11, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x07, 0x42, 0x79, 0x74, 0x65, 0x73, 0x50, 0x74, 0x12, 0x33, 0x0a, 0x07, 0x74, 0x69, - 0x6d, 0x65, 0x5f, 0x70, 0x74, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x06, 0x54, 0x69, 0x6d, 0x65, 0x50, 0x74, 0x12, - 0x3a, 0x0a, 0x0b, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x74, 0x18, 0x13, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x0a, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x74, 0x12, 0x2d, 0x0a, 0x08, 0x65, - 0x6d, 0x70, 0x74, 0x79, 0x5f, 0x70, 0x74, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, - 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x53, 0x74, 0x72, 0x75, 0x63, - 0x74, 0x52, 0x07, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x50, 0x74, 0x22, 0x8c, 0x06, 0x0a, 0x13, 0x50, - 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, - 0x63, 0x74, 0x12, 0x1c, 0x0a, 0x0a, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x70, 0x74, 0x5f, 0x73, 0x6c, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x11, 0x52, 0x08, 0x49, 0x6e, 0x74, 0x38, 0x50, 0x74, 0x53, 0x6c, - 0x12, 0x1e, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x70, 0x74, 0x5f, 0x73, 0x6c, 0x18, - 0x02, 0x20, 0x03, 0x28, 0x11, 0x52, 0x09, 0x49, 0x6e, 0x74, 0x31, 0x36, 0x50, 0x74, 0x53, 0x6c, - 0x12, 0x1e, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x70, 0x74, 0x5f, 0x73, 0x6c, 0x18, - 0x03, 0x20, 0x03, 0x28, 0x11, 0x52, 0x09, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x50, 0x74, 0x53, 0x6c, - 0x12, 0x29, 0x0a, 0x11, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, - 0x70, 0x74, 0x5f, 0x73, 0x6c, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0f, 0x52, 0x0e, 0x49, 0x6e, 0x74, - 0x33, 0x32, 0x46, 0x69, 0x78, 0x65, 0x64, 0x50, 0x74, 0x53, 0x6c, 0x12, 0x1e, 0x0a, 0x0b, 0x69, - 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x70, 0x74, 0x5f, 0x73, 0x6c, 0x18, 0x05, 0x20, 0x03, 0x28, 0x12, - 0x52, 0x09, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x50, 0x74, 0x53, 0x6c, 0x12, 0x29, 0x0a, 0x11, 0x69, - 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x70, 0x74, 0x5f, 0x73, 0x6c, - 0x18, 0x06, 0x20, 0x03, 0x28, 0x10, 0x52, 0x0e, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x46, 0x69, 0x78, - 0x65, 0x64, 0x50, 0x74, 0x53, 0x6c, 0x12, 0x1a, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x5f, 0x70, 0x74, - 0x5f, 0x73, 0x6c, 0x18, 0x07, 0x20, 0x03, 0x28, 0x12, 0x52, 0x07, 0x49, 0x6e, 0x74, 0x50, 0x74, - 0x53, 0x6c, 0x12, 0x1c, 0x0a, 0x0a, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x70, 0x74, 0x5f, 0x73, 0x6c, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x42, 0x79, 0x74, 0x65, 0x50, 0x74, 0x53, 0x6c, - 0x12, 0x1e, 0x0a, 0x0b, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x70, 0x74, 0x5f, 0x73, 0x6c, 0x18, - 0x09, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x55, 0x69, 0x6e, 0x74, 0x38, 0x50, 0x74, 0x53, 0x6c, - 0x12, 0x20, 0x0a, 0x0c, 0x75, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x70, 0x74, 0x5f, 0x73, 0x6c, - 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x0a, 0x55, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x50, 0x74, - 0x53, 0x6c, 0x12, 0x20, 0x0a, 0x0c, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x70, 0x74, 0x5f, - 0x73, 0x6c, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x0a, 0x55, 0x69, 0x6e, 0x74, 0x33, 0x32, - 0x50, 0x74, 0x53, 0x6c, 0x12, 0x2b, 0x0a, 0x12, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x66, - 0x69, 0x78, 0x65, 0x64, 0x5f, 0x70, 0x74, 0x5f, 0x73, 0x6c, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x07, - 0x52, 0x0f, 0x55, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x78, 0x65, 0x64, 0x50, 0x74, 0x53, - 0x6c, 0x12, 0x20, 0x0a, 0x0c, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x70, 0x74, 0x5f, 0x73, - 0x6c, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x04, 0x52, 0x0a, 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x50, - 0x74, 0x53, 0x6c, 0x12, 0x2b, 0x0a, 0x12, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x66, 0x69, - 0x78, 0x65, 0x64, 0x5f, 0x70, 0x74, 0x5f, 0x73, 0x6c, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x06, 0x52, - 0x0f, 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x46, 0x69, 0x78, 0x65, 0x64, 0x50, 0x74, 0x53, 0x6c, - 0x12, 0x1c, 0x0a, 0x0a, 0x75, 0x69, 0x6e, 0x74, 0x5f, 0x70, 0x74, 0x5f, 0x73, 0x6c, 0x18, 0x0f, - 0x20, 0x03, 0x28, 0x04, 0x52, 0x08, 0x55, 0x69, 0x6e, 0x74, 0x50, 0x74, 0x53, 0x6c, 0x12, 0x1a, - 0x0a, 0x09, 0x73, 0x74, 0x72, 0x5f, 0x70, 0x74, 0x5f, 0x73, 0x6c, 0x18, 0x10, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x07, 0x53, 0x74, 0x72, 0x50, 0x74, 0x53, 0x6c, 0x12, 0x1e, 0x0a, 0x0b, 0x62, 0x79, - 0x74, 0x65, 0x73, 0x5f, 0x70, 0x74, 0x5f, 0x73, 0x6c, 0x18, 0x11, 0x20, 0x03, 0x28, 0x0c, 0x52, - 0x09, 0x42, 0x79, 0x74, 0x65, 0x73, 0x50, 0x74, 0x53, 0x6c, 0x12, 0x38, 0x0a, 0x0a, 0x74, 0x69, - 0x6d, 0x65, 0x5f, 0x70, 0x74, 0x5f, 0x73, 0x6c, 0x18, 0x12, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x54, 0x69, 0x6d, 0x65, - 0x50, 0x74, 0x53, 0x6c, 0x12, 0x3f, 0x0a, 0x0e, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x5f, 0x70, 0x74, 0x5f, 0x73, 0x6c, 0x18, 0x13, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x50, 0x74, 0x53, 0x6c, 0x12, 0x32, 0x0a, 0x0b, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x5f, 0x70, - 0x74, 0x5f, 0x73, 0x6c, 0x18, 0x14, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x74, 0x65, 0x73, - 0x74, 0x73, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x09, - 0x45, 0x6d, 0x70, 0x74, 0x79, 0x50, 0x74, 0x53, 0x6c, 0x22, 0xd1, 0x01, 0x0a, 0x09, 0x43, 0x6f, - 0x6d, 0x70, 0x6c, 0x65, 0x78, 0x53, 0x74, 0x12, 0x32, 0x0a, 0x08, 0x70, 0x72, 0x5f, 0x66, 0x69, - 0x65, 0x6c, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x65, 0x73, 0x74, - 0x73, 0x2e, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, - 0x63, 0x74, 0x52, 0x07, 0x50, 0x72, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x2e, 0x0a, 0x08, 0x61, - 0x72, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, - 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x41, 0x72, 0x72, 0x61, 0x79, 0x73, 0x53, 0x74, 0x72, 0x75, - 0x63, 0x74, 0x52, 0x07, 0x41, 0x72, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x2e, 0x0a, 0x08, 0x73, - 0x6c, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, - 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, - 0x63, 0x74, 0x52, 0x07, 0x53, 0x6c, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x30, 0x0a, 0x08, 0x70, - 0x74, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, - 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x53, 0x74, - 0x72, 0x75, 0x63, 0x74, 0x52, 0x07, 0x50, 0x74, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x22, 0x53, 0x0a, - 0x0b, 0x45, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x53, 0x74, 0x31, 0x12, 0x44, 0x0a, 0x11, - 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, - 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, - 0x52, 0x10, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, - 0x63, 0x74, 0x22, 0x87, 0x02, 0x0a, 0x0b, 0x45, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x53, - 0x74, 0x32, 0x12, 0x44, 0x0a, 0x11, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, - 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, - 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, - 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x10, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, - 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x12, 0x38, 0x0a, 0x0d, 0x61, 0x72, 0x72, 0x61, - 0x79, 0x73, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x13, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x41, 0x72, 0x72, 0x61, 0x79, 0x73, 0x53, 0x74, - 0x72, 0x75, 0x63, 0x74, 0x52, 0x0c, 0x41, 0x72, 0x72, 0x61, 0x79, 0x73, 0x53, 0x74, 0x72, 0x75, - 0x63, 0x74, 0x12, 0x38, 0x0a, 0x0d, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x73, 0x5f, 0x73, 0x74, 0x72, - 0x75, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x65, 0x73, 0x74, - 0x73, 0x2e, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x0c, - 0x53, 0x6c, 0x69, 0x63, 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x12, 0x3e, 0x0a, 0x0f, - 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x50, 0x6f, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x0e, 0x50, 0x6f, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x22, 0xbe, 0x02, 0x0a, - 0x0b, 0x45, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x53, 0x74, 0x33, 0x12, 0x44, 0x0a, 0x11, - 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, - 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, - 0x52, 0x10, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, - 0x63, 0x74, 0x12, 0x38, 0x0a, 0x0d, 0x61, 0x72, 0x72, 0x61, 0x79, 0x73, 0x5f, 0x73, 0x74, 0x72, - 0x75, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x65, 0x73, 0x74, - 0x73, 0x2e, 0x41, 0x72, 0x72, 0x61, 0x79, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x0c, - 0x41, 0x72, 0x72, 0x61, 0x79, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x12, 0x38, 0x0a, 0x0d, - 0x73, 0x6c, 0x69, 0x63, 0x65, 0x73, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x53, 0x6c, 0x69, 0x63, - 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x0c, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x73, - 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x12, 0x3e, 0x0a, 0x0f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x73, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x15, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x73, - 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x0e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x73, - 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x12, 0x35, 0x0a, 0x0c, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x5f, - 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x74, - 0x65, 0x73, 0x74, 0x73, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, - 0x52, 0x0b, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x22, 0x81, 0x03, - 0x0a, 0x0b, 0x45, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x53, 0x74, 0x34, 0x12, 0x12, 0x0a, - 0x04, 0x66, 0x6f, 0x6f, 0x31, 0x18, 0x01, 0x20, 0x01, 0x28, 0x12, 0x52, 0x04, 0x46, 0x6f, 0x6f, - 0x31, 0x12, 0x44, 0x0a, 0x11, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x5f, - 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, - 0x65, 0x73, 0x74, 0x73, 0x2e, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x53, - 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x10, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, - 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x6f, 0x6f, 0x32, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x46, 0x6f, 0x6f, 0x32, 0x12, 0x43, 0x0a, 0x13, 0x61, - 0x72, 0x72, 0x61, 0x79, 0x73, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x5f, 0x66, 0x69, 0x65, - 0x6c, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, - 0x2e, 0x41, 0x72, 0x72, 0x61, 0x79, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x11, 0x41, - 0x72, 0x72, 0x61, 0x79, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x46, 0x69, 0x65, 0x6c, 0x64, - 0x12, 0x12, 0x0a, 0x04, 0x66, 0x6f, 0x6f, 0x33, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, - 0x46, 0x6f, 0x6f, 0x33, 0x12, 0x38, 0x0a, 0x0d, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x73, 0x5f, 0x73, - 0x74, 0x72, 0x75, 0x63, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x65, - 0x73, 0x74, 0x73, 0x2e, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, - 0x52, 0x0c, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x12, 0x12, - 0x0a, 0x04, 0x66, 0x6f, 0x6f, 0x34, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x46, 0x6f, - 0x6f, 0x34, 0x12, 0x49, 0x0a, 0x15, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x5f, 0x73, - 0x74, 0x72, 0x75, 0x63, 0x74, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x13, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x12, 0x0a, - 0x04, 0x66, 0x6f, 0x6f, 0x35, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x46, 0x6f, 0x6f, - 0x35, 0x22, 0x8d, 0x03, 0x0a, 0x17, 0x45, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x53, 0x74, - 0x35, 0x4e, 0x61, 0x6d, 0x65, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x12, 0x0a, - 0x04, 0x66, 0x6f, 0x6f, 0x31, 0x18, 0x01, 0x20, 0x01, 0x28, 0x12, 0x52, 0x04, 0x46, 0x6f, 0x6f, - 0x31, 0x12, 0x44, 0x0a, 0x11, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x5f, - 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, - 0x65, 0x73, 0x74, 0x73, 0x2e, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x53, - 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x10, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, - 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x6f, 0x6f, 0x32, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x46, 0x6f, 0x6f, 0x32, 0x12, 0x43, 0x0a, 0x13, 0x61, - 0x72, 0x72, 0x61, 0x79, 0x73, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x5f, 0x66, 0x69, 0x65, - 0x6c, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, - 0x2e, 0x41, 0x72, 0x72, 0x61, 0x79, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x11, 0x41, - 0x72, 0x72, 0x61, 0x79, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x46, 0x69, 0x65, 0x6c, 0x64, - 0x12, 0x12, 0x0a, 0x04, 0x66, 0x6f, 0x6f, 0x33, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, - 0x46, 0x6f, 0x6f, 0x33, 0x12, 0x38, 0x0a, 0x0d, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x73, 0x5f, 0x73, - 0x74, 0x72, 0x75, 0x63, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x65, - 0x73, 0x74, 0x73, 0x2e, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, - 0x52, 0x0c, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x12, 0x12, - 0x0a, 0x04, 0x66, 0x6f, 0x6f, 0x34, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x46, 0x6f, - 0x6f, 0x34, 0x12, 0x49, 0x0a, 0x15, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x5f, 0x73, - 0x74, 0x72, 0x75, 0x63, 0x74, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x13, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x12, 0x0a, - 0x04, 0x66, 0x6f, 0x6f, 0x35, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x46, 0x6f, 0x6f, - 0x35, 0x22, 0x33, 0x0a, 0x15, 0x41, 0x6d, 0x69, 0x6e, 0x6f, 0x4d, 0x61, 0x72, 0x73, 0x68, 0x61, - 0x6c, 0x65, 0x72, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x31, 0x12, 0x0c, 0x0a, 0x01, 0x63, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x12, 0x52, 0x01, 0x43, 0x12, 0x0c, 0x0a, 0x01, 0x64, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x12, 0x52, 0x01, 0x44, 0x22, 0x29, 0x0a, 0x0b, 0x52, 0x65, 0x70, 0x72, 0x53, 0x74, - 0x72, 0x75, 0x63, 0x74, 0x31, 0x12, 0x0c, 0x0a, 0x01, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x12, - 0x52, 0x01, 0x43, 0x12, 0x0c, 0x0a, 0x01, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x12, 0x52, 0x01, - 0x44, 0x22, 0x3f, 0x0a, 0x15, 0x41, 0x6d, 0x69, 0x6e, 0x6f, 0x4d, 0x61, 0x72, 0x73, 0x68, 0x61, - 0x6c, 0x65, 0x72, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x32, 0x12, 0x26, 0x0a, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x74, 0x65, 0x73, 0x74, - 0x73, 0x2e, 0x52, 0x65, 0x70, 0x72, 0x45, 0x6c, 0x65, 0x6d, 0x32, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x22, 0x49, 0x0a, 0x09, 0x52, 0x65, 0x70, 0x72, 0x45, 0x6c, 0x65, 0x6d, 0x32, 0x12, - 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x4b, 0x65, - 0x79, 0x12, 0x2a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x2d, 0x0a, - 0x15, 0x41, 0x6d, 0x69, 0x6e, 0x6f, 0x4d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c, 0x65, 0x72, 0x53, - 0x74, 0x72, 0x75, 0x63, 0x74, 0x33, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x11, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x22, 0x0a, 0x12, - 0x41, 0x6d, 0x69, 0x6e, 0x6f, 0x4d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c, 0x65, 0x72, 0x49, 0x6e, - 0x74, 0x34, 0x12, 0x0c, 0x0a, 0x01, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x11, 0x52, 0x01, 0x41, - 0x22, 0x2a, 0x0a, 0x12, 0x41, 0x6d, 0x69, 0x6e, 0x6f, 0x4d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c, - 0x65, 0x72, 0x49, 0x6e, 0x74, 0x35, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x4b, 0x0a, 0x15, - 0x41, 0x6d, 0x69, 0x6e, 0x6f, 0x4d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c, 0x65, 0x72, 0x53, 0x74, - 0x72, 0x75, 0x63, 0x74, 0x36, 0x12, 0x32, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x41, 0x6d, 0x69, - 0x6e, 0x6f, 0x4d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x72, 0x75, 0x63, - 0x74, 0x31, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x2d, 0x0a, 0x15, 0x41, 0x6d, 0x69, - 0x6e, 0x6f, 0x4d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x72, 0x75, 0x63, - 0x74, 0x37, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x21, 0x0a, 0x09, 0x52, 0x65, 0x70, 0x72, - 0x45, 0x6c, 0x65, 0x6d, 0x37, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x1e, 0x0a, 0x06, 0x49, - 0x6e, 0x74, 0x44, 0x65, 0x66, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x12, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x1d, 0x0a, 0x05, 0x49, - 0x6e, 0x74, 0x41, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x12, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x1d, 0x0a, 0x05, 0x49, 0x6e, - 0x74, 0x53, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x12, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x1e, 0x0a, 0x06, 0x42, 0x79, 0x74, - 0x65, 0x41, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x1e, 0x0a, 0x06, 0x42, 0x79, 0x74, - 0x65, 0x53, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xc4, 0x04, 0x0a, 0x13, 0x50, 0x72, - 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x44, 0x65, - 0x66, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x6e, 0x74, 0x38, 0x18, 0x01, 0x20, 0x01, 0x28, 0x11, 0x52, - 0x04, 0x49, 0x6e, 0x74, 0x38, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x11, 0x52, 0x05, 0x49, 0x6e, 0x74, 0x31, 0x36, 0x12, 0x14, 0x0a, 0x05, 0x69, - 0x6e, 0x74, 0x33, 0x32, 0x18, 0x03, 0x20, 0x01, 0x28, 0x11, 0x52, 0x05, 0x49, 0x6e, 0x74, 0x33, - 0x32, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0f, 0x52, 0x0a, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x78, - 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x12, 0x52, 0x05, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x36, - 0x34, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x10, 0x52, 0x0a, 0x49, - 0x6e, 0x74, 0x36, 0x34, 0x46, 0x69, 0x78, 0x65, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x6e, 0x74, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x12, 0x52, 0x03, 0x49, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x62, - 0x79, 0x74, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x42, 0x79, 0x74, 0x65, 0x12, - 0x14, 0x0a, 0x05, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, - 0x55, 0x69, 0x6e, 0x74, 0x38, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x18, - 0x0a, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x55, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x12, 0x16, 0x0a, - 0x06, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x55, - 0x69, 0x6e, 0x74, 0x33, 0x32, 0x12, 0x21, 0x0a, 0x0c, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, - 0x66, 0x69, 0x78, 0x65, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x07, 0x52, 0x0b, 0x55, 0x69, 0x6e, - 0x74, 0x33, 0x32, 0x46, 0x69, 0x78, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x69, 0x6e, 0x74, - 0x36, 0x34, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, - 0x12, 0x21, 0x0a, 0x0c, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, - 0x18, 0x0e, 0x20, 0x01, 0x28, 0x06, 0x52, 0x0b, 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x46, 0x69, - 0x78, 0x65, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x69, 0x6e, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x04, 0x55, 0x69, 0x6e, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x74, 0x72, 0x18, 0x10, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x53, 0x74, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x79, 0x74, - 0x65, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, - 0x2e, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x54, 0x69, 0x6d, 0x65, 0x12, - 0x35, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x13, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x44, 0x75, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x05, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x18, - 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x05, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x22, 0x43, 0x0a, 0x12, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x53, 0x74, - 0x72, 0x75, 0x63, 0x74, 0x53, 0x6c, 0x12, 0x2d, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x50, 0x72, - 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x43, 0x0a, 0x12, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, - 0x76, 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x41, 0x72, 0x12, 0x2d, 0x0a, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x65, 0x73, - 0x74, 0x73, 0x2e, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x53, 0x74, 0x72, - 0x75, 0x63, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x0b, 0x0a, 0x09, 0x43, 0x6f, - 0x6e, 0x63, 0x72, 0x65, 0x74, 0x65, 0x31, 0x22, 0x0b, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x63, 0x72, - 0x65, 0x74, 0x65, 0x32, 0x22, 0x27, 0x0a, 0x0f, 0x43, 0x6f, 0x6e, 0x63, 0x72, 0x65, 0x74, 0x65, - 0x54, 0x79, 0x70, 0x65, 0x44, 0x65, 0x66, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x2c, 0x0a, - 0x14, 0x43, 0x6f, 0x6e, 0x63, 0x72, 0x65, 0x74, 0x65, 0x57, 0x72, 0x61, 0x70, 0x70, 0x65, 0x64, - 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xaf, 0x01, 0x0a, 0x15, - 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x53, - 0x74, 0x72, 0x75, 0x63, 0x74, 0x12, 0x24, 0x0a, 0x02, 0x66, 0x31, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x02, 0x46, 0x31, 0x12, 0x24, 0x0a, 0x02, 0x66, - 0x32, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x02, 0x46, - 0x32, 0x12, 0x24, 0x0a, 0x02, 0x66, 0x33, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x41, 0x6e, 0x79, 0x52, 0x02, 0x46, 0x33, 0x12, 0x24, 0x0a, 0x02, 0x66, 0x34, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x02, 0x46, 0x34, 0x22, 0x27, 0x0a, - 0x0f, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x42, 0x79, 0x74, 0x65, 0x73, 0x4c, 0x69, 0x73, 0x74, - 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, - 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x43, 0x0a, 0x13, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, - 0x42, 0x79, 0x74, 0x65, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2c, 0x0a, - 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x74, - 0x65, 0x73, 0x74, 0x73, 0x2e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x42, 0x79, 0x74, 0x65, 0x73, - 0x4c, 0x69, 0x73, 0x74, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x45, 0x0a, 0x12, 0x54, - 0x45, 0x53, 0x54, 0x53, 0x5f, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x73, - 0x74, 0x12, 0x2f, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x22, 0x41, 0x0a, 0x15, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x28, 0x0a, 0x05, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x74, 0x65, 0x73, - 0x74, 0x73, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x05, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x33, 0x0a, 0x1b, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x46, - 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x4c, 0x69, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0f, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x34, 0x0a, 0x1c, 0x54, 0x45, - 0x53, 0x54, 0x53, 0x5f, 0x46, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x55, 0x49, 0x6e, 0x74, 0x33, - 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x07, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x22, 0x33, 0x0a, 0x1b, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x46, 0x69, 0x78, 0x65, 0x64, 0x36, - 0x34, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, - 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x10, 0x52, 0x05, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x34, 0x0a, 0x1c, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x46, - 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x06, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x27, 0x0a, 0x0f, 0x54, - 0x45, 0x53, 0x54, 0x53, 0x5f, 0x49, 0x6e, 0x74, 0x31, 0x36, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x14, - 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x11, 0x52, 0x05, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x22, 0x2c, 0x0a, 0x14, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x49, 0x6e, - 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x11, 0x52, 0x05, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x22, 0x2c, 0x0a, 0x14, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x49, 0x6e, 0x74, 0x36, - 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x12, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x22, 0x26, 0x0a, 0x0e, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x49, 0x6e, 0x74, 0x38, 0x4c, 0x69, - 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x11, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x2d, 0x0a, 0x15, 0x54, 0x45, 0x53, 0x54, - 0x53, 0x5f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, 0x73, - 0x74, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x47, 0x0a, 0x13, 0x54, 0x45, 0x53, 0x54, 0x53, - 0x5f, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x30, - 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x22, 0x28, 0x0a, 0x10, 0x54, 0x45, 0x53, 0x54, 0x53, 0x5f, 0x55, 0x49, 0x6e, 0x74, 0x31, 0x36, - 0x4c, 0x69, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0d, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x2d, 0x0a, 0x15, 0x54, 0x45, - 0x53, 0x54, 0x53, 0x5f, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, - 0x69, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0d, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x2d, 0x0a, 0x15, 0x54, 0x45, 0x53, - 0x54, 0x53, 0x5f, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x69, - 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x04, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x2f, 0x5a, 0x2d, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6e, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2f, 0x67, - 0x6e, 0x6f, 0x2f, 0x74, 0x6d, 0x32, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x6d, 0x69, 0x6e, 0x6f, - 0x2f, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, -} - -var ( - file_tests_proto_rawDescOnce sync.Once - file_tests_proto_rawDescData = file_tests_proto_rawDesc -) - -func file_tests_proto_rawDescGZIP() []byte { - file_tests_proto_rawDescOnce.Do(func() { - file_tests_proto_rawDescData = protoimpl.X.CompressGZIP(file_tests_proto_rawDescData) - }) - return file_tests_proto_rawDescData -} - -var file_tests_proto_msgTypes = make([]protoimpl.MessageInfo, 55) -var file_tests_proto_goTypes = []interface{}{ - (*EmptyStruct)(nil), // 0: tests.EmptyStruct - (*PrimitivesStruct)(nil), // 1: tests.PrimitivesStruct - (*ShortArraysStruct)(nil), // 2: tests.ShortArraysStruct - (*ArraysStruct)(nil), // 3: tests.ArraysStruct - (*ArraysArraysStruct)(nil), // 4: tests.ArraysArraysStruct - (*SlicesStruct)(nil), // 5: tests.SlicesStruct - (*SlicesSlicesStruct)(nil), // 6: tests.SlicesSlicesStruct - (*PointersStruct)(nil), // 7: tests.PointersStruct - (*PointerSlicesStruct)(nil), // 8: tests.PointerSlicesStruct - (*ComplexSt)(nil), // 9: tests.ComplexSt - (*EmbeddedSt1)(nil), // 10: tests.EmbeddedSt1 - (*EmbeddedSt2)(nil), // 11: tests.EmbeddedSt2 - (*EmbeddedSt3)(nil), // 12: tests.EmbeddedSt3 - (*EmbeddedSt4)(nil), // 13: tests.EmbeddedSt4 - (*EmbeddedSt5NameOverride)(nil), // 14: tests.EmbeddedSt5NameOverride - (*AminoMarshalerStruct1)(nil), // 15: tests.AminoMarshalerStruct1 - (*ReprStruct1)(nil), // 16: tests.ReprStruct1 - (*AminoMarshalerStruct2)(nil), // 17: tests.AminoMarshalerStruct2 - (*ReprElem2)(nil), // 18: tests.ReprElem2 - (*AminoMarshalerStruct3)(nil), // 19: tests.AminoMarshalerStruct3 - (*AminoMarshalerInt4)(nil), // 20: tests.AminoMarshalerInt4 - (*AminoMarshalerInt5)(nil), // 21: tests.AminoMarshalerInt5 - (*AminoMarshalerStruct6)(nil), // 22: tests.AminoMarshalerStruct6 - (*AminoMarshalerStruct7)(nil), // 23: tests.AminoMarshalerStruct7 - (*ReprElem7)(nil), // 24: tests.ReprElem7 - (*IntDef)(nil), // 25: tests.IntDef - (*IntAr)(nil), // 26: tests.IntAr - (*IntSl)(nil), // 27: tests.IntSl - (*ByteAr)(nil), // 28: tests.ByteAr - (*ByteSl)(nil), // 29: tests.ByteSl - (*PrimitivesStructDef)(nil), // 30: tests.PrimitivesStructDef - (*PrimitivesStructSl)(nil), // 31: tests.PrimitivesStructSl - (*PrimitivesStructAr)(nil), // 32: tests.PrimitivesStructAr - (*Concrete1)(nil), // 33: tests.Concrete1 - (*Concrete2)(nil), // 34: tests.Concrete2 - (*ConcreteTypeDef)(nil), // 35: tests.ConcreteTypeDef - (*ConcreteWrappedBytes)(nil), // 36: tests.ConcreteWrappedBytes - (*InterfaceFieldsStruct)(nil), // 37: tests.InterfaceFieldsStruct - (*TESTS_BytesList)(nil), // 38: tests.TESTS_BytesList - (*TESTS_BytesListList)(nil), // 39: tests.TESTS_BytesListList - (*TESTS_DurationList)(nil), // 40: tests.TESTS_DurationList - (*TESTS_EmptyStructList)(nil), // 41: tests.TESTS_EmptyStructList - (*TESTS_Fixed32Int32ValueList)(nil), // 42: tests.TESTS_Fixed32Int32ValueList - (*TESTS_Fixed32UInt32ValueList)(nil), // 43: tests.TESTS_Fixed32UInt32ValueList - (*TESTS_Fixed64Int64ValueList)(nil), // 44: tests.TESTS_Fixed64Int64ValueList - (*TESTS_Fixed64UInt64ValueList)(nil), // 45: tests.TESTS_Fixed64UInt64ValueList - (*TESTS_Int16List)(nil), // 46: tests.TESTS_Int16List - (*TESTS_Int32ValueList)(nil), // 47: tests.TESTS_Int32ValueList - (*TESTS_Int64ValueList)(nil), // 48: tests.TESTS_Int64ValueList - (*TESTS_Int8List)(nil), // 49: tests.TESTS_Int8List - (*TESTS_StringValueList)(nil), // 50: tests.TESTS_StringValueList - (*TESTS_TimestampList)(nil), // 51: tests.TESTS_TimestampList - (*TESTS_UInt16List)(nil), // 52: tests.TESTS_UInt16List - (*TESTS_UInt32ValueList)(nil), // 53: tests.TESTS_UInt32ValueList - (*TESTS_UInt64ValueList)(nil), // 54: tests.TESTS_UInt64ValueList - (*timestamppb.Timestamp)(nil), // 55: google.protobuf.Timestamp - (*durationpb.Duration)(nil), // 56: google.protobuf.Duration - (*anypb.Any)(nil), // 57: google.protobuf.Any -} -var file_tests_proto_depIdxs = []int32{ - 55, // 0: tests.PrimitivesStruct.time:type_name -> google.protobuf.Timestamp - 56, // 1: tests.PrimitivesStruct.duration:type_name -> google.protobuf.Duration - 0, // 2: tests.PrimitivesStruct.empty:type_name -> tests.EmptyStruct - 55, // 3: tests.ShortArraysStruct.time_ar:type_name -> google.protobuf.Timestamp - 56, // 4: tests.ShortArraysStruct.duration_ar:type_name -> google.protobuf.Duration - 55, // 5: tests.ArraysStruct.time_ar:type_name -> google.protobuf.Timestamp - 56, // 6: tests.ArraysStruct.duration_ar:type_name -> google.protobuf.Duration - 0, // 7: tests.ArraysStruct.empty_ar:type_name -> tests.EmptyStruct - 49, // 8: tests.ArraysArraysStruct.int8_ar_ar:type_name -> tests.TESTS_Int8List - 46, // 9: tests.ArraysArraysStruct.int16_ar_ar:type_name -> tests.TESTS_Int16List - 47, // 10: tests.ArraysArraysStruct.int32_ar_ar:type_name -> tests.TESTS_Int32ValueList - 42, // 11: tests.ArraysArraysStruct.int32_fixed_ar_ar:type_name -> tests.TESTS_Fixed32Int32ValueList - 48, // 12: tests.ArraysArraysStruct.int64_ar_ar:type_name -> tests.TESTS_Int64ValueList - 44, // 13: tests.ArraysArraysStruct.int64_fixed_ar_ar:type_name -> tests.TESTS_Fixed64Int64ValueList - 48, // 14: tests.ArraysArraysStruct.int_ar_ar:type_name -> tests.TESTS_Int64ValueList - 52, // 15: tests.ArraysArraysStruct.uint16_ar_ar:type_name -> tests.TESTS_UInt16List - 53, // 16: tests.ArraysArraysStruct.uint32_ar_ar:type_name -> tests.TESTS_UInt32ValueList - 43, // 17: tests.ArraysArraysStruct.uint32_fixed_ar_ar:type_name -> tests.TESTS_Fixed32UInt32ValueList - 54, // 18: tests.ArraysArraysStruct.uint64_ar_ar:type_name -> tests.TESTS_UInt64ValueList - 45, // 19: tests.ArraysArraysStruct.uint64_fixed_ar_ar:type_name -> tests.TESTS_Fixed64UInt64ValueList - 54, // 20: tests.ArraysArraysStruct.uint_ar_ar:type_name -> tests.TESTS_UInt64ValueList - 50, // 21: tests.ArraysArraysStruct.str_ar_ar:type_name -> tests.TESTS_StringValueList - 38, // 22: tests.ArraysArraysStruct.bytes_ar_ar:type_name -> tests.TESTS_BytesList - 51, // 23: tests.ArraysArraysStruct.time_ar_ar:type_name -> tests.TESTS_TimestampList - 40, // 24: tests.ArraysArraysStruct.duration_ar_ar:type_name -> tests.TESTS_DurationList - 41, // 25: tests.ArraysArraysStruct.empty_ar_ar:type_name -> tests.TESTS_EmptyStructList - 55, // 26: tests.SlicesStruct.time_sl:type_name -> google.protobuf.Timestamp - 56, // 27: tests.SlicesStruct.duration_sl:type_name -> google.protobuf.Duration - 0, // 28: tests.SlicesStruct.empty_sl:type_name -> tests.EmptyStruct - 49, // 29: tests.SlicesSlicesStruct.int8_sl_sl:type_name -> tests.TESTS_Int8List - 46, // 30: tests.SlicesSlicesStruct.int16_sl_sl:type_name -> tests.TESTS_Int16List - 47, // 31: tests.SlicesSlicesStruct.int32_sl_sl:type_name -> tests.TESTS_Int32ValueList - 42, // 32: tests.SlicesSlicesStruct.int32_fixed_sl_sl:type_name -> tests.TESTS_Fixed32Int32ValueList - 48, // 33: tests.SlicesSlicesStruct.int64_sl_sl:type_name -> tests.TESTS_Int64ValueList - 44, // 34: tests.SlicesSlicesStruct.int64_fixed_sl_sl:type_name -> tests.TESTS_Fixed64Int64ValueList - 48, // 35: tests.SlicesSlicesStruct.int_sl_sl:type_name -> tests.TESTS_Int64ValueList - 52, // 36: tests.SlicesSlicesStruct.uint16_sl_sl:type_name -> tests.TESTS_UInt16List - 53, // 37: tests.SlicesSlicesStruct.uint32_sl_sl:type_name -> tests.TESTS_UInt32ValueList - 43, // 38: tests.SlicesSlicesStruct.uint32_fixed_sl_sl:type_name -> tests.TESTS_Fixed32UInt32ValueList - 54, // 39: tests.SlicesSlicesStruct.uint64_sl_sl:type_name -> tests.TESTS_UInt64ValueList - 45, // 40: tests.SlicesSlicesStruct.uint64_fixed_sl_sl:type_name -> tests.TESTS_Fixed64UInt64ValueList - 54, // 41: tests.SlicesSlicesStruct.uint_sl_sl:type_name -> tests.TESTS_UInt64ValueList - 50, // 42: tests.SlicesSlicesStruct.str_sl_sl:type_name -> tests.TESTS_StringValueList - 38, // 43: tests.SlicesSlicesStruct.bytes_sl_sl:type_name -> tests.TESTS_BytesList - 51, // 44: tests.SlicesSlicesStruct.time_sl_sl:type_name -> tests.TESTS_TimestampList - 40, // 45: tests.SlicesSlicesStruct.duration_sl_sl:type_name -> tests.TESTS_DurationList - 41, // 46: tests.SlicesSlicesStruct.empty_sl_sl:type_name -> tests.TESTS_EmptyStructList - 55, // 47: tests.PointersStruct.time_pt:type_name -> google.protobuf.Timestamp - 56, // 48: tests.PointersStruct.duration_pt:type_name -> google.protobuf.Duration - 0, // 49: tests.PointersStruct.empty_pt:type_name -> tests.EmptyStruct - 55, // 50: tests.PointerSlicesStruct.time_pt_sl:type_name -> google.protobuf.Timestamp - 56, // 51: tests.PointerSlicesStruct.duration_pt_sl:type_name -> google.protobuf.Duration - 0, // 52: tests.PointerSlicesStruct.empty_pt_sl:type_name -> tests.EmptyStruct - 1, // 53: tests.ComplexSt.pr_field:type_name -> tests.PrimitivesStruct - 3, // 54: tests.ComplexSt.ar_field:type_name -> tests.ArraysStruct - 5, // 55: tests.ComplexSt.sl_field:type_name -> tests.SlicesStruct - 7, // 56: tests.ComplexSt.pt_field:type_name -> tests.PointersStruct - 1, // 57: tests.EmbeddedSt1.primitives_struct:type_name -> tests.PrimitivesStruct - 1, // 58: tests.EmbeddedSt2.primitives_struct:type_name -> tests.PrimitivesStruct - 3, // 59: tests.EmbeddedSt2.arrays_struct:type_name -> tests.ArraysStruct - 5, // 60: tests.EmbeddedSt2.slices_struct:type_name -> tests.SlicesStruct - 7, // 61: tests.EmbeddedSt2.pointers_struct:type_name -> tests.PointersStruct - 1, // 62: tests.EmbeddedSt3.primitives_struct:type_name -> tests.PrimitivesStruct - 3, // 63: tests.EmbeddedSt3.arrays_struct:type_name -> tests.ArraysStruct - 5, // 64: tests.EmbeddedSt3.slices_struct:type_name -> tests.SlicesStruct - 7, // 65: tests.EmbeddedSt3.pointers_struct:type_name -> tests.PointersStruct - 0, // 66: tests.EmbeddedSt3.empty_struct:type_name -> tests.EmptyStruct - 1, // 67: tests.EmbeddedSt4.primitives_struct:type_name -> tests.PrimitivesStruct - 3, // 68: tests.EmbeddedSt4.arrays_struct_field:type_name -> tests.ArraysStruct - 5, // 69: tests.EmbeddedSt4.slices_struct:type_name -> tests.SlicesStruct - 7, // 70: tests.EmbeddedSt4.pointers_struct_field:type_name -> tests.PointersStruct - 1, // 71: tests.EmbeddedSt5NameOverride.primitives_struct:type_name -> tests.PrimitivesStruct - 3, // 72: tests.EmbeddedSt5NameOverride.arrays_struct_field:type_name -> tests.ArraysStruct - 5, // 73: tests.EmbeddedSt5NameOverride.slices_struct:type_name -> tests.SlicesStruct - 7, // 74: tests.EmbeddedSt5NameOverride.pointers_struct_field:type_name -> tests.PointersStruct - 18, // 75: tests.AminoMarshalerStruct2.value:type_name -> tests.ReprElem2 - 57, // 76: tests.ReprElem2.value:type_name -> google.protobuf.Any - 15, // 77: tests.AminoMarshalerStruct6.value:type_name -> tests.AminoMarshalerStruct1 - 55, // 78: tests.PrimitivesStructDef.time:type_name -> google.protobuf.Timestamp - 56, // 79: tests.PrimitivesStructDef.duration:type_name -> google.protobuf.Duration - 0, // 80: tests.PrimitivesStructDef.empty:type_name -> tests.EmptyStruct - 1, // 81: tests.PrimitivesStructSl.value:type_name -> tests.PrimitivesStruct - 1, // 82: tests.PrimitivesStructAr.value:type_name -> tests.PrimitivesStruct - 57, // 83: tests.InterfaceFieldsStruct.f1:type_name -> google.protobuf.Any - 57, // 84: tests.InterfaceFieldsStruct.f2:type_name -> google.protobuf.Any - 57, // 85: tests.InterfaceFieldsStruct.f3:type_name -> google.protobuf.Any - 57, // 86: tests.InterfaceFieldsStruct.f4:type_name -> google.protobuf.Any - 38, // 87: tests.TESTS_BytesListList.Value:type_name -> tests.TESTS_BytesList - 56, // 88: tests.TESTS_DurationList.Value:type_name -> google.protobuf.Duration - 0, // 89: tests.TESTS_EmptyStructList.Value:type_name -> tests.EmptyStruct - 55, // 90: tests.TESTS_TimestampList.Value:type_name -> google.protobuf.Timestamp - 91, // [91:91] is the sub-list for method output_type - 91, // [91:91] is the sub-list for method input_type - 91, // [91:91] is the sub-list for extension type_name - 91, // [91:91] is the sub-list for extension extendee - 0, // [0:91] is the sub-list for field type_name -} - -func init() { file_tests_proto_init() } -func file_tests_proto_init() { - if File_tests_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_tests_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EmptyStruct); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PrimitivesStruct); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ShortArraysStruct); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ArraysStruct); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ArraysArraysStruct); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SlicesStruct); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SlicesSlicesStruct); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PointersStruct); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PointerSlicesStruct); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ComplexSt); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EmbeddedSt1); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EmbeddedSt2); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EmbeddedSt3); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EmbeddedSt4); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EmbeddedSt5NameOverride); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AminoMarshalerStruct1); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ReprStruct1); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AminoMarshalerStruct2); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ReprElem2); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AminoMarshalerStruct3); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AminoMarshalerInt4); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AminoMarshalerInt5); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AminoMarshalerStruct6); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AminoMarshalerStruct7); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ReprElem7); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*IntDef); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*IntAr); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*IntSl); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ByteAr); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ByteSl); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PrimitivesStructDef); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PrimitivesStructSl); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PrimitivesStructAr); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Concrete1); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Concrete2); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ConcreteTypeDef); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ConcreteWrappedBytes); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*InterfaceFieldsStruct); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TESTS_BytesList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TESTS_BytesListList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TESTS_DurationList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TESTS_EmptyStructList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TESTS_Fixed32Int32ValueList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TESTS_Fixed32UInt32ValueList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TESTS_Fixed64Int64ValueList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TESTS_Fixed64UInt64ValueList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TESTS_Int16List); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TESTS_Int32ValueList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[48].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TESTS_Int64ValueList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TESTS_Int8List); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[50].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TESTS_StringValueList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[51].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TESTS_TimestampList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[52].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TESTS_UInt16List); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[53].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TESTS_UInt32ValueList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tests_proto_msgTypes[54].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TESTS_UInt64ValueList); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_tests_proto_rawDesc, - NumEnums: 0, - NumMessages: 55, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_tests_proto_goTypes, - DependencyIndexes: file_tests_proto_depIdxs, - MessageInfos: file_tests_proto_msgTypes, - }.Build() - File_tests_proto = out.File - file_tests_proto_rawDesc = nil - file_tests_proto_goTypes = nil - file_tests_proto_depIdxs = nil -} diff --git a/tm2/pkg/amino/tests/proto3/proto/compat.pb.go b/tm2/pkg/amino/tests/proto3/proto/compat.pb.go deleted file mode 100644 index b03a9273125..00000000000 --- a/tm2/pkg/amino/tests/proto3/proto/compat.pb.go +++ /dev/null @@ -1,1044 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.31.0 -// protoc v4.24.3 -// source: proto/compat.proto - -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" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type TestInt32Varint struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Int32 int32 `protobuf:"zigzag32,1,opt,name=Int32,proto3" json:"Int32,omitempty"` -} - -func (x *TestInt32Varint) Reset() { - *x = TestInt32Varint{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_compat_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TestInt32Varint) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TestInt32Varint) ProtoMessage() {} - -func (x *TestInt32Varint) ProtoReflect() protoreflect.Message { - mi := &file_proto_compat_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TestInt32Varint.ProtoReflect.Descriptor instead. -func (*TestInt32Varint) Descriptor() ([]byte, []int) { - return file_proto_compat_proto_rawDescGZIP(), []int{0} -} - -func (x *TestInt32Varint) GetInt32() int32 { - if x != nil { - return x.Int32 - } - return 0 -} - -type TestInt32Fixed struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Fixed32 uint32 `protobuf:"fixed32,1,opt,name=Fixed32,proto3" json:"Fixed32,omitempty"` -} - -func (x *TestInt32Fixed) Reset() { - *x = TestInt32Fixed{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_compat_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TestInt32Fixed) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TestInt32Fixed) ProtoMessage() {} - -func (x *TestInt32Fixed) ProtoReflect() protoreflect.Message { - mi := &file_proto_compat_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TestInt32Fixed.ProtoReflect.Descriptor instead. -func (*TestInt32Fixed) Descriptor() ([]byte, []int) { - return file_proto_compat_proto_rawDescGZIP(), []int{1} -} - -func (x *TestInt32Fixed) GetFixed32() uint32 { - if x != nil { - return x.Fixed32 - } - return 0 -} - -type Test32 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Foo uint32 `protobuf:"fixed32,1,opt,name=foo,proto3" json:"foo,omitempty"` - Bar int32 `protobuf:"zigzag32,2,opt,name=bar,proto3" json:"bar,omitempty"` -} - -func (x *Test32) Reset() { - *x = Test32{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_compat_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Test32) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Test32) ProtoMessage() {} - -func (x *Test32) ProtoReflect() protoreflect.Message { - mi := &file_proto_compat_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Test32.ProtoReflect.Descriptor instead. -func (*Test32) Descriptor() ([]byte, []int) { - return file_proto_compat_proto_rawDescGZIP(), []int{2} -} - -func (x *Test32) GetFoo() uint32 { - if x != nil { - return x.Foo - } - return 0 -} - -func (x *Test32) GetBar() int32 { - if x != nil { - return x.Bar - } - return 0 -} - -type TestFixedInt64 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Int64 uint64 `protobuf:"fixed64,1,opt,name=Int64,proto3" json:"Int64,omitempty"` -} - -func (x *TestFixedInt64) Reset() { - *x = TestFixedInt64{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_compat_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TestFixedInt64) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TestFixedInt64) ProtoMessage() {} - -func (x *TestFixedInt64) ProtoReflect() protoreflect.Message { - mi := &file_proto_compat_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TestFixedInt64.ProtoReflect.Descriptor instead. -func (*TestFixedInt64) Descriptor() ([]byte, []int) { - return file_proto_compat_proto_rawDescGZIP(), []int{3} -} - -func (x *TestFixedInt64) GetInt64() uint64 { - if x != nil { - return x.Int64 - } - return 0 -} - -type TestSFixedSInt64 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - SInt64 int64 `protobuf:"fixed64,1,opt,name=SInt64,proto3" json:"SInt64,omitempty"` -} - -func (x *TestSFixedSInt64) Reset() { - *x = TestSFixedSInt64{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_compat_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TestSFixedSInt64) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TestSFixedSInt64) ProtoMessage() {} - -func (x *TestSFixedSInt64) ProtoReflect() protoreflect.Message { - mi := &file_proto_compat_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TestSFixedSInt64.ProtoReflect.Descriptor instead. -func (*TestSFixedSInt64) Descriptor() ([]byte, []int) { - return file_proto_compat_proto_rawDescGZIP(), []int{4} -} - -func (x *TestSFixedSInt64) GetSInt64() int64 { - if x != nil { - return x.SInt64 - } - return 0 -} - -type EmbeddedStruct struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - SomethingFixedLen int64 `protobuf:"fixed64,1,opt,name=somethingFixedLen,proto3" json:"somethingFixedLen,omitempty"` -} - -func (x *EmbeddedStruct) Reset() { - *x = EmbeddedStruct{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_compat_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *EmbeddedStruct) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*EmbeddedStruct) ProtoMessage() {} - -func (x *EmbeddedStruct) ProtoReflect() protoreflect.Message { - mi := &file_proto_compat_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use EmbeddedStruct.ProtoReflect.Descriptor instead. -func (*EmbeddedStruct) Descriptor() ([]byte, []int) { - return file_proto_compat_proto_rawDescGZIP(), []int{5} -} - -func (x *EmbeddedStruct) GetSomethingFixedLen() int64 { - if x != nil { - return x.SomethingFixedLen - } - return 0 -} - -type SomeStruct struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // proto3 autom. turns this into a pointer ... - Emb *EmbeddedStruct `protobuf:"bytes,1,opt,name=emb,proto3" json:"emb,omitempty"` -} - -func (x *SomeStruct) Reset() { - *x = SomeStruct{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_compat_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SomeStruct) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SomeStruct) ProtoMessage() {} - -func (x *SomeStruct) ProtoReflect() protoreflect.Message { - mi := &file_proto_compat_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SomeStruct.ProtoReflect.Descriptor instead. -func (*SomeStruct) Descriptor() ([]byte, []int) { - return file_proto_compat_proto_rawDescGZIP(), []int{6} -} - -func (x *SomeStruct) GetEmb() *EmbeddedStruct { - if x != nil { - return x.Emb - } - return nil -} - -type ProtoGotTime struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - T *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=T,proto3" json:"T,omitempty"` -} - -func (x *ProtoGotTime) Reset() { - *x = ProtoGotTime{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_compat_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ProtoGotTime) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ProtoGotTime) ProtoMessage() {} - -func (x *ProtoGotTime) ProtoReflect() protoreflect.Message { - mi := &file_proto_compat_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ProtoGotTime.ProtoReflect.Descriptor instead. -func (*ProtoGotTime) Descriptor() ([]byte, []int) { - return file_proto_compat_proto_rawDescGZIP(), []int{7} -} - -func (x *ProtoGotTime) GetT() *timestamppb.Timestamp { - if x != nil { - return x.T - } - return nil -} - -type TestInt32 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Int32 int32 `protobuf:"varint,1,opt,name=Int32,proto3" json:"Int32,omitempty"` -} - -func (x *TestInt32) Reset() { - *x = TestInt32{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_compat_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TestInt32) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TestInt32) ProtoMessage() {} - -func (x *TestInt32) ProtoReflect() protoreflect.Message { - mi := &file_proto_compat_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TestInt32.ProtoReflect.Descriptor instead. -func (*TestInt32) Descriptor() ([]byte, []int) { - return file_proto_compat_proto_rawDescGZIP(), []int{8} -} - -func (x *TestInt32) GetInt32() int32 { - if x != nil { - return x.Int32 - } - return 0 -} - -type TestInts struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Int32 int32 `protobuf:"varint,1,opt,name=Int32,proto3" json:"Int32,omitempty"` - Int64 int64 `protobuf:"varint,2,opt,name=Int64,proto3" json:"Int64,omitempty"` -} - -func (x *TestInts) Reset() { - *x = TestInts{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_compat_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TestInts) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TestInts) ProtoMessage() {} - -func (x *TestInts) ProtoReflect() protoreflect.Message { - mi := &file_proto_compat_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TestInts.ProtoReflect.Descriptor instead. -func (*TestInts) Descriptor() ([]byte, []int) { - return file_proto_compat_proto_rawDescGZIP(), []int{9} -} - -func (x *TestInts) GetInt32() int32 { - if x != nil { - return x.Int32 - } - return 0 -} - -func (x *TestInts) GetInt64() int64 { - if x != nil { - return x.Int64 - } - return 0 -} - -type IntDef struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Val int64 `protobuf:"varint,1,opt,name=val,proto3" json:"val,omitempty"` -} - -func (x *IntDef) Reset() { - *x = IntDef{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_compat_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *IntDef) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*IntDef) ProtoMessage() {} - -func (x *IntDef) ProtoReflect() protoreflect.Message { - mi := &file_proto_compat_proto_msgTypes[10] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use IntDef.ProtoReflect.Descriptor instead. -func (*IntDef) Descriptor() ([]byte, []int) { - return file_proto_compat_proto_rawDescGZIP(), []int{10} -} - -func (x *IntDef) GetVal() int64 { - if x != nil { - return x.Val - } - return 0 -} - -type IntArr struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Val []int64 `protobuf:"varint,1,rep,packed,name=val,proto3" json:"val,omitempty"` -} - -func (x *IntArr) Reset() { - *x = IntArr{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_compat_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *IntArr) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*IntArr) ProtoMessage() {} - -func (x *IntArr) ProtoReflect() protoreflect.Message { - mi := &file_proto_compat_proto_msgTypes[11] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use IntArr.ProtoReflect.Descriptor instead. -func (*IntArr) Descriptor() ([]byte, []int) { - return file_proto_compat_proto_rawDescGZIP(), []int{11} -} - -func (x *IntArr) GetVal() []int64 { - if x != nil { - return x.Val - } - return nil -} - -type PrimitivesStruct struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Int32 int32 `protobuf:"varint,3,opt,name=Int32,proto3" json:"Int32,omitempty"` - Int64 int64 `protobuf:"varint,4,opt,name=Int64,proto3" json:"Int64,omitempty"` - Varint int64 `protobuf:"varint,5,opt,name=Varint,proto3" json:"Varint,omitempty"` - // int int - // Byte byte = 4; // this just another varint - // Uint8 uint8 // another varint - // Uint16 uint16 // another one, also the following - // Uint32 uint32 - // Uint64 uint64 - // Uvarint uint64 `binary:"varint"` - // Uint uint - String_ string `protobuf:"bytes,14,opt,name=String,proto3" json:"String,omitempty"` - Bytes []byte `protobuf:"bytes,15,opt,name=Bytes,proto3" json:"Bytes,omitempty"` - Time *timestamppb.Timestamp `protobuf:"bytes,16,opt,name=Time,proto3" json:"Time,omitempty"` -} - -func (x *PrimitivesStruct) Reset() { - *x = PrimitivesStruct{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_compat_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PrimitivesStruct) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PrimitivesStruct) ProtoMessage() {} - -func (x *PrimitivesStruct) ProtoReflect() protoreflect.Message { - mi := &file_proto_compat_proto_msgTypes[12] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PrimitivesStruct.ProtoReflect.Descriptor instead. -func (*PrimitivesStruct) Descriptor() ([]byte, []int) { - return file_proto_compat_proto_rawDescGZIP(), []int{12} -} - -func (x *PrimitivesStruct) GetInt32() int32 { - if x != nil { - return x.Int32 - } - return 0 -} - -func (x *PrimitivesStruct) GetInt64() int64 { - if x != nil { - return x.Int64 - } - return 0 -} - -func (x *PrimitivesStruct) GetVarint() int64 { - if x != nil { - return x.Varint - } - return 0 -} - -func (x *PrimitivesStruct) GetString_() string { - if x != nil { - return x.String_ - } - return "" -} - -func (x *PrimitivesStruct) GetBytes() []byte { - if x != nil { - return x.Bytes - } - return nil -} - -func (x *PrimitivesStruct) GetTime() *timestamppb.Timestamp { - if x != nil { - return x.Time - } - return nil -} - -type PrimitivesStructSl struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Structs []*PrimitivesStruct `protobuf:"bytes,1,rep,name=Structs,proto3" json:"Structs,omitempty"` -} - -func (x *PrimitivesStructSl) Reset() { - *x = PrimitivesStructSl{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_compat_proto_msgTypes[13] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PrimitivesStructSl) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PrimitivesStructSl) ProtoMessage() {} - -func (x *PrimitivesStructSl) ProtoReflect() protoreflect.Message { - mi := &file_proto_compat_proto_msgTypes[13] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PrimitivesStructSl.ProtoReflect.Descriptor instead. -func (*PrimitivesStructSl) Descriptor() ([]byte, []int) { - return file_proto_compat_proto_rawDescGZIP(), []int{13} -} - -func (x *PrimitivesStructSl) GetStructs() []*PrimitivesStruct { - if x != nil { - return x.Structs - } - return nil -} - -var File_proto_compat_proto protoreflect.FileDescriptor - -var file_proto_compat_proto_rawDesc = []byte{ - 0x0a, 0x12, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x74, 0x65, 0x73, 0x74, - 0x73, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x22, 0x27, 0x0a, 0x0f, 0x54, 0x65, 0x73, 0x74, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, - 0x61, 0x72, 0x69, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x11, 0x52, 0x05, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x22, 0x2a, 0x0a, 0x0e, 0x54, - 0x65, 0x73, 0x74, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x78, 0x65, 0x64, 0x12, 0x18, 0x0a, - 0x07, 0x46, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x18, 0x01, 0x20, 0x01, 0x28, 0x07, 0x52, 0x07, - 0x46, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x22, 0x2c, 0x0a, 0x06, 0x54, 0x65, 0x73, 0x74, 0x33, - 0x32, 0x12, 0x10, 0x0a, 0x03, 0x66, 0x6f, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x07, 0x52, 0x03, - 0x66, 0x6f, 0x6f, 0x12, 0x10, 0x0a, 0x03, 0x62, 0x61, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x11, - 0x52, 0x03, 0x62, 0x61, 0x72, 0x22, 0x26, 0x0a, 0x0e, 0x54, 0x65, 0x73, 0x74, 0x46, 0x69, 0x78, - 0x65, 0x64, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x12, 0x14, 0x0a, 0x05, 0x49, 0x6e, 0x74, 0x36, 0x34, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x06, 0x52, 0x05, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x22, 0x2a, 0x0a, - 0x10, 0x54, 0x65, 0x73, 0x74, 0x53, 0x46, 0x69, 0x78, 0x65, 0x64, 0x53, 0x49, 0x6e, 0x74, 0x36, - 0x34, 0x12, 0x16, 0x0a, 0x06, 0x53, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x10, 0x52, 0x06, 0x53, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x22, 0x3e, 0x0a, 0x0e, 0x45, 0x6d, 0x62, - 0x65, 0x64, 0x64, 0x65, 0x64, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x12, 0x2c, 0x0a, 0x11, 0x73, - 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x46, 0x69, 0x78, 0x65, 0x64, 0x4c, 0x65, 0x6e, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x10, 0x52, 0x11, 0x73, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x69, 0x6e, - 0x67, 0x46, 0x69, 0x78, 0x65, 0x64, 0x4c, 0x65, 0x6e, 0x22, 0x3b, 0x0a, 0x0a, 0x53, 0x6f, 0x6d, - 0x65, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x12, 0x2d, 0x0a, 0x03, 0x65, 0x6d, 0x62, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x74, 0x65, 0x73, - 0x74, 0x73, 0x2e, 0x45, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x53, 0x74, 0x72, 0x75, 0x63, - 0x74, 0x52, 0x03, 0x65, 0x6d, 0x62, 0x22, 0x38, 0x0a, 0x0c, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x47, - 0x6f, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x01, 0x54, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x01, 0x54, - 0x22, 0x21, 0x0a, 0x09, 0x54, 0x65, 0x73, 0x74, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x12, 0x14, 0x0a, - 0x05, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x49, 0x6e, - 0x74, 0x33, 0x32, 0x22, 0x36, 0x0a, 0x08, 0x54, 0x65, 0x73, 0x74, 0x49, 0x6e, 0x74, 0x73, 0x12, - 0x14, 0x0a, 0x05, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, - 0x49, 0x6e, 0x74, 0x33, 0x32, 0x12, 0x14, 0x0a, 0x05, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x22, 0x1a, 0x0a, 0x06, 0x49, - 0x6e, 0x74, 0x44, 0x65, 0x66, 0x12, 0x10, 0x0a, 0x03, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x03, 0x76, 0x61, 0x6c, 0x22, 0x1a, 0x0a, 0x06, 0x49, 0x6e, 0x74, 0x41, 0x72, - 0x72, 0x12, 0x10, 0x0a, 0x03, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x03, 0x28, 0x03, 0x52, 0x03, - 0x76, 0x61, 0x6c, 0x22, 0xb4, 0x01, 0x0a, 0x10, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, - 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x49, 0x6e, 0x74, 0x33, - 0x32, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x12, 0x14, - 0x0a, 0x05, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x49, - 0x6e, 0x74, 0x36, 0x34, 0x12, 0x16, 0x0a, 0x06, 0x56, 0x61, 0x72, 0x69, 0x6e, 0x74, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x56, 0x61, 0x72, 0x69, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, - 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x53, 0x74, - 0x72, 0x69, 0x6e, 0x67, 0x12, 0x14, 0x0a, 0x05, 0x42, 0x79, 0x74, 0x65, 0x73, 0x18, 0x0f, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x05, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x2e, 0x0a, 0x04, 0x54, 0x69, - 0x6d, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x4d, 0x0a, 0x12, 0x50, 0x72, - 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x53, 0x6c, - 0x12, 0x37, 0x0a, 0x07, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, - 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, - 0x52, 0x07, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, -} - -var ( - file_proto_compat_proto_rawDescOnce sync.Once - file_proto_compat_proto_rawDescData = file_proto_compat_proto_rawDesc -) - -func file_proto_compat_proto_rawDescGZIP() []byte { - file_proto_compat_proto_rawDescOnce.Do(func() { - file_proto_compat_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_compat_proto_rawDescData) - }) - return file_proto_compat_proto_rawDescData -} - -var file_proto_compat_proto_msgTypes = make([]protoimpl.MessageInfo, 14) -var file_proto_compat_proto_goTypes = []interface{}{ - (*TestInt32Varint)(nil), // 0: proto3tests.TestInt32Varint - (*TestInt32Fixed)(nil), // 1: proto3tests.TestInt32Fixed - (*Test32)(nil), // 2: proto3tests.Test32 - (*TestFixedInt64)(nil), // 3: proto3tests.TestFixedInt64 - (*TestSFixedSInt64)(nil), // 4: proto3tests.TestSFixedSInt64 - (*EmbeddedStruct)(nil), // 5: proto3tests.EmbeddedStruct - (*SomeStruct)(nil), // 6: proto3tests.SomeStruct - (*ProtoGotTime)(nil), // 7: proto3tests.ProtoGotTime - (*TestInt32)(nil), // 8: proto3tests.TestInt32 - (*TestInts)(nil), // 9: proto3tests.TestInts - (*IntDef)(nil), // 10: proto3tests.IntDef - (*IntArr)(nil), // 11: proto3tests.IntArr - (*PrimitivesStruct)(nil), // 12: proto3tests.PrimitivesStruct - (*PrimitivesStructSl)(nil), // 13: proto3tests.PrimitivesStructSl - (*timestamppb.Timestamp)(nil), // 14: google.protobuf.Timestamp -} -var file_proto_compat_proto_depIdxs = []int32{ - 5, // 0: proto3tests.SomeStruct.emb:type_name -> proto3tests.EmbeddedStruct - 14, // 1: proto3tests.ProtoGotTime.T:type_name -> google.protobuf.Timestamp - 14, // 2: proto3tests.PrimitivesStruct.Time:type_name -> google.protobuf.Timestamp - 12, // 3: proto3tests.PrimitivesStructSl.Structs:type_name -> proto3tests.PrimitivesStruct - 4, // [4:4] is the sub-list for method output_type - 4, // [4:4] is the sub-list for method input_type - 4, // [4:4] is the sub-list for extension type_name - 4, // [4:4] is the sub-list for extension extendee - 0, // [0:4] is the sub-list for field type_name -} - -func init() { file_proto_compat_proto_init() } -func file_proto_compat_proto_init() { - if File_proto_compat_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_proto_compat_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TestInt32Varint); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_compat_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TestInt32Fixed); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_compat_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Test32); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_compat_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TestFixedInt64); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_compat_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TestSFixedSInt64); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_compat_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EmbeddedStruct); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_compat_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SomeStruct); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_compat_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProtoGotTime); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_compat_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TestInt32); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_compat_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TestInts); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_compat_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*IntDef); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_compat_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*IntArr); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_compat_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PrimitivesStruct); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_compat_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PrimitivesStructSl); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_proto_compat_proto_rawDesc, - NumEnums: 0, - NumMessages: 14, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_proto_compat_proto_goTypes, - DependencyIndexes: file_proto_compat_proto_depIdxs, - MessageInfos: file_proto_compat_proto_msgTypes, - }.Build() - File_proto_compat_proto = out.File - file_proto_compat_proto_rawDesc = nil - file_proto_compat_proto_goTypes = nil - file_proto_compat_proto_depIdxs = nil -} diff --git a/tm2/pkg/amino/tests/proto3/proto/doc.go b/tm2/pkg/amino/tests/proto3/proto/doc.go new file mode 100644 index 00000000000..909d94e7e7f --- /dev/null +++ b/tm2/pkg/amino/tests/proto3/proto/doc.go @@ -0,0 +1,3 @@ +// This file ensures there is at least one go file in this dir at all times. + +package proto3 diff --git a/tm2/pkg/amino/tests/proto3/proto3_compat_test.go b/tm2/pkg/amino/tests/proto3/proto3_compat_test.go deleted file mode 100644 index 8f9e04fc35c..00000000000 --- a/tm2/pkg/amino/tests/proto3/proto3_compat_test.go +++ /dev/null @@ -1,458 +0,0 @@ -//go:build extensive_tests - -// only built if manually enforced (via the build tag above) -package proto3 - -import ( - "bufio" - "bytes" - "encoding/binary" - "math" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/golang/protobuf/proto" - "github.com/golang/protobuf/ptypes" - - p3 "github.com/gnolang/gno/tm2/pkg/amino/tests/proto3/proto" - - "github.com/gnolang/gno/tm2/pkg/amino" - "github.com/gnolang/gno/tm2/pkg/amino/tests" -) - -// This file checks basic proto3 compatibility by checking encoding of some test-vectors generated by using protoc. - -var ( - cdc = amino.NewCodec() - epoch time.Time -) - -func init() { - cdc.Seal() - epoch, _ = time.Parse("2006-01-02 15:04:05 +0000 UTC", "1970-01-01 00:00:00 +0000 UTC") -} - -func TestFixed32Roundtrip(t *testing.T) { - t.Parallel() - - // amino fixed32 (int32) <-> protbuf fixed32 (uint32) - type testi32 struct { - Int32 int32 `binary:"fixed32"` - } - ab, err := cdc.Marshal(testi32{Int32: 150}) - assert.NoError(t, err, "unexpected error") - - pb, err := proto.Marshal(&p3.TestInt32Fixed{Fixed32: 150}) - assert.NoError(t, err, "unexpected error") - - assert.Equal(t, pb, ab, "fixed32 (int32) encoding doesn't match") - - // unmarshal (from amino to proto and vice versa) - var att testi32 - var pt p3.Test32 - err = proto.Unmarshal(ab, &pt) - assert.NoError(t, err, "unexpected error") - - err = cdc.Unmarshal(pb, &att) - assert.NoError(t, err, "unexpected error") - - assert.Equal(t, uint32(att.Int32), pt.Foo) -} - -func TestVarintZigzagRoundtrip(t *testing.T) { - t.Parallel() - - t.Skip("zigzag encoding isn't default anymore for (unsigned) ints") - // amino varint (int) <-> protobuf zigzag32 (int32 in go sint32 in proto file) - type testInt32Varint struct { - Int32 int `binary:"varint"` - } - varint := testInt32Varint{Int32: 6000000} - ab, err := cdc.Marshal(varint) - assert.NoError(t, err, "unexpected error") - pb, err := proto.Marshal(&p3.TestInt32Varint{Int32: 6000000}) - assert.NoError(t, err, "unexpected error") - assert.Equal(t, pb, ab, "varint encoding doesn't match") - - var amToP3 p3.TestInt32Varint - var p3ToAm testInt32Varint - err = proto.Unmarshal(ab, &amToP3) - assert.NoError(t, err, "unexpected error") - - err = cdc.Unmarshal(pb, &p3ToAm) - assert.NoError(t, err, "unexpected error") - - assert.EqualValues(t, varint.Int32, amToP3.Int32) -} - -func TestFixedU64Roundtrip(t *testing.T) { - t.Parallel() - - type testFixed64Uint struct { - Int64 uint64 `binary:"fixed64"` - } - - pvint64 := p3.TestFixedInt64{Int64: 150} - avint64 := testFixed64Uint{Int64: 150} - ab, err := cdc.Marshal(avint64) - assert.NoError(t, err, "unexpected error") - - pb, err := proto.Marshal(&pvint64) - assert.NoError(t, err, "unexpected error") - - assert.Equal(t, pb, ab, "fixed64 encoding doesn't match") - - var amToP3 p3.TestFixedInt64 - var p3ToAm testFixed64Uint - err = proto.Unmarshal(ab, &amToP3) - assert.NoError(t, err, "unexpected error") - - err = cdc.Unmarshal(pb, &p3ToAm) - assert.NoError(t, err, "unexpected error") - - assert.EqualValues(t, p3ToAm.Int64, amToP3.Int64) -} - -func TestMultidimensionalSlices(t *testing.T) { - t.Parallel() - - s := [][]int8{ - {1, 2}, - {3, 4, 5}, - } - - _, err := cdc.Marshal(s) - assert.Error(t, err, "expected error: multidimensional slices are not allowed") -} - -func TestMultidimensionalArrays(t *testing.T) { - t.Parallel() - - arr := [2][2]int8{ - {1, 2}, - {3, 4}, - } - - _, err := cdc.Marshal(arr) - assert.Error(t, err, "expected error: multidimensional arrays are not allowed") -} - -func TestMultidimensionalByteArraysAndSlices(t *testing.T) { - t.Parallel() - - arr := [2][2]byte{ - {1, 2}, - {3, 4}, - } - - _, err := cdc.Marshal(arr) - assert.NoError(t, err, "unexpected error: multidimensional arrays are allowed, as long as they are only of bytes") - - s := [][]byte{ - {1, 2}, - {3, 4, 5}, - } - - _, err = cdc.Marshal(s) - assert.NoError(t, err, "unexpected error: multidimensional slices are allowed, as long as they are only of bytes") - - s2 := [][][]byte{{ - {1, 2}, - {3, 4, 5}, - }} - - _, err = cdc.Marshal(s2) - assert.NoError(t, err, "unexpected error: multidimensional slices are allowed, as long as they are only of bytes") -} - -func TestProto3CompatPtrsRoundtrip(t *testing.T) { - t.Parallel() - - s := p3.SomeStruct{} - - ab, err := cdc.Marshal(s) - assert.NoError(t, err) - - pb, err := proto.Marshal(&s) - assert.NoError(t, err) - // This fails as amino currently returns []byte(nil) - // while protobuf returns []byte{}: - // - // assert.Equal(t, ab, pb) - // - // Semantically, that's no problem though. Hence, we only check for zero length: - assert.Zero(t, len(ab), "expected an empty encoding for a nil pointer") - t.Log(ab) - - var amToP3 p3.SomeStruct - var p3ToAm p3.SomeStruct - err = proto.Unmarshal(ab, &amToP3) - assert.NoError(t, err, "unexpected error") - - err = cdc.Unmarshal(pb, &p3ToAm) - assert.NoError(t, err, "unexpected error") - - assert.EqualValues(t, p3ToAm, amToP3) - - s2 := p3.SomeStruct{Emb: &p3.EmbeddedStruct{}} - - ab, err = cdc.Marshal(s2) - assert.NoError(t, err) - - pb, err = proto.Marshal(&s2) - assert.NoError(t, err) - assert.Equal(t, ab, pb) - - err = proto.Unmarshal(ab, &amToP3) - assert.NoError(t, err, "unexpected error") - - err = cdc.Unmarshal(pb, &p3ToAm) - assert.NoError(t, err, "unexpected error") - - assert.EqualValues(t, p3ToAm, amToP3) - - assert.NotZero(t, len(ab), "expected a non-empty encoding for a non-nil pointer to an empty struct") - t.Log(ab) -} - -// --------------------------------------------------------------- -// ---- time.Time <-> timestamp.Timestamp (proto3 well known type) : -// --------------------------------------------------------------- - -// equivalent go struct or "type" to the proto3 message: -type goAminoGotTime struct { - T *time.Time -} - -func TestProto3CompatEmptyTimestamp(t *testing.T) { - t.Parallel() - - empty := p3.ProtoGotTime{} - // protobuf also marshals to empty bytes here: - pb, err := proto.Marshal(&empty) - assert.NoError(t, err) - assert.Len(t, pb, 0) - - // unmarshaling an empty slice behaves a bit differently in proto3 compared to amino: - res := &goAminoGotTime{} - err = cdc.Unmarshal(pb, res) - assert.NoError(t, err) - // NOTE: this behaves differently because amino defaults the time to 1970-01-01 00:00:00 +0000 UTC while - // decoding; protobuf defaults to nil here (see the following lines below): - assert.NoError(t, err) - assert.Equal(t, goAminoGotTime{T: &epoch}, *res) - pbRes := p3.ProtoGotTime{} - err = proto.Unmarshal(pb, &pbRes) - assert.NoError(t, err) - assert.Equal(t, p3.ProtoGotTime{T: nil}, pbRes) -} - -func TestProto3CompatTimestampNow(t *testing.T) { - t.Parallel() - - // test with current time: - now := time.Now() - ptts, err := ptypes.TimestampProto(now) - assert.NoError(t, err) - pt := p3.ProtoGotTime{T: ptts} - at := goAminoGotTime{T: &now} - ab1, err := cdc.Marshal(at) - assert.NoError(t, err) - ab2, err := cdc.Marshal(pt) - assert.NoError(t, err) - // amino's encoding of time.Time is the same as proto's encoding of the well known type - // timestamp.Timestamp (they can be used interchangeably): - assert.Equal(t, ab1, ab2) - pb, err := proto.Marshal(&pt) - assert.NoError(t, err) - assert.Equal(t, ab1, pb) - - pbRes := p3.ProtoGotTime{} - err = proto.Unmarshal(ab1, &pbRes) - assert.NoError(t, err) - got, err := ptypes.Timestamp(pbRes.T) - assert.NoError(t, err) - _, err = ptypes.TimestampProto(now) - assert.NoError(t, err) - err = proto.Unmarshal(pb, &pbRes) - assert.NoError(t, err) - // create time.Time from timestamp.Timestamp and check if they are the same: - got, err = ptypes.Timestamp(pbRes.T) - assert.Equal(t, got.UTC(), now.UTC()) -} - -func TestProto3EpochTime(t *testing.T) { - t.Parallel() - - pbRes := p3.ProtoGotTime{} - // amino encode epoch (1970) and decode using proto; expect the resulting time to be epoch again: - ab, err := cdc.Marshal(goAminoGotTime{T: &epoch}) - assert.NoError(t, err) - err = proto.Unmarshal(ab, &pbRes) - assert.NoError(t, err) - ts, err := ptypes.Timestamp(pbRes.T) - assert.NoError(t, err) - assert.EqualValues(t, ts, epoch) -} - -func TestProtoNegativeSeconds(t *testing.T) { - t.Parallel() - - pbRes := p3.ProtoGotTime{} - // test with negative seconds (0001-01-01 -> seconds = -62135596800, nanos = 0): - ntm, err := time.Parse("2006-01-02 15:04:05 +0000 UTC", "0001-01-01 00:00:00 +0000 UTC") - ab, err := cdc.Marshal(goAminoGotTime{T: &ntm}) - assert.NoError(t, err) - res := &goAminoGotTime{} - err = cdc.Unmarshal(ab, res) - assert.NoError(t, err) - assert.EqualValues(t, ntm, *res.T) - err = proto.Unmarshal(ab, &pbRes) - assert.NoError(t, err) - got, err := ptypes.Timestamp(pbRes.T) - assert.NoError(t, err) - assert.Equal(t, got, ntm) -} - -func TestIntVarintCompat(t *testing.T) { - t.Parallel() - - tcs := []struct { - val32 int32 - val64 int64 - }{ - {1, 1}, - {-1, -1}, - {2, 2}, - {1000, 1000}, - {math.MaxInt32, math.MaxInt64}, - {math.MinInt32, math.MinInt64}, - } - for _, tc := range tcs { - tv := p3.TestInts{Int32: tc.val32, Int64: tc.val64} - ab, err := cdc.Marshal(tv) - assert.NoError(t, err) - pb, err := proto.Marshal(&tv) - assert.NoError(t, err) - assert.Equal(t, ab, pb) - var res p3.TestInts - err = cdc.Unmarshal(pb, &res) - assert.NoError(t, err) - var res2 p3.TestInts - err = proto.Unmarshal(ab, &res2) - assert.NoError(t, err) - assert.Equal(t, res.Int32, tc.val32) - assert.Equal(t, res.Int64, tc.val64) - assert.Equal(t, res2.Int32, tc.val32) - assert.Equal(t, res2.Int64, tc.val64) - } - // special case: amino allows int as well - // test that ints are also varint encoded: - type TestInt struct { - Int int - } - tcs2 := []struct { - val int - }{ - {0}, - {-1}, - {1000}, - {-1000}, - {math.MaxInt32}, - {math.MinInt32}, - } - for _, tc := range tcs2 { - ptv := p3.TestInts{Int32: int32(tc.val)} - pb, err := proto.Marshal(&ptv) - assert.NoError(t, err) - atv := TestInt{tc.val} - ab, err := cdc.Marshal(atv) - assert.NoError(t, err) - if tc.val == 0 { - // amino results in []byte(nil) - // protobuf in []byte{} - assert.Empty(t, ab) - assert.Empty(t, pb) - } else { - assert.Equal(t, ab, pb) - } - // can we get back the int from the proto? - var res TestInt - err = cdc.Unmarshal(pb, &res) - assert.NoError(t, err) - assert.EqualValues(t, res.Int, tc.val) - } - - // purposely overflow by writing a too large value to first field (which is int32): - fieldNum := 1 - fieldNumAndType := (uint64(fieldNum) << 3) | uint64(amino.Typ3Varint) - var b bytes.Buffer - writer := bufio.NewWriter(&b) - var buf [10]byte - n := binary.PutUvarint(buf[:], fieldNumAndType) - _, err := writer.Write(buf[0:n]) - assert.NoError(t, err) - amino.EncodeUvarint(writer, math.MaxInt32+1) - err = writer.Flush() - assert.NoError(t, err) - - var res p3.TestInts - err = cdc.Unmarshal(b.Bytes(), &res) - assert.Error(t, err) -} - -// See if encoding of type def types matches the proto3 encoding -func TestTypeDefCompatibility(t *testing.T) { - t.Parallel() - - pNow := ptypes.TimestampNow() - now, err := ptypes.Timestamp(pNow) - require.NoError(t, err) - - strSl := tests.PrimitivesStructSl{ - {Int32: 1, Int64: -1, Varint: 2, String: "protobuf3", Bytes: []byte("got some bytes"), Time: now}, - {Int32: 0, Int64: 1, Varint: -2, String: "amino", Bytes: []byte("more of these bytes"), Time: now}, - } - strAr := tests.PrimitivesStructAr{strSl[0], strSl[1]} - p3StrSl := &p3.PrimitivesStructSl{ - Structs: []*p3.PrimitivesStruct{ - {Int32: 1, Int64: -1, Varint: 2, String_: "protobuf3", Bytes: []byte("got some bytes"), Time: pNow}, - {Int32: 0, Int64: 1, Varint: -2, String_: "amino", Bytes: []byte("more of these bytes"), Time: pNow}, - }, - } - - tcs := []struct { - AminoType interface{} - ProtoMsg proto.Message - }{ - // type IntDef int - 0: {tests.IntDef(0), &p3.IntDef{}}, - 1: {tests.IntDef(0), &p3.IntDef{Val: 0}}, - 2: {tests.IntDef(1), &p3.IntDef{Val: 1}}, - 3: {tests.IntDef(-1), &p3.IntDef{Val: -1}}, - - // type IntAr [4]int - 4: {tests.IntAr{1, 2, 3, 4}, &p3.IntArr{Val: []int64{1, 2, 3, 4}}}, - 5: {tests.IntAr{0, -2, 3, 4}, &p3.IntArr{Val: []int64{0, -2, 3, 4}}}, - - // type IntSl []int (protobuf doesn't really have arrays) - 6: {tests.IntSl{1, 2, 3, 4}, &p3.IntArr{Val: []int64{1, 2, 3, 4}}}, - - // type PrimitivesStructSl []PrimitivesStruct - 7: {strSl, p3StrSl}, - // type PrimitivesStructAr [2]PrimitivesStruct - 8: {strAr, p3StrSl}, - } - for i, tc := range tcs { - ab, err := amino.Marshal(tc.AminoType) - require.NoError(t, err) - - pb, err := proto.Marshal(tc.ProtoMsg) - require.NoError(t, err) - - assert.Equal(t, pb, ab, "Amino and protobuf encoding do not match %v", i) - } -} diff --git a/tm2/pkg/amino/wellknown.go b/tm2/pkg/amino/wellknown.go index 8c8ff79695d..7720c2894d9 100644 --- a/tm2/pkg/amino/wellknown.go +++ b/tm2/pkg/amino/wellknown.go @@ -210,7 +210,6 @@ func isJSONWellKnownType(rt reflect.Type) (wellKnown bool) { default: return false } - return false } // Returns ok=false if nothing was done because the default behavior is fine (or if err). @@ -238,16 +237,21 @@ func encodeReflectJSONWellKnown(w io.Writer, info *TypeInfo, rv reflect.Value, f } return true, nil // Google "well known" types. + // The protobuf Timestamp and Duration values contain a Mutex, and therefore must not be copied. + // The corresponding reflect value may not be addressable, we can not safely get their pointer. + // So we just extract the `Seconds` and `Nanos` fields from the reflect value, without copying + // the whole struct, and encode them as their coresponding time.Time or time.Duration value. case gTimestampType: - t := rv.Interface().(timestamppb.Timestamp) - err = EncodeJSONPBTimestamp(w, t) + t := time.Unix(rv.Interface().(timestamppb.Timestamp).Seconds, int64(rv.Interface().(timestamppb.Timestamp).Nanos)) + err = EncodeJSONTime(w, t) if err != nil { return false, err } return true, nil case gDurationType: - d := rv.Interface().(durationpb.Duration) - err = EncodeJSONPBDuration(w, d) + d := time.Duration(rv.Interface().(durationpb.Duration).Seconds) * time.Second + d += time.Duration(rv.Interface().(durationpb.Duration).Nanos) + err = EncodeJSONDuration(w, d) if err != nil { return false, err } @@ -301,7 +305,8 @@ func decodeReflectJSONWellKnown(bz []byte, info *TypeInfo, rv reflect.Value, fop if err != nil { return false, err } - rv.Set(reflect.ValueOf(t)) + rv.FieldByName("Seconds").Set(reflect.ValueOf(t.Seconds)) + rv.FieldByName("Nanos").Set(reflect.ValueOf(t.Nanos)) return true, nil case gDurationType: var d durationpb.Duration @@ -309,7 +314,8 @@ func decodeReflectJSONWellKnown(bz []byte, info *TypeInfo, rv reflect.Value, fop if err != nil { return false, err } - rv.Set(reflect.ValueOf(d)) + rv.FieldByName("Seconds").Set(reflect.ValueOf(d.Seconds)) + rv.FieldByName("Nanos").Set(reflect.ValueOf(d.Nanos)) return true, nil // TODO: port each below to above without proto dependency // for unmarshaling code, to minimize dependencies. @@ -427,7 +433,7 @@ func EncodeJSONTime(w io.Writer, t time.Time) (err error) { return EncodeJSONTimeValue(w, t.Unix(), int32(t.Nanosecond())) } -func EncodeJSONPBTimestamp(w io.Writer, t timestamppb.Timestamp) (err error) { +func EncodeJSONPBTimestamp(w io.Writer, t *timestamppb.Timestamp) (err error) { return EncodeJSONTimeValue(w, t.GetSeconds(), t.GetNanos()) } @@ -457,7 +463,7 @@ func EncodeJSONDuration(w io.Writer, d time.Duration) (err error) { return EncodeJSONDurationValue(w, int64(d)/1e9, int32(int64(d)%1e9)) } -func EncodeJSONPBDuration(w io.Writer, d durationpb.Duration) (err error) { +func EncodeJSONPBDuration(w io.Writer, d *durationpb.Duration) (err error) { return EncodeJSONDurationValue(w, d.GetSeconds(), d.GetNanos()) } diff --git a/tm2/pkg/bft/abci/example/kvstore/helpers.go b/tm2/pkg/bft/abci/example/kvstore/helpers.go index b72b4da4778..c2a89fa20b3 100644 --- a/tm2/pkg/bft/abci/example/kvstore/helpers.go +++ b/tm2/pkg/bft/abci/example/kvstore/helpers.go @@ -11,7 +11,7 @@ import ( func RandVal(i int) abci.ValidatorUpdate { pubkey := ed25519.GenPrivKey().PubKey() power := random.RandUint16() + 1 - v := abci.ValidatorUpdate{pubkey.Address(), pubkey, int64(power)} + v := abci.ValidatorUpdate{Address: pubkey.Address(), PubKey: pubkey, Power: int64(power)} return v } diff --git a/tm2/pkg/bft/abci/example/kvstore/persistent_kvstore.go b/tm2/pkg/bft/abci/example/kvstore/persistent_kvstore.go index 01a8a3a8b8c..b6d096667ac 100644 --- a/tm2/pkg/bft/abci/example/kvstore/persistent_kvstore.go +++ b/tm2/pkg/bft/abci/example/kvstore/persistent_kvstore.go @@ -211,7 +211,7 @@ func (app *PersistentKVStoreApplication) execValidatorTx(tx []byte) (res abci.Re } // update - return app.updateValidator(abci.ValidatorUpdate{pubkey.Address(), pubkey, power}) + return app.updateValidator(abci.ValidatorUpdate{Address: pubkey.Address(), PubKey: pubkey, Power: power}) } // add, update, or remove a validator diff --git a/tm2/pkg/bft/consensus/state.go b/tm2/pkg/bft/consensus/state.go index 3f71dac368c..6faa40be20b 100644 --- a/tm2/pkg/bft/consensus/state.go +++ b/tm2/pkg/bft/consensus/state.go @@ -73,7 +73,7 @@ func (ti *timeoutInfo) GetHRS() cstypes.HRS { if ti == nil { return cstypes.HRS{} } else { - return cstypes.HRS{ti.Height, ti.Round, ti.Step} + return cstypes.HRS{Height: ti.Height, Round: ti.Round, Step: ti.Step} } } @@ -746,13 +746,13 @@ func (cs *ConsensusState) handleTimeout(ti timeoutInfo, rs cstypes.RoundState) { case cstypes.RoundStepNewRound: cs.enterPropose(ti.Height, 0) case cstypes.RoundStepPropose: - cs.evsw.FireEvent(cstypes.EventTimeoutPropose{cs.RoundState.GetHRS()}) + cs.evsw.FireEvent(cstypes.EventTimeoutPropose{HRS: cs.RoundState.GetHRS()}) cs.enterPrevote(ti.Height, ti.Round) case cstypes.RoundStepPrevoteWait: - cs.evsw.FireEvent(cstypes.EventTimeoutWait{cs.RoundState.GetHRS()}) + cs.evsw.FireEvent(cstypes.EventTimeoutWait{HRS: cs.RoundState.GetHRS()}) cs.enterPrecommit(ti.Height, ti.Round) case cstypes.RoundStepPrecommitWait: - cs.evsw.FireEvent(cstypes.EventTimeoutWait{cs.RoundState.GetHRS()}) + cs.evsw.FireEvent(cstypes.EventTimeoutWait{HRS: cs.RoundState.GetHRS()}) cs.enterPrecommit(ti.Height, ti.Round) cs.enterNewRound(ti.Height, ti.Round+1) default: @@ -1126,7 +1126,7 @@ func (cs *ConsensusState) enterPrecommit(height int64, round int) { } // At this point +2/3 prevoted for a particular block or nil. - cs.evsw.FireEvent(cstypes.EventPolka{cs.RoundState.GetHRS()}) + cs.evsw.FireEvent(cstypes.EventPolka{HRS: cs.RoundState.GetHRS()}) // the latest POLRound should be this round. polRound, _ := cs.Votes.POLInfo() @@ -1143,7 +1143,7 @@ func (cs *ConsensusState) enterPrecommit(height int64, round int) { cs.LockedRound = -1 cs.LockedBlock = nil cs.LockedBlockParts = nil - cs.evsw.FireEvent(cstypes.EventUnlock{cs.RoundState.GetHRS()}) + cs.evsw.FireEvent(cstypes.EventUnlock{HRS: cs.RoundState.GetHRS()}) } cs.signAddVote(types.PrecommitType, nil, types.PartSetHeader{}) return @@ -1155,7 +1155,7 @@ func (cs *ConsensusState) enterPrecommit(height int64, round int) { if cs.LockedBlock.HashesTo(blockID.Hash) { logger.Info("enterPrecommit: +2/3 prevoted locked block. Relocking") cs.LockedRound = round - cs.evsw.FireEvent(cstypes.EventRelock{cs.RoundState.GetHRS()}) + cs.evsw.FireEvent(cstypes.EventRelock{HRS: cs.RoundState.GetHRS()}) cs.signAddVote(types.PrecommitType, blockID.Hash, blockID.PartsHeader) return } @@ -1170,7 +1170,7 @@ func (cs *ConsensusState) enterPrecommit(height int64, round int) { cs.LockedRound = round cs.LockedBlock = cs.ProposalBlock cs.LockedBlockParts = cs.ProposalBlockParts - cs.evsw.FireEvent(cstypes.EventLock{cs.RoundState.GetHRS()}) + cs.evsw.FireEvent(cstypes.EventLock{HRS: cs.RoundState.GetHRS()}) cs.signAddVote(types.PrecommitType, blockID.Hash, blockID.PartsHeader) return } @@ -1186,7 +1186,7 @@ func (cs *ConsensusState) enterPrecommit(height int64, round int) { cs.ProposalBlock = nil cs.ProposalBlockParts = types.NewPartSetFromHeader(blockID.PartsHeader) } - cs.evsw.FireEvent(cstypes.EventUnlock{cs.RoundState.GetHRS()}) + cs.evsw.FireEvent(cstypes.EventUnlock{HRS: cs.RoundState.GetHRS()}) cs.signAddVote(types.PrecommitType, nil, types.PartSetHeader{}) } @@ -1591,7 +1591,7 @@ func (cs *ConsensusState) addVote(vote *types.Vote, peerID p2p.ID) (added bool, return } - cs.evsw.FireEvent(types.EventVote{vote}) + cs.evsw.FireEvent(types.EventVote{Vote: vote}) switch vote.Type { case types.PrevoteType: @@ -1620,7 +1620,7 @@ func (cs *ConsensusState) addVote(vote *types.Vote, peerID p2p.ID) (added bool, cs.LockedRound = -1 cs.LockedBlock = nil cs.LockedBlockParts = nil - cs.evsw.FireEvent(cstypes.EventUnlock{cs.RoundState.GetHRS()}) + cs.evsw.FireEvent(cstypes.EventUnlock{HRS: cs.RoundState.GetHRS()}) } // Update Valid* if we can. diff --git a/tm2/pkg/bft/consensus/wal_generator.go b/tm2/pkg/bft/consensus/wal_generator.go index fddcb4231e5..79c6e63c6a1 100644 --- a/tm2/pkg/bft/consensus/wal_generator.go +++ b/tm2/pkg/bft/consensus/wal_generator.go @@ -77,7 +77,7 @@ func (w *heightStopWAL) Write(m walm.WALMessage) error { } w.logger.Debug("WAL Write Message", "msg", m) - err := w.enc.Write(walm.TimedWALMessage{fixedTime, m}) + err := w.enc.Write(walm.TimedWALMessage{Time: fixedTime, Msg: m}) if err != nil { panic(fmt.Sprintf("failed to encode the msg %v", m)) } diff --git a/tm2/pkg/bft/types/params.go b/tm2/pkg/bft/types/params.go index 0b48da9329e..c2e8f304698 100644 --- a/tm2/pkg/bft/types/params.go +++ b/tm2/pkg/bft/types/params.go @@ -36,8 +36,8 @@ var validatorPubKeyTypeURLs = map[string]struct{}{ func DefaultConsensusParams() abci.ConsensusParams { return abci.ConsensusParams{ - DefaultBlockParams(), - DefaultValidatorParams(), + Block: DefaultBlockParams(), + Validator: DefaultValidatorParams(), } } @@ -51,7 +51,7 @@ func DefaultBlockParams() *abci.BlockParams { } func DefaultValidatorParams() *abci.ValidatorParams { - return &abci.ValidatorParams{[]string{ + return &abci.ValidatorParams{PubKeyTypeURLs: []string{ amino.GetTypeURL(ed25519.PubKeyEd25519{}), }} } diff --git a/tm2/pkg/bitarray/bit_array.go b/tm2/pkg/bitarray/bit_array.go index 2f7b184b938..a48c71a5650 100644 --- a/tm2/pkg/bitarray/bit_array.go +++ b/tm2/pkg/bitarray/bit_array.go @@ -394,8 +394,12 @@ func (bA *BitArray) UnmarshalJSON(bz []byte) error { if b == "null" { // This is required e.g. for encoding/json when decoding // into a pointer with pre-allocated BitArray. + bA.mtx.Lock() + defer bA.mtx.Unlock() + bA.Bits = 0 bA.Elems = nil + return nil } @@ -414,6 +418,12 @@ func (bA *BitArray) UnmarshalJSON(bz []byte) error { bA2.SetIndex(i, true) } } - *bA = *bA2 //nolint:govet + + bA.mtx.Lock() + defer bA.mtx.Unlock() + + bA.Bits = bA2.Bits + bA.Elems = bA2.Elems + return nil } diff --git a/tm2/pkg/crypto/hd/hdpath_test.go b/tm2/pkg/crypto/hd/hdpath_test.go index 31e806b2b1a..f79ee1151f7 100644 --- a/tm2/pkg/crypto/hd/hdpath_test.go +++ b/tm2/pkg/crypto/hd/hdpath_test.go @@ -17,7 +17,7 @@ func mnemonicToSeed(mnemonic string) []byte { return bip39.NewSeed(mnemonic, defaultBIP39Passphrase) } -func ExampleStringifyPathParams() { +func ExampleNewParams() { path := NewParams(44, 0, 0, false, 0) fmt.Println(path.String()) path = NewParams(44, 33, 7, true, 9) @@ -109,7 +109,7 @@ func TestParamsFromPath(t *testing.T) { } } -func ExampleSomeBIP32TestVecs() { +func ExampleDerivePrivateKeyForPath() { seed := mnemonicToSeed("barrel original fuel morning among eternal " + "filter ball stove pluck matrix mechanic") master, ch := ComputeMastersFromSeed(seed) diff --git a/tm2/pkg/crypto/keys/client/root.go b/tm2/pkg/crypto/keys/client/root.go index f69155ace85..8dcd9210a50 100644 --- a/tm2/pkg/crypto/keys/client/root.go +++ b/tm2/pkg/crypto/keys/client/root.go @@ -43,6 +43,7 @@ func NewRootCmdWithBaseConfig(io commands.IO, base BaseOptions) *commands.Comman NewExportCmd(cfg, io), NewImportCmd(cfg, io), NewListCmd(cfg, io), + NewRotateCmd(cfg, io), NewSignCmd(cfg, io), NewVerifyCmd(cfg, io), NewQueryCmd(cfg, io), diff --git a/tm2/pkg/crypto/keys/client/rotate.go b/tm2/pkg/crypto/keys/client/rotate.go new file mode 100644 index 00000000000..876e9f40b70 --- /dev/null +++ b/tm2/pkg/crypto/keys/client/rotate.go @@ -0,0 +1,75 @@ +package client + +import ( + "context" + "flag" + "fmt" + + "github.com/gnolang/gno/tm2/pkg/commands" + "github.com/gnolang/gno/tm2/pkg/crypto/keys" +) + +type RotateCfg struct { + RootCfg *BaseCfg + + Force bool +} + +func NewRotateCmd(rootCfg *BaseCfg, io commands.IO) *commands.Command { + cfg := &RotateCfg{ + RootCfg: rootCfg, + } + + return commands.NewCommand( + commands.Metadata{ + Name: "rotate", + ShortUsage: "rotate [flags] ", + ShortHelp: "rotate the password of a key in the keybase to a new password", + }, + cfg, + func(_ context.Context, args []string) error { + return execRotate(cfg, args, io) + }, + ) +} + +func (c *RotateCfg) RegisterFlags(fs *flag.FlagSet) { +} + +func execRotate(cfg *RotateCfg, args []string, io commands.IO) error { + if len(args) != 1 { + return flag.ErrHelp + } + + nameOrBech32 := args[0] + + kb, err := keys.NewKeyBaseFromDir(cfg.RootCfg.Home) + if err != nil { + return err + } + + oldpass, err := io.GetPassword("Enter the current password:", cfg.RootCfg.InsecurePasswordStdin) + if err != nil { + return err + } + + newpass, err := io.GetCheckPassword( + [2]string{ + "Enter the new password to encrypt your key to disk:", + "Repeat the password:", + }, + cfg.RootCfg.InsecurePasswordStdin, + ) + if err != nil { + return fmt.Errorf("unable to parse provided password, %w", err) + } + + getNewpass := func() (string, error) { return newpass, nil } + err = kb.Rotate(nameOrBech32, oldpass, getNewpass) + if err != nil { + return err + } + io.ErrPrintln("Password rotated") + + return nil +} diff --git a/tm2/pkg/crypto/keys/client/rotate_test.go b/tm2/pkg/crypto/keys/client/rotate_test.go new file mode 100644 index 00000000000..f365359d943 --- /dev/null +++ b/tm2/pkg/crypto/keys/client/rotate_test.go @@ -0,0 +1,95 @@ +package client + +import ( + "strings" + "testing" + + "github.com/gnolang/gno/tm2/pkg/commands" + "github.com/gnolang/gno/tm2/pkg/crypto/keys" + "github.com/gnolang/gno/tm2/pkg/testutils" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func Test_execRotate(t *testing.T) { + t.Parallel() + + // make new test dir + kbHome, kbCleanUp := testutils.NewTestCaseDir(t) + defer kbCleanUp() + + // initialize test options + cfg := &RotateCfg{ + RootCfg: &BaseCfg{ + BaseOptions: BaseOptions{ + Home: kbHome, + InsecurePasswordStdin: true, + }, + }, + } + + io := commands.NewTestIO() + + // Add test accounts to keybase. + kb, err := keys.NewKeyBaseFromDir(kbHome) + assert.NoError(t, err) + + keyName := "rotateApp_Key1" + p1, p2 := "1234", "foobar" + mnemonic := "equip will roof matter pink blind book anxiety banner elbow sun young" + + _, err = kb.CreateAccount(keyName, mnemonic, "", p1, 0, 0) + assert.NoError(t, err) + + { + // test: Key not found + args := []string{"blah"} + io.SetIn(strings.NewReader(p1 + "\n" + p2 + "\n" + p2 + "\n")) + err = execRotate(cfg, args, io) + require.Error(t, err) + require.Equal(t, "Key blah not found", err.Error()) + } + + { + // test: Wrong password + args := []string{keyName} + io.SetIn(strings.NewReader("blah" + "\n" + p2 + "\n" + p2 + "\n")) + err = execRotate(cfg, args, io) + require.Error(t, err) + require.Equal(t, "invalid account password", err.Error()) + } + + { + // test: New passwords don't match + args := []string{keyName} + io.SetIn(strings.NewReader(p1 + "\n" + p2 + "\n" + "blah" + "\n")) + err = execRotate(cfg, args, io) + require.Error(t, err) + require.Equal(t, "unable to parse provided password, passphrases don't match", err.Error()) + } + + { + // Rotate the password + args := []string{keyName} + io.SetIn(strings.NewReader(p1 + "\n" + p2 + "\n" + p2 + "\n")) + err = execRotate(cfg, args, io) + require.NoError(t, err) + } + + { + // test: The old password shouldn't work + args := []string{keyName} + io.SetIn(strings.NewReader(p1 + "\n" + p1 + "\n" + p1 + "\n")) + err = execRotate(cfg, args, io) + require.Error(t, err) + require.Equal(t, "invalid account password", err.Error()) + } + + { + // Updating the new password to itself should work + args := []string{keyName} + io.SetIn(strings.NewReader(p2 + "\n" + p2 + "\n" + p2 + "\n")) + err = execRotate(cfg, args, io) + require.NoError(t, err) + } +} diff --git a/tm2/pkg/crypto/keys/keybase.go b/tm2/pkg/crypto/keys/keybase.go index 2dc7d41be0b..ea3d0546fa0 100644 --- a/tm2/pkg/crypto/keys/keybase.go +++ b/tm2/pkg/crypto/keys/keybase.go @@ -115,33 +115,32 @@ func (kb dbKeybase) CreateLedger(name string, algo SigningAlgo, hrp string, acco pub := priv.PubKey() // Note: Once Cosmos App v1.3.1 is compulsory, it could be possible to check that pubkey and addr match - return kb.writeLedgerKey(name, pub, *hdPath), nil + return kb.writeLedgerKey(name, pub, *hdPath) } // CreateOffline creates a new reference to an offline keypair. It returns the // created key info. func (kb dbKeybase) CreateOffline(name string, pub crypto.PubKey) (Info, error) { - return kb.writeOfflineKey(name, pub), nil + return kb.writeOfflineKey(name, pub) } // CreateMulti creates a new reference to a multisig (offline) keypair. It // returns the created key info. func (kb dbKeybase) CreateMulti(name string, pub crypto.PubKey) (Info, error) { - return kb.writeMultisigKey(name, pub), nil + return kb.writeMultisigKey(name, pub) } -func (kb *dbKeybase) persistDerivedKey(seed []byte, passwd, name, fullHdPath string) (info Info, err error) { +func (kb *dbKeybase) persistDerivedKey(seed []byte, passwd, name, fullHdPath string) (Info, error) { // create master key and derive first key: masterPriv, ch := hd.ComputeMastersFromSeed(seed) derivedPriv, err := hd.DerivePrivateKeyForPath(masterPriv, ch, fullHdPath) if err != nil { - return + return nil, err } // use possibly blank password to encrypt the private // key and store it. User must enforce good passwords. - info = kb.writeLocalKey(name, secp256k1.PrivKeySecp256k1(derivedPriv), passwd) - return + return kb.writeLocalKey(name, secp256k1.PrivKeySecp256k1(derivedPriv), passwd) } // List returns the keys from storage in alphabetical order. @@ -441,13 +440,13 @@ func (kb dbKeybase) Delete(nameOrBech32, passphrase string, skipPass bool) error return nil } -// Update changes the passphrase with which an already stored key is +// Rotate changes the passphrase with which an already stored key is // encrypted. // // oldpass must be the current passphrase used for encryption, // getNewpass is a function to get the passphrase to permanently replace // the current passphrase -func (kb dbKeybase) Update(nameOrBech32, oldpass string, getNewpass func() (string, error)) error { +func (kb dbKeybase) Rotate(nameOrBech32, oldpass string, getNewpass func() (string, error)) error { info, err := kb.GetByNameOrAddress(nameOrBech32) if err != nil { return err @@ -475,41 +474,60 @@ func (kb dbKeybase) CloseDB() { kb.db.Close() } -func (kb dbKeybase) writeLocalKey(name string, priv crypto.PrivKey, passphrase string) Info { +func (kb dbKeybase) writeLocalKey(name string, priv crypto.PrivKey, passphrase string) (Info, error) { // encrypt private key using passphrase privArmor := armor.EncryptArmorPrivKey(priv, passphrase) // make Info pub := priv.PubKey() info := newLocalInfo(name, pub, privArmor) - kb.writeInfo(name, info) - return info + if err := kb.writeInfo(name, info); err != nil { + return nil, err + } + return info, nil } -func (kb dbKeybase) writeLedgerKey(name string, pub crypto.PubKey, path hd.BIP44Params) Info { +func (kb dbKeybase) writeLedgerKey(name string, pub crypto.PubKey, path hd.BIP44Params) (Info, error) { info := newLedgerInfo(name, pub, path) - kb.writeInfo(name, info) - return info + if err := kb.writeInfo(name, info); err != nil { + return nil, err + } + return info, nil } -func (kb dbKeybase) writeOfflineKey(name string, pub crypto.PubKey) Info { +func (kb dbKeybase) writeOfflineKey(name string, pub crypto.PubKey) (Info, error) { info := newOfflineInfo(name, pub) - kb.writeInfo(name, info) - return info + if err := kb.writeInfo(name, info); err != nil { + return nil, err + } + return info, nil } -func (kb dbKeybase) writeMultisigKey(name string, pub crypto.PubKey) Info { +func (kb dbKeybase) writeMultisigKey(name string, pub crypto.PubKey) (Info, error) { info := NewMultiInfo(name, pub) - kb.writeInfo(name, info) - return info + if err := kb.writeInfo(name, info); err != nil { + return nil, err + } + return info, nil } -func (kb dbKeybase) writeInfo(name string, info Info) { +func (kb dbKeybase) writeInfo(name string, info Info) error { // write the info by key key := infoKey(name) + oldInfob := kb.db.Get(key) + if len(oldInfob) > 0 { + // Enforce 1-to-1 name to address. Remove the lookup by the old address + oldInfo, err := readInfo(oldInfob) + if err != nil { + return err + } + kb.db.DeleteSync(addrKey(oldInfo.GetAddress())) + } + serializedInfo := writeInfo(info) kb.db.SetSync(key, serializedInfo) // store a pointer to the infokey by address for fast lookup kb.db.SetSync(addrKey(info.GetAddress()), key) + return nil } func addrKey(address crypto.Address) []byte { diff --git a/tm2/pkg/crypto/keys/keybase_test.go b/tm2/pkg/crypto/keys/keybase_test.go index 32cc8788b52..bfb21b46fad 100644 --- a/tm2/pkg/crypto/keys/keybase_test.go +++ b/tm2/pkg/crypto/keys/keybase_test.go @@ -111,6 +111,19 @@ func TestKeyManagement(t *testing.T) { require.NoError(t, err) require.Equal(t, 1, len(keyS)) + // Lookup by original i2 address + infoByAddress, err := cstore.GetByAddress(i2.GetAddress()) + require.NoError(t, err) + // GetByAddress should return Info with the corresponding public key + require.Equal(t, infoByAddress.GetPubKey(), i2.GetPubKey()) + // Replace n2 with a new address + mn2New := `fancy assault crane note start invite ladder ordinary gold amateur check cousin text mercy speak chuckle wine raw chief isolate swallow cushion wrist piece` + _, err = cstore.CreateAccount(n2, mn2New, bip39Passphrase, p2, 0, 0) + require.NoError(t, err) + // Check that CreateAccount removes the entry for the original address (public key) + _, err = cstore.GetByAddress(i2.GetAddress()) + require.NotNil(t, err) + // addr cache gets nuked - and test skip flag err = cstore.Delete(n2, "", true) require.NoError(t, err) @@ -199,9 +212,9 @@ func assertPassword(t *testing.T, cstore Keybase, name, pass, badpass string) { t.Helper() getNewpass := func() (string, error) { return pass, nil } - err := cstore.Update(name, badpass, getNewpass) + err := cstore.Rotate(name, badpass, getNewpass) require.NotNil(t, err) - err = cstore.Update(name, pass, getNewpass) + err = cstore.Rotate(name, pass, getNewpass) require.Nil(t, err, "%+v", err) } @@ -280,7 +293,7 @@ func TestExportImportPubKey(t *testing.T) { require.NotNil(t, err) } -// TestAdvancedKeyManagement verifies update, import, export functionality +// TestAdvancedKeyManagement verifies rotate, import, export functionality func TestAdvancedKeyManagement(t *testing.T) { t.Parallel() @@ -297,14 +310,14 @@ func TestAdvancedKeyManagement(t *testing.T) { require.Nil(t, err, "%+v", err) assertPassword(t, cstore, n1, p1, p2) - // update password requires the existing password + // rotate password requires the existing password getNewpass := func() (string, error) { return p2, nil } - err = cstore.Update(n1, "jkkgkg", getNewpass) + err = cstore.Rotate(n1, "jkkgkg", getNewpass) require.NotNil(t, err) assertPassword(t, cstore, n1, p1, p2) // then it changes the password when correct - err = cstore.Update(n1, p1, getNewpass) + err = cstore.Rotate(n1, p1, getNewpass) require.NoError(t, err) // p2 is now the proper one! assertPassword(t, cstore, n1, p2, p1) diff --git a/tm2/pkg/crypto/keys/lazy_keybase.go b/tm2/pkg/crypto/keys/lazy_keybase.go index eb9c0f3b551..38cec501135 100644 --- a/tm2/pkg/crypto/keys/lazy_keybase.go +++ b/tm2/pkg/crypto/keys/lazy_keybase.go @@ -179,14 +179,14 @@ func (lkb lazyKeybase) CreateMulti(name string, pubkey crypto.PubKey) (info Info return NewDBKeybase(db).CreateMulti(name, pubkey) } -func (lkb lazyKeybase) Update(name, oldpass string, getNewpass func() (string, error)) error { +func (lkb lazyKeybase) Rotate(name, oldpass string, getNewpass func() (string, error)) error { db, err := db.NewDB(lkb.name, dbBackend, lkb.dir) if err != nil { return err } defer db.Close() - return NewDBKeybase(db).Update(name, oldpass, getNewpass) + return NewDBKeybase(db).Rotate(name, oldpass, getNewpass) } func (lkb lazyKeybase) Import(name string, armor string) (err error) { diff --git a/tm2/pkg/crypto/keys/types.go b/tm2/pkg/crypto/keys/types.go index c5d33023a0a..3865951168e 100644 --- a/tm2/pkg/crypto/keys/types.go +++ b/tm2/pkg/crypto/keys/types.go @@ -43,7 +43,7 @@ type Keybase interface { CreateMulti(name string, pubkey crypto.PubKey) (info Info, err error) // The following operations will *only* work on locally-stored keys - Update(name, oldpass string, getNewpass func() (string, error)) error + Rotate(name, oldpass string, getNewpass func() (string, error)) error Import(name string, armor string) (err error) ImportPrivKey(name, armor, decryptPassphrase, encryptPassphrase string) error ImportPrivKeyUnsafe(name, armor, encryptPassphrase string) error diff --git a/tm2/pkg/db/boltdb/boltdb.go b/tm2/pkg/db/boltdb/boltdb.go index c35e3bb00e1..12aa20b8ce2 100644 --- a/tm2/pkg/db/boltdb/boltdb.go +++ b/tm2/pkg/db/boltdb/boltdb.go @@ -170,13 +170,13 @@ func (bdb *BoltDB) NewBatch() db.Batch { // It is safe to modify the contents of the argument after Set returns but not // before. func (bdb *boltDBBatch) Set(key, value []byte) { - bdb.ops = append(bdb.ops, internal.Operation{internal.OpTypeSet, key, value}) + bdb.ops = append(bdb.ops, internal.Operation{OpType: internal.OpTypeSet, Key: key, Value: value}) } // It is safe to modify the contents of the argument after Delete returns but // not before. func (bdb *boltDBBatch) Delete(key []byte) { - bdb.ops = append(bdb.ops, internal.Operation{internal.OpTypeDelete, key, nil}) + bdb.ops = append(bdb.ops, internal.Operation{OpType: internal.OpTypeDelete, Key: key}) } // NOTE: the operation is synchronous (see BoltDB for reasons) diff --git a/tm2/pkg/db/memdb/mem_db.go b/tm2/pkg/db/memdb/mem_db.go index 09b90b6be44..d39a9838cef 100644 --- a/tm2/pkg/db/memdb/mem_db.go +++ b/tm2/pkg/db/memdb/mem_db.go @@ -150,7 +150,7 @@ func (db *MemDB) NewBatch() dbm.Batch { db.mtx.Lock() defer db.mtx.Unlock() - return &internal.MemBatch{db, nil} + return &internal.MemBatch{DB: db} } // ---------------------------------------- diff --git a/tm2/pkg/libtm/messages/types/messages.pb.go b/tm2/pkg/libtm/messages/types/messages.pb.go deleted file mode 100644 index 5e09d2a1a11..00000000000 --- a/tm2/pkg/libtm/messages/types/messages.pb.go +++ /dev/null @@ -1,543 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.28.1 -// protoc v4.25.3 -// source: messages/types/proto/messages.proto - -package types - -import ( - reflect "reflect" - sync "sync" - - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// MessageType defines the types of messages -// that are related to the consensus process -type MessageType int32 - -const ( - MessageType_PROPOSAL MessageType = 0 - MessageType_PREVOTE MessageType = 1 - MessageType_PRECOMMIT MessageType = 2 -) - -// Enum value maps for MessageType. -var ( - MessageType_name = map[int32]string{ - 0: "PROPOSAL", - 1: "PREVOTE", - 2: "PRECOMMIT", - } - MessageType_value = map[string]int32{ - "PROPOSAL": 0, - "PREVOTE": 1, - "PRECOMMIT": 2, - } -) - -func (x MessageType) Enum() *MessageType { - p := new(MessageType) - *p = x - return p -} - -func (x MessageType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (MessageType) Descriptor() protoreflect.EnumDescriptor { - return file_messages_types_proto_messages_proto_enumTypes[0].Descriptor() -} - -func (MessageType) Type() protoreflect.EnumType { - return &file_messages_types_proto_messages_proto_enumTypes[0] -} - -func (x MessageType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use MessageType.Descriptor instead. -func (MessageType) EnumDescriptor() ([]byte, []int) { - return file_messages_types_proto_messages_proto_rawDescGZIP(), []int{0} -} - -// View is the consensus state associated with the message -type View struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // height represents the number of the proposal - Height uint64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` - // round represents the round number within a - // specific height (starts from 0) - Round uint64 `protobuf:"varint,2,opt,name=round,proto3" json:"round,omitempty"` -} - -func (x *View) Reset() { - *x = View{} - if protoimpl.UnsafeEnabled { - mi := &file_messages_types_proto_messages_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *View) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*View) ProtoMessage() {} - -func (x *View) ProtoReflect() protoreflect.Message { - mi := &file_messages_types_proto_messages_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use View.ProtoReflect.Descriptor instead. -func (*View) Descriptor() ([]byte, []int) { - return file_messages_types_proto_messages_proto_rawDescGZIP(), []int{0} -} - -func (x *View) GetHeight() uint64 { - if x != nil { - return x.Height - } - return 0 -} - -func (x *View) GetRound() uint64 { - if x != nil { - return x.Round - } - return 0 -} - -// ProposalMessage is the message containing -// the consensus proposal for the view -// -type ProposalMessage struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // view is the current view for the message - // (the view in which the message was sent) - View *View `protobuf:"bytes,1,opt,name=view,proto3" json:"view,omitempty"` - // sender is the message sender (unique identifier) - Sender []byte `protobuf:"bytes,2,opt,name=sender,proto3" json:"sender,omitempty"` - // signature is the message signature of the sender - Signature []byte `protobuf:"bytes,3,opt,name=signature,proto3" json:"signature,omitempty"` - // proposal is the actual consensus proposal - Proposal []byte `protobuf:"bytes,4,opt,name=proposal,proto3" json:"proposal,omitempty"` - // proposalRound is the round associated with the - // proposal in the PROPOSE message. - // NOTE: this round value DOES NOT have - // to match the message view (proposal from an earlier round) - ProposalRound int64 `protobuf:"varint,5,opt,name=proposalRound,proto3" json:"proposalRound,omitempty"` -} - -func (x *ProposalMessage) Reset() { - *x = ProposalMessage{} - if protoimpl.UnsafeEnabled { - mi := &file_messages_types_proto_messages_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ProposalMessage) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ProposalMessage) ProtoMessage() {} - -func (x *ProposalMessage) ProtoReflect() protoreflect.Message { - mi := &file_messages_types_proto_messages_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ProposalMessage.ProtoReflect.Descriptor instead. -func (*ProposalMessage) Descriptor() ([]byte, []int) { - return file_messages_types_proto_messages_proto_rawDescGZIP(), []int{1} -} - -func (x *ProposalMessage) GetView() *View { - if x != nil { - return x.View - } - return nil -} - -func (x *ProposalMessage) GetSender() []byte { - if x != nil { - return x.Sender - } - return nil -} - -func (x *ProposalMessage) GetSignature() []byte { - if x != nil { - return x.Signature - } - return nil -} - -func (x *ProposalMessage) GetProposal() []byte { - if x != nil { - return x.Proposal - } - return nil -} - -func (x *ProposalMessage) GetProposalRound() int64 { - if x != nil { - return x.ProposalRound - } - return 0 -} - -// PrevoteMessage is the message -// containing the consensus proposal prevote. -// The prevote message is pretty light, -// apart from containing the view, it just -// contains a unique identifier of the proposal -// for which this prevote is meant for (ex. proposal hash) -// -type PrevoteMessage struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // view is the current view for the message - // (the view in which the message was sent) - View *View `protobuf:"bytes,1,opt,name=view,proto3" json:"view,omitempty"` - // sender is the message sender (unique identifier) - Sender []byte `protobuf:"bytes,2,opt,name=sender,proto3" json:"sender,omitempty"` - // signature is the message signature of the sender - Signature []byte `protobuf:"bytes,3,opt,name=signature,proto3" json:"signature,omitempty"` - // identifier is the unique identifier for - // the proposal associated with this - // prevote message (ex. proposal hash) - Identifier []byte `protobuf:"bytes,4,opt,name=identifier,proto3" json:"identifier,omitempty"` -} - -func (x *PrevoteMessage) Reset() { - *x = PrevoteMessage{} - if protoimpl.UnsafeEnabled { - mi := &file_messages_types_proto_messages_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PrevoteMessage) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PrevoteMessage) ProtoMessage() {} - -func (x *PrevoteMessage) ProtoReflect() protoreflect.Message { - mi := &file_messages_types_proto_messages_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PrevoteMessage.ProtoReflect.Descriptor instead. -func (*PrevoteMessage) Descriptor() ([]byte, []int) { - return file_messages_types_proto_messages_proto_rawDescGZIP(), []int{2} -} - -func (x *PrevoteMessage) GetView() *View { - if x != nil { - return x.View - } - return nil -} - -func (x *PrevoteMessage) GetSender() []byte { - if x != nil { - return x.Sender - } - return nil -} - -func (x *PrevoteMessage) GetSignature() []byte { - if x != nil { - return x.Signature - } - return nil -} - -func (x *PrevoteMessage) GetIdentifier() []byte { - if x != nil { - return x.Identifier - } - return nil -} - -// PrecommitMessage is the message -// containing the consensus proposal precommit. -// The precommit message, same as the prevote message, -// contains a unique identifier for the proposal -// for which this precommit is meant for (ex. proposal hash) -// -type PrecommitMessage struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // view is the current view for the message - // (the view in which the message was sent) - View *View `protobuf:"bytes,1,opt,name=view,proto3" json:"view,omitempty"` - // sender is the message sender (unique identifier) - Sender []byte `protobuf:"bytes,2,opt,name=sender,proto3" json:"sender,omitempty"` - // signature is the message signature of the sender - Signature []byte `protobuf:"bytes,3,opt,name=signature,proto3" json:"signature,omitempty"` - // identifier is the unique identifier for - // the proposal associated with this - // precommit message (ex. proposal hash) - Identifier []byte `protobuf:"bytes,4,opt,name=identifier,proto3" json:"identifier,omitempty"` -} - -func (x *PrecommitMessage) Reset() { - *x = PrecommitMessage{} - if protoimpl.UnsafeEnabled { - mi := &file_messages_types_proto_messages_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PrecommitMessage) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PrecommitMessage) ProtoMessage() {} - -func (x *PrecommitMessage) ProtoReflect() protoreflect.Message { - mi := &file_messages_types_proto_messages_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PrecommitMessage.ProtoReflect.Descriptor instead. -func (*PrecommitMessage) Descriptor() ([]byte, []int) { - return file_messages_types_proto_messages_proto_rawDescGZIP(), []int{3} -} - -func (x *PrecommitMessage) GetView() *View { - if x != nil { - return x.View - } - return nil -} - -func (x *PrecommitMessage) GetSender() []byte { - if x != nil { - return x.Sender - } - return nil -} - -func (x *PrecommitMessage) GetSignature() []byte { - if x != nil { - return x.Signature - } - return nil -} - -func (x *PrecommitMessage) GetIdentifier() []byte { - if x != nil { - return x.Identifier - } - return nil -} - -var File_messages_types_proto_messages_proto protoreflect.FileDescriptor - -var file_messages_types_proto_messages_proto_rawDesc = []byte{ - 0x0a, 0x23, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x34, 0x0a, 0x04, 0x56, 0x69, 0x65, 0x77, 0x12, 0x16, 0x0a, - 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x68, - 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x22, 0xa4, 0x01, 0x0a, 0x0f, - 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, - 0x19, 0x0a, 0x04, 0x76, 0x69, 0x65, 0x77, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x05, 0x2e, - 0x56, 0x69, 0x65, 0x77, 0x52, 0x04, 0x76, 0x69, 0x65, 0x77, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, - 0x6e, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x65, 0x6e, 0x64, - 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x12, 0x24, 0x0a, 0x0d, - 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x52, 0x6f, 0x75, - 0x6e, 0x64, 0x22, 0x81, 0x01, 0x0a, 0x0e, 0x50, 0x72, 0x65, 0x76, 0x6f, 0x74, 0x65, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x19, 0x0a, 0x04, 0x76, 0x69, 0x65, 0x77, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x05, 0x2e, 0x56, 0x69, 0x65, 0x77, 0x52, 0x04, 0x76, 0x69, 0x65, 0x77, - 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x66, 0x69, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x69, 0x64, 0x65, 0x6e, - 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x22, 0x83, 0x01, 0x0a, 0x10, 0x50, 0x72, 0x65, 0x63, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x19, 0x0a, 0x04, 0x76, - 0x69, 0x65, 0x77, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x05, 0x2e, 0x56, 0x69, 0x65, 0x77, - 0x52, 0x04, 0x76, 0x69, 0x65, 0x77, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x12, 0x1c, - 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x1e, 0x0a, 0x0a, - 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x2a, 0x37, 0x0a, 0x0b, - 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0c, 0x0a, 0x08, 0x50, - 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x52, 0x45, - 0x56, 0x4f, 0x54, 0x45, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x50, 0x52, 0x45, 0x43, 0x4f, 0x4d, - 0x4d, 0x49, 0x54, 0x10, 0x02, 0x42, 0x11, 0x5a, 0x0f, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x73, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_messages_types_proto_messages_proto_rawDescOnce sync.Once - file_messages_types_proto_messages_proto_rawDescData = file_messages_types_proto_messages_proto_rawDesc -) - -func file_messages_types_proto_messages_proto_rawDescGZIP() []byte { - file_messages_types_proto_messages_proto_rawDescOnce.Do(func() { - file_messages_types_proto_messages_proto_rawDescData = protoimpl.X.CompressGZIP(file_messages_types_proto_messages_proto_rawDescData) - }) - return file_messages_types_proto_messages_proto_rawDescData -} - -var file_messages_types_proto_messages_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_messages_types_proto_messages_proto_msgTypes = make([]protoimpl.MessageInfo, 4) -var file_messages_types_proto_messages_proto_goTypes = []interface{}{ - (MessageType)(0), // 0: MessageType - (*View)(nil), // 1: View - (*ProposalMessage)(nil), // 2: ProposalMessage - (*PrevoteMessage)(nil), // 3: PrevoteMessage - (*PrecommitMessage)(nil), // 4: PrecommitMessage -} -var file_messages_types_proto_messages_proto_depIdxs = []int32{ - 1, // 0: ProposalMessage.view:type_name -> View - 1, // 1: PrevoteMessage.view:type_name -> View - 1, // 2: PrecommitMessage.view:type_name -> View - 3, // [3:3] is the sub-list for method output_type - 3, // [3:3] is the sub-list for method input_type - 3, // [3:3] is the sub-list for extension type_name - 3, // [3:3] is the sub-list for extension extendee - 0, // [0:3] is the sub-list for field type_name -} - -func init() { file_messages_types_proto_messages_proto_init() } -func file_messages_types_proto_messages_proto_init() { - if File_messages_types_proto_messages_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_messages_types_proto_messages_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*View); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_messages_types_proto_messages_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProposalMessage); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_messages_types_proto_messages_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PrevoteMessage); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_messages_types_proto_messages_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PrecommitMessage); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_messages_types_proto_messages_proto_rawDesc, - NumEnums: 1, - NumMessages: 4, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_messages_types_proto_messages_proto_goTypes, - DependencyIndexes: file_messages_types_proto_messages_proto_depIdxs, - EnumInfos: file_messages_types_proto_messages_proto_enumTypes, - MessageInfos: file_messages_types_proto_messages_proto_msgTypes, - }.Build() - File_messages_types_proto_messages_proto = out.File - file_messages_types_proto_messages_proto_rawDesc = nil - file_messages_types_proto_messages_proto_goTypes = nil - file_messages_types_proto_messages_proto_depIdxs = nil -} diff --git a/tm2/pkg/p2p/switch.go b/tm2/pkg/p2p/switch.go index cecfc21f3ef..b2de68e1ae3 100644 --- a/tm2/pkg/p2p/switch.go +++ b/tm2/pkg/p2p/switch.go @@ -219,7 +219,7 @@ func (sw *Switch) OnStop() { if t, ok := sw.transport.(TransportLifecycle); ok { err := t.Close() if err != nil { - sw.Logger.Error("Error stopping transport on stop: ", err) + sw.Logger.Error("Error stopping transport on stop: ", "error", err) } } diff --git a/tm2/pkg/sdk/auth/keeper.go b/tm2/pkg/sdk/auth/keeper.go index e43b5389844..7669b8ace73 100644 --- a/tm2/pkg/sdk/auth/keeper.go +++ b/tm2/pkg/sdk/auth/keeper.go @@ -31,11 +31,6 @@ func NewAccountKeeper( } } -// Logger returns a module-specific logger. -func (ak AccountKeeper) Logger(ctx sdk.Context) *slog.Logger { - return ctx.Logger().With("module", fmt.Sprintf("auth")) -} - // NewAccountWithAddress implements AccountKeeper. func (ak AccountKeeper) NewAccountWithAddress(ctx sdk.Context, addr crypto.Address) std.Account { acc := ak.proto() @@ -53,7 +48,12 @@ func (ak AccountKeeper) NewAccountWithAddress(ctx sdk.Context, addr crypto.Addre return acc } -// GetAccount implements AccountKeeper. +// Logger returns a module-specific logger. +func (ak AccountKeeper) Logger(ctx sdk.Context) *slog.Logger { + return ctx.Logger().With("module", ModuleName) +} + +// GetAccount returns a specific account in the AccountKeeper. func (ak AccountKeeper) GetAccount(ctx sdk.Context, addr crypto.Address) std.Account { stor := ctx.Store(ak.key) bz := stor.Get(AddressStoreKey(addr)) diff --git a/tm2/pkg/sdk/bank/keeper.go b/tm2/pkg/sdk/bank/keeper.go index 5d3699c99ef..f98e6b3e225 100644 --- a/tm2/pkg/sdk/bank/keeper.go +++ b/tm2/pkg/sdk/bank/keeper.go @@ -25,8 +25,8 @@ type BankKeeperI interface { var _ BankKeeperI = BankKeeper{} -// BBankKeeper only allows transfers between accounts without the possibility of -// creating coins. It implements the BankKeeper interface. +// BankKeeper only allows transfers between accounts without the possibility of +// creating coins. It implements the BankKeeperI interface. type BankKeeper struct { ViewKeeper diff --git a/tm2/pkg/sdk/bank/keeper_test.go b/tm2/pkg/sdk/bank/keeper_test.go index 59b4c12689c..df2039a682c 100644 --- a/tm2/pkg/sdk/bank/keeper_test.go +++ b/tm2/pkg/sdk/bank/keeper_test.go @@ -133,7 +133,7 @@ func TestBankKeeper(t *testing.T) { // validate coins with invalid denoms or negative values cannot be sent // NOTE: We must use the Coin literal as the constructor does not allow // negative values. - err = bank.SendCoins(ctx, addr, addr2, sdk.Coins{sdk.Coin{"FOOCOIN", -5}}) + err = bank.SendCoins(ctx, addr, addr2, sdk.Coins{sdk.Coin{Denom: "FOOCOIN", Amount: -5}}) require.Error(t, err) } diff --git a/tm2/pkg/sdk/baseapp.go b/tm2/pkg/sdk/baseapp.go index 671f18cf058..c11f81d852a 100644 --- a/tm2/pkg/sdk/baseapp.go +++ b/tm2/pkg/sdk/baseapp.go @@ -336,6 +336,7 @@ func (app *BaseApp) InitChain(req abci.RequestInitChain) (res abci.ResponseInitC app.deliverState.ctx = app.deliverState.ctx. WithBlockGasMeter(store.NewInfiniteGasMeter()) + // Run the set chain initializer res = app.initChainer(app.deliverState.ctx, req) // sanity check @@ -392,10 +393,6 @@ func (app *BaseApp) Query(req abci.RequestQuery) (res abci.ResponseQuery) { default: return handleQueryCustom(app, path, req) } - - msg := "unknown query path " + req.Path - res.Error = ABCIError(std.ErrUnknownRequest(msg)) - return } func handleQueryApp(app *BaseApp, path []string, req abci.RequestQuery) (res abci.ResponseQuery) { @@ -561,7 +558,9 @@ func (app *BaseApp) CheckTx(req abci.RequestCheckTx) (res abci.ResponseCheckTx) res.Error = ABCIError(std.ErrTxDecode(err.Error())) return } else { - result := app.runTx(RunTxModeCheck, req.Tx, tx) + ctx := app.getContextForTx(RunTxModeCheck, req.Tx) + + result := app.runTx(ctx, tx) res.ResponseBase = result.ResponseBase res.GasWanted = result.GasWanted res.GasUsed = result.GasUsed @@ -577,7 +576,9 @@ func (app *BaseApp) DeliverTx(req abci.RequestDeliverTx) (res abci.ResponseDeliv res.Error = ABCIError(std.ErrTxDecode(err.Error())) return } else { - result := app.runTx(RunTxModeDeliver, req.Tx, tx) + ctx := app.getContextForTx(RunTxModeDeliver, req.Tx) + + result := app.runTx(ctx, tx) res.ResponseBase = result.ResponseBase res.GasWanted = result.GasWanted res.GasUsed = result.GasUsed @@ -705,14 +706,17 @@ func (app *BaseApp) cacheTxContext(ctx Context) (Context, store.MultiStore) { // anteHandler. The provided txBytes may be nil in some cases, eg. in tests. For // further details on transaction execution, reference the BaseApp SDK // documentation. -func (app *BaseApp) runTx(mode RunTxMode, txBytes []byte, tx Tx) (result Result) { - // NOTE: GasWanted should be returned by the AnteHandler. GasUsed is - // determined by the GasMeter. We need access to the context to get the gas - // meter so we initialize upfront. - var gasWanted int64 +func (app *BaseApp) runTx(ctx Context, tx Tx) (result Result) { + var ( + // NOTE: GasWanted should be returned by the AnteHandler. GasUsed is + // determined by the GasMeter. We need access to the context to get the gas + // meter so we initialize upfront. + gasWanted int64 + + ms = ctx.MultiStore() + mode = ctx.Mode() + ) - ctx := app.getContextForTx(mode, txBytes) - ms := ctx.MultiStore() if mode == RunTxModeDeliver { gasleft := ctx.BlockGasMeter().Remaining() ctx = ctx.WithGasMeter(store.NewPassthroughGasMeter( diff --git a/tm2/pkg/sdk/baseapp_test.go b/tm2/pkg/sdk/baseapp_test.go index c8884533b30..08e8191170a 100644 --- a/tm2/pkg/sdk/baseapp_test.go +++ b/tm2/pkg/sdk/baseapp_test.go @@ -47,7 +47,7 @@ func newTxCounter(txInt int64, msgInts ...int64) std.Tx { msgs := make([]std.Msg, len(msgInts)) for i, msgInt := range msgInts { - msgs[i] = msgCounter{msgInt, false} + msgs[i] = msgCounter{Counter: msgInt, FailOnHandler: false} } tx := std.Tx{Msgs: msgs} @@ -120,13 +120,13 @@ func TestLoadVersion(t *testing.T) { header := &bft.Header{ChainID: "test-chain", Height: 1} app.BeginBlock(abci.RequestBeginBlock{Header: header}) res := app.Commit() - commitID1 := store.CommitID{1, res.Data} + commitID1 := store.CommitID{Version: 1, Hash: res.Data} // execute a block, collect commit ID header = &bft.Header{ChainID: "test-chain", Height: 2} app.BeginBlock(abci.RequestBeginBlock{Header: header}) res = app.Commit() - commitID2 := store.CommitID{2, res.Data} + commitID2 := store.CommitID{Version: 2, Hash: res.Data} // reload with LoadLatestVersion app = newBaseApp(name, db, pruningOpt) @@ -184,7 +184,7 @@ func TestLoadVersionInvalid(t *testing.T) { header := &bft.Header{ChainID: "test-chain", Height: 1} app.BeginBlock(abci.RequestBeginBlock{Header: header}) res := app.Commit() - commitID1 := store.CommitID{1, res.Data} + commitID1 := store.CommitID{Version: 1, Hash: res.Data} // create a new app with the stores mounted under the same cap key app = newBaseApp(name, db, pruningOpt) @@ -439,7 +439,7 @@ func setCounter(tx *Tx, counter int64) { func setFailOnHandler(tx *Tx, fail bool) { for i, msg := range tx.Msgs { - tx.Msgs[i] = msgCounter{msg.(msgCounter).Counter, fail} + tx.Msgs[i] = msgCounter{Counter: msg.(msgCounter).Counter, FailOnHandler: fail} } } @@ -676,8 +676,8 @@ func TestMultiMsgDeliverTx(t *testing.T) { // replace the second message with a msgCounter2 tx = newTxCounter(1, 3) - tx.Msgs = append(tx.Msgs, msgCounter2{0}) - tx.Msgs = append(tx.Msgs, msgCounter2{1}) + tx.Msgs = append(tx.Msgs, msgCounter2{Counter: 0}) + tx.Msgs = append(tx.Msgs, msgCounter2{Counter: 1}) txBytes, err = amino.Marshal(tx) require.NoError(t, err) res = app.DeliverTx(abci.RequestDeliverTx{Tx: txBytes}) diff --git a/tm2/pkg/sdk/helpers.go b/tm2/pkg/sdk/helpers.go index d61e8115671..ea5cdfea2da 100644 --- a/tm2/pkg/sdk/helpers.go +++ b/tm2/pkg/sdk/helpers.go @@ -10,17 +10,36 @@ import ( var isAlphaNumeric = regexp.MustCompile(`^[a-zA-Z0-9]+$`).MatchString func (app *BaseApp) Check(tx Tx) (result Result) { - return app.runTx(RunTxModeCheck, nil, tx) + ctx := app.getContextForTx(RunTxModeCheck, nil) + + return app.runTx(ctx, tx) } func (app *BaseApp) Simulate(txBytes []byte, tx Tx) (result Result) { - return app.runTx(RunTxModeSimulate, txBytes, tx) + ctx := app.getContextForTx(RunTxModeSimulate, txBytes) + + return app.runTx(ctx, tx) } -func (app *BaseApp) Deliver(tx Tx) (result Result) { - return app.runTx(RunTxModeDeliver, nil, tx) +func (app *BaseApp) Deliver(tx Tx, ctxFns ...ContextFn) (result Result) { + ctx := app.getContextForTx(RunTxModeDeliver, nil) + + for _, ctxFn := range ctxFns { + if ctxFn == nil { + continue + } + + ctx = ctxFn(ctx) + } + + return app.runTx(ctx, tx) } +// ContextFn is the custom execution context builder. +// It can be used to add custom metadata when replaying transactions +// during InitChainer or in the context of a unit test. +type ContextFn func(ctx Context) Context + // Context with current {check, deliver}State of the app // used by tests func (app *BaseApp) NewContext(mode RunTxMode, header abci.Header) Context { diff --git a/tm2/pkg/sdk/params/doc.go b/tm2/pkg/sdk/params/doc.go new file mode 100644 index 00000000000..a433b5eb115 --- /dev/null +++ b/tm2/pkg/sdk/params/doc.go @@ -0,0 +1,15 @@ +// Package params provides a lightweight implementation inspired by the x/params +// module of the Cosmos SDK. +// +// It includes a keeper for managing key-value pairs with module identifiers as +// prefixes, along with a global querier for retrieving any key from any module. +// +// Changes: This version removes the concepts of subspaces and proposals, +// allowing the creation of multiple keepers identified by a provided prefix. +// Proposals may be added later when governance modules are introduced. The +// transient store and .Modified helper have also been removed but can be +// implemented later if needed. Keys are represented as strings instead of +// []byte. +// +// XXX: removes isAlphaNum validation for keys. +package params diff --git a/tm2/pkg/sdk/params/handler.go b/tm2/pkg/sdk/params/handler.go new file mode 100644 index 00000000000..b662fc06c58 --- /dev/null +++ b/tm2/pkg/sdk/params/handler.go @@ -0,0 +1,79 @@ +package params + +import ( + "fmt" + "strings" + + abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" + "github.com/gnolang/gno/tm2/pkg/sdk" + "github.com/gnolang/gno/tm2/pkg/std" +) + +type paramsHandler struct { + params ParamsKeeper +} + +func NewHandler(params ParamsKeeper) paramsHandler { + return paramsHandler{ + params: params, + } +} + +func (bh paramsHandler) Process(ctx sdk.Context, msg std.Msg) sdk.Result { + errMsg := fmt.Sprintf("unrecognized params message type: %T", msg) + return abciResult(std.ErrUnknownRequest(errMsg)) +} + +//---------------------------------------- +// Query + +func (bh paramsHandler) Query(ctx sdk.Context, req abci.RequestQuery) (res abci.ResponseQuery) { + switch secondPart(req.Path) { + case bh.params.prefix: + return bh.queryParam(ctx, req) + default: + res = sdk.ABCIResponseQueryFromError( + std.ErrUnknownRequest("unknown params query endpoint")) + return + } +} + +// queryParam returns param for a key. +func (bh paramsHandler) queryParam(ctx sdk.Context, req abci.RequestQuery) (res abci.ResponseQuery) { + // parse key from path. + key := thirdPartWithSlashes(req.Path) + if key == "" { + res = sdk.ABCIResponseQueryFromError( + std.ErrUnknownRequest("param key is empty")) + } + + // XXX: validate? + + val := bh.params.GetRaw(ctx, key) + + res.Data = val + return +} + +//---------------------------------------- +// misc + +func abciResult(err error) sdk.Result { + return sdk.ABCIResultFromError(err) +} + +// returns the second component of a path. +func secondPart(path string) string { + parts := strings.SplitN(path, "/", 3) + if len(parts) < 2 { + return "" + } else { + return parts[1] + } +} + +// returns the third component of a path, including other slashes. +func thirdPartWithSlashes(path string) string { + split := strings.SplitN(path, "/", 3) + return split[2] +} diff --git a/tm2/pkg/sdk/params/handler_test.go b/tm2/pkg/sdk/params/handler_test.go new file mode 100644 index 00000000000..1fff5d007d3 --- /dev/null +++ b/tm2/pkg/sdk/params/handler_test.go @@ -0,0 +1,58 @@ +package params + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/require" + + abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" + bft "github.com/gnolang/gno/tm2/pkg/bft/types" + "github.com/gnolang/gno/tm2/pkg/sdk" + tu "github.com/gnolang/gno/tm2/pkg/sdk/testutils" +) + +func TestInvalidMsg(t *testing.T) { + t.Parallel() + + h := NewHandler(ParamsKeeper{}) + res := h.Process(sdk.NewContext(sdk.RunTxModeDeliver, nil, &bft.Header{ChainID: "test-chain"}, nil), tu.NewTestMsg()) + require.False(t, res.IsOK()) + require.True(t, strings.Contains(res.Log, "unrecognized params message type")) +} + +func TestQuery(t *testing.T) { + t.Parallel() + + env := setupTestEnv() + h := NewHandler(env.keeper) + + req := abci.RequestQuery{ + Path: "params/params_test/foo/bar.string", + } + + res := h.Query(env.ctx, req) + require.Nil(t, res.Error) + require.NotNil(t, res) + require.Nil(t, res.Data) + + env.keeper.SetString(env.ctx, "foo/bar.string", "baz") + + res = h.Query(env.ctx, req) + require.Nil(t, res.Error) + require.NotNil(t, res) + require.Equal(t, string(res.Data), `"baz"`) +} + +func TestQuerierRouteNotFound(t *testing.T) { + t.Parallel() + + env := setupTestEnv() + h := NewHandler(env.keeper) + req := abci.RequestQuery{ + Path: "params/notfound", + Data: []byte{}, + } + res := h.Query(env.ctx, req) + require.Error(t, res.Error) +} diff --git a/tm2/pkg/sdk/params/keeper.go b/tm2/pkg/sdk/params/keeper.go new file mode 100644 index 00000000000..ffeb1775acb --- /dev/null +++ b/tm2/pkg/sdk/params/keeper.go @@ -0,0 +1,157 @@ +package params + +import ( + "log/slog" + "strings" + + "github.com/gnolang/gno/tm2/pkg/amino" + "github.com/gnolang/gno/tm2/pkg/sdk" + "github.com/gnolang/gno/tm2/pkg/store" +) + +const ( + ModuleName = "params" + StoreKey = ModuleName +) + +type ParamsKeeperI interface { + GetString(ctx sdk.Context, key string, ptr *string) + GetInt64(ctx sdk.Context, key string, ptr *int64) + GetUint64(ctx sdk.Context, key string, ptr *uint64) + GetBool(ctx sdk.Context, key string, ptr *bool) + GetBytes(ctx sdk.Context, key string, ptr *[]byte) + + SetString(ctx sdk.Context, key string, value string) + SetInt64(ctx sdk.Context, key string, value int64) + SetUint64(ctx sdk.Context, key string, value uint64) + SetBool(ctx sdk.Context, key string, value bool) + SetBytes(ctx sdk.Context, key string, value []byte) + + Has(ctx sdk.Context, key string) bool + GetRaw(ctx sdk.Context, key string) []byte + + // XXX: ListKeys? +} + +var _ ParamsKeeperI = ParamsKeeper{} + +// global paramstore Keeper. +type ParamsKeeper struct { + key store.StoreKey + prefix string +} + +// NewParamsKeeper returns a new ParamsKeeper. +func NewParamsKeeper(key store.StoreKey, prefix string) ParamsKeeper { + return ParamsKeeper{ + key: key, + prefix: prefix, + } +} + +// Logger returns a module-specific logger. +// XXX: why do we expose this? +func (pk ParamsKeeper) Logger(ctx sdk.Context) *slog.Logger { + return ctx.Logger().With("module", ModuleName) +} + +func (pk ParamsKeeper) Has(ctx sdk.Context, key string) bool { + stor := ctx.Store(pk.key) + return stor.Has([]byte(key)) +} + +func (pk ParamsKeeper) GetRaw(ctx sdk.Context, key string) []byte { + stor := ctx.Store(pk.key) + return stor.Get([]byte(key)) +} + +func (pk ParamsKeeper) GetString(ctx sdk.Context, key string, ptr *string) { + checkSuffix(key, ".string") + pk.getIfExists(ctx, key, ptr) +} + +func (pk ParamsKeeper) GetBool(ctx sdk.Context, key string, ptr *bool) { + checkSuffix(key, ".bool") + pk.getIfExists(ctx, key, ptr) +} + +func (pk ParamsKeeper) GetInt64(ctx sdk.Context, key string, ptr *int64) { + checkSuffix(key, ".int64") + pk.getIfExists(ctx, key, ptr) +} + +func (pk ParamsKeeper) GetUint64(ctx sdk.Context, key string, ptr *uint64) { + checkSuffix(key, ".uint64") + pk.getIfExists(ctx, key, ptr) +} + +func (pk ParamsKeeper) GetBytes(ctx sdk.Context, key string, ptr *[]byte) { + checkSuffix(key, ".bytes") + pk.getIfExists(ctx, key, ptr) +} + +func (pk ParamsKeeper) SetString(ctx sdk.Context, key, value string) { + checkSuffix(key, ".string") + pk.set(ctx, key, value) +} + +func (pk ParamsKeeper) SetBool(ctx sdk.Context, key string, value bool) { + checkSuffix(key, ".bool") + pk.set(ctx, key, value) +} + +func (pk ParamsKeeper) SetInt64(ctx sdk.Context, key string, value int64) { + checkSuffix(key, ".int64") + pk.set(ctx, key, value) +} + +func (pk ParamsKeeper) SetUint64(ctx sdk.Context, key string, value uint64) { + checkSuffix(key, ".uint64") + pk.set(ctx, key, value) +} + +func (pk ParamsKeeper) SetBytes(ctx sdk.Context, key string, value []byte) { + checkSuffix(key, ".bytes") + pk.set(ctx, key, value) +} + +func (pk ParamsKeeper) getIfExists(ctx sdk.Context, key string, ptr interface{}) { + stor := ctx.Store(pk.key) + bz := stor.Get([]byte(key)) + if bz == nil { + return + } + err := amino.UnmarshalJSON(bz, ptr) + if err != nil { + panic(err) + } +} + +func (pk ParamsKeeper) get(ctx sdk.Context, key string, ptr interface{}) { + stor := ctx.Store(pk.key) + bz := stor.Get([]byte(key)) + err := amino.UnmarshalJSON(bz, ptr) + if err != nil { + panic(err) + } +} + +func (pk ParamsKeeper) set(ctx sdk.Context, key string, value interface{}) { + stor := ctx.Store(pk.key) + bz, err := amino.MarshalJSON(value) + if err != nil { + panic(err) + } + stor.Set([]byte(key), bz) +} + +func checkSuffix(key, expectedSuffix string) { + var ( + noSuffix = !strings.HasSuffix(key, expectedSuffix) + noName = len(key) == len(expectedSuffix) + // XXX: additional sanity checks? + ) + if noSuffix || noName { + panic(`key should be like "` + expectedSuffix + `"`) + } +} diff --git a/tm2/pkg/sdk/params/keeper_test.go b/tm2/pkg/sdk/params/keeper_test.go new file mode 100644 index 00000000000..45a97ae44ad --- /dev/null +++ b/tm2/pkg/sdk/params/keeper_test.go @@ -0,0 +1,142 @@ +package params + +import ( + "reflect" + "testing" + + "github.com/gnolang/gno/tm2/pkg/amino" + "github.com/stretchr/testify/require" +) + +func TestKeeper(t *testing.T) { + env := setupTestEnv() + ctx, store, keeper := env.ctx, env.store, env.keeper + _ = store // XXX: add store tests? + + require.False(t, keeper.Has(ctx, "param1.string")) + require.False(t, keeper.Has(ctx, "param2.bool")) + require.False(t, keeper.Has(ctx, "param3.uint64")) + require.False(t, keeper.Has(ctx, "param4.int64")) + require.False(t, keeper.Has(ctx, "param5.bytes")) + + // initial set + require.NotPanics(t, func() { keeper.SetString(ctx, "param1.string", "foo") }) + require.NotPanics(t, func() { keeper.SetBool(ctx, "param2.bool", true) }) + require.NotPanics(t, func() { keeper.SetUint64(ctx, "param3.uint64", 42) }) + require.NotPanics(t, func() { keeper.SetInt64(ctx, "param4.int64", -1337) }) + require.NotPanics(t, func() { keeper.SetBytes(ctx, "param5.bytes", []byte("hello world!")) }) + + require.True(t, keeper.Has(ctx, "param1.string")) + require.True(t, keeper.Has(ctx, "param2.bool")) + require.True(t, keeper.Has(ctx, "param3.uint64")) + require.True(t, keeper.Has(ctx, "param4.int64")) + require.True(t, keeper.Has(ctx, "param5.bytes")) + + var ( + param1 string + param2 bool + param3 uint64 + param4 int64 + param5 []byte + ) + + require.NotPanics(t, func() { keeper.GetString(ctx, "param1.string", ¶m1) }) + require.NotPanics(t, func() { keeper.GetBool(ctx, "param2.bool", ¶m2) }) + require.NotPanics(t, func() { keeper.GetUint64(ctx, "param3.uint64", ¶m3) }) + require.NotPanics(t, func() { keeper.GetInt64(ctx, "param4.int64", ¶m4) }) + require.NotPanics(t, func() { keeper.GetBytes(ctx, "param5.bytes", ¶m5) }) + + require.Equal(t, param1, "foo") + require.Equal(t, param2, true) + require.Equal(t, param3, uint64(42)) + require.Equal(t, param4, int64(-1337)) + require.Equal(t, param5, []byte("hello world!")) + + // reset + require.NotPanics(t, func() { keeper.SetString(ctx, "param1.string", "bar") }) + require.NotPanics(t, func() { keeper.SetBool(ctx, "param2.bool", false) }) + require.NotPanics(t, func() { keeper.SetUint64(ctx, "param3.uint64", 12345) }) + require.NotPanics(t, func() { keeper.SetInt64(ctx, "param4.int64", 1000) }) + require.NotPanics(t, func() { keeper.SetBytes(ctx, "param5.bytes", []byte("bye")) }) + + require.True(t, keeper.Has(ctx, "param1.string")) + require.True(t, keeper.Has(ctx, "param2.bool")) + require.True(t, keeper.Has(ctx, "param3.uint64")) + require.True(t, keeper.Has(ctx, "param4.int64")) + require.True(t, keeper.Has(ctx, "param5.bytes")) + + require.NotPanics(t, func() { keeper.GetString(ctx, "param1.string", ¶m1) }) + require.NotPanics(t, func() { keeper.GetBool(ctx, "param2.bool", ¶m2) }) + require.NotPanics(t, func() { keeper.GetUint64(ctx, "param3.uint64", ¶m3) }) + require.NotPanics(t, func() { keeper.GetInt64(ctx, "param4.int64", ¶m4) }) + require.NotPanics(t, func() { keeper.GetBytes(ctx, "param5.bytes", ¶m5) }) + + require.Equal(t, param1, "bar") + require.Equal(t, param2, false) + require.Equal(t, param3, uint64(12345)) + require.Equal(t, param4, int64(1000)) + require.Equal(t, param5, []byte("bye")) + + // invalid sets + require.PanicsWithValue(t, `key should be like ".string"`, func() { keeper.SetString(ctx, "invalid.int64", "hello") }) + require.PanicsWithValue(t, `key should be like ".int64"`, func() { keeper.SetInt64(ctx, "invalid.string", int64(42)) }) + require.PanicsWithValue(t, `key should be like ".uint64"`, func() { keeper.SetUint64(ctx, "invalid.int64", uint64(42)) }) + require.PanicsWithValue(t, `key should be like ".bool"`, func() { keeper.SetBool(ctx, "invalid.int64", true) }) + require.PanicsWithValue(t, `key should be like ".bytes"`, func() { keeper.SetBytes(ctx, "invalid.int64", []byte("hello")) }) +} + +// adapted from TestKeeperSubspace from Cosmos SDK, but adapted to a subspace-less Keeper. +func TestKeeper_internal(t *testing.T) { + env := setupTestEnv() + ctx, store, keeper := env.ctx, env.store, env.keeper + + kvs := []struct { + key string + param interface{} + zero interface{} + ptr interface{} + }{ + {"string", "test", "", new(string)}, + {"bool", true, false, new(bool)}, + {"int16", int16(1), int16(0), new(int16)}, + {"int32", int32(1), int32(0), new(int32)}, + {"int64", int64(1), int64(0), new(int64)}, + {"uint16", uint16(1), uint16(0), new(uint16)}, + {"uint32", uint32(1), uint32(0), new(uint32)}, + {"uint64", uint64(1), uint64(0), new(uint64)}, + {"struct", s{1}, s{0}, new(s)}, + } + + for i, kv := range kvs { + require.NotPanics(t, func() { keeper.set(ctx, kv.key, kv.param) }, "keeper.Set panics, tc #%d", i) + } + + for i, kv := range kvs { + require.NotPanics(t, func() { keeper.getIfExists(ctx, "invalid", kv.ptr) }, "keeper.GetIfExists panics when no value exists, tc #%d", i) + require.Equal(t, kv.zero, indirect(kv.ptr), "keeper.GetIfExists unmarshalls when no value exists, tc #%d", i) + require.Panics(t, func() { keeper.get(ctx, "invalid", kv.ptr) }, "invalid keeper.Get not panics when no value exists, tc #%d", i) + require.Equal(t, kv.zero, indirect(kv.ptr), "invalid keeper.Get unmarshalls when no value exists, tc #%d", i) + + require.NotPanics(t, func() { keeper.getIfExists(ctx, kv.key, kv.ptr) }, "keeper.GetIfExists panics, tc #%d", i) + require.Equal(t, kv.param, indirect(kv.ptr), "stored param not equal, tc #%d", i) + require.NotPanics(t, func() { keeper.get(ctx, kv.key, kv.ptr) }, "keeper.Get panics, tc #%d", i) + require.Equal(t, kv.param, indirect(kv.ptr), "stored param not equal, tc #%d", i) + + require.Panics(t, func() { keeper.get(ctx, "invalid", kv.ptr) }, "invalid keeper.Get not panics when no value exists, tc #%d", i) + require.Equal(t, kv.param, indirect(kv.ptr), "invalid keeper.Get unmarshalls when no value existt, tc #%d", i) + + require.Panics(t, func() { keeper.get(ctx, kv.key, nil) }, "invalid keeper.Get not panics when the pointer is nil, tc #%d", i) + } + + for i, kv := range kvs { + bz := store.Get([]byte(kv.key)) + require.NotNil(t, bz, "store.Get() returns nil, tc #%d", i) + err := amino.UnmarshalJSON(bz, kv.ptr) + require.NoError(t, err, "cdc.UnmarshalJSON() returns error, tc #%d", i) + require.Equal(t, kv.param, indirect(kv.ptr), "stored param not equal, tc #%d", i) + } +} + +type s struct{ I int } + +func indirect(ptr interface{}) interface{} { return reflect.ValueOf(ptr).Elem().Interface() } diff --git a/tm2/pkg/sdk/params/test_common.go b/tm2/pkg/sdk/params/test_common.go new file mode 100644 index 00000000000..8243ee867de --- /dev/null +++ b/tm2/pkg/sdk/params/test_common.go @@ -0,0 +1,46 @@ +package params + +import ( + abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" + bft "github.com/gnolang/gno/tm2/pkg/bft/types" + "github.com/gnolang/gno/tm2/pkg/db/memdb" + "github.com/gnolang/gno/tm2/pkg/log" + "github.com/gnolang/gno/tm2/pkg/sdk" + "github.com/gnolang/gno/tm2/pkg/store" + "github.com/gnolang/gno/tm2/pkg/store/iavl" +) + +type testEnv struct { + ctx sdk.Context + store store.Store + keeper ParamsKeeper +} + +func setupTestEnv() testEnv { + db := memdb.NewMemDB() + paramsCapKey := store.NewStoreKey("paramsCapKey") + ms := store.NewCommitMultiStore(db) + ms.MountStoreWithDB(paramsCapKey, iavl.StoreConstructor, db) + ms.LoadLatestVersion() + + prefix := "params_test" + keeper := NewParamsKeeper(paramsCapKey, prefix) + + ctx := sdk.NewContext(sdk.RunTxModeDeliver, ms, &bft.Header{Height: 1, ChainID: "test-chain-id"}, log.NewNoopLogger()) + // XXX: context key? + ctx = ctx.WithConsensusParams(&abci.ConsensusParams{ + Block: &abci.BlockParams{ + MaxTxBytes: 1024, + MaxDataBytes: 1024 * 100, + MaxBlockBytes: 1024 * 100, + MaxGas: 10 * 1000 * 1000, + TimeIotaMS: 10, + }, + Validator: &abci.ValidatorParams{ + PubKeyTypeURLs: []string{}, // XXX + }, + }) + + stor := ctx.Store(paramsCapKey) + return testEnv{ctx: ctx, store: stor, keeper: keeper} +} diff --git a/tm2/pkg/std/coin_benchmark_test.go b/tm2/pkg/std/coin_benchmark_test.go index 2d4d2f03890..3cb05612373 100644 --- a/tm2/pkg/std/coin_benchmark_test.go +++ b/tm2/pkg/std/coin_benchmark_test.go @@ -2,12 +2,10 @@ package std import ( "fmt" - "strconv" "testing" ) func BenchmarkCoinsAdditionIntersect(b *testing.B) { - b.Skip("TODO: panicking benchmark") benchmarkingFunc := func(numCoinsA int, numCoinsB int) func(b *testing.B) { return func(b *testing.B) { b.Helper() @@ -15,11 +13,16 @@ func BenchmarkCoinsAdditionIntersect(b *testing.B) { coinsA := Coins(make([]Coin, numCoinsA)) coinsB := Coins(make([]Coin, numCoinsB)) + maxCoins := max(numCoinsA, numCoinsB) + denomLength := len(fmt.Sprint(maxCoins)) + for i := 0; i < numCoinsA; i++ { - coinsA[i] = NewCoin("COINZ_"+strconv.Itoa(i), (int64(i))) + denom := fmt.Sprintf("coinz_%0*d", denomLength, i) + coinsA[i] = NewCoin(denom, int64(i+1)) } for i := 0; i < numCoinsB; i++ { - coinsB[i] = NewCoin("COINZ_"+strconv.Itoa(i), (int64(i))) + denom := fmt.Sprintf("coinz_%0*d", denomLength, i) + coinsB[i] = NewCoin(denom, int64(i+1)) } b.ResetTimer() @@ -39,7 +42,6 @@ func BenchmarkCoinsAdditionIntersect(b *testing.B) { } func BenchmarkCoinsAdditionNoIntersect(b *testing.B) { - b.Skip("TODO: panicking benchmark") benchmarkingFunc := func(numCoinsA int, numCoinsB int) func(b *testing.B) { return func(b *testing.B) { b.Helper() @@ -47,11 +49,16 @@ func BenchmarkCoinsAdditionNoIntersect(b *testing.B) { coinsA := Coins(make([]Coin, numCoinsA)) coinsB := Coins(make([]Coin, numCoinsB)) + maxCoins := max(numCoinsA, numCoinsB) + denomLength := len(fmt.Sprint(maxCoins)) + for i := 0; i < numCoinsA; i++ { - coinsA[i] = NewCoin("COINZ_"+strconv.Itoa(numCoinsB+i), (int64(i))) + denom := fmt.Sprintf("coinz_%0*d", denomLength, i) + coinsA[i] = NewCoin(denom, int64(i+1)) } for i := 0; i < numCoinsB; i++ { - coinsB[i] = NewCoin("COINZ_"+strconv.Itoa(i), (int64(i))) + denom := fmt.Sprintf("coinz_%0*d", denomLength, i) + coinsB[i] = NewCoin(denom, int64(i+1)) } b.ResetTimer() diff --git a/tm2/pkg/std/package.go b/tm2/pkg/std/package.go index 76e1f9fc4ad..3f71c69f0ce 100644 --- a/tm2/pkg/std/package.go +++ b/tm2/pkg/std/package.go @@ -13,10 +13,6 @@ var Package = amino.RegisterPackage(amino.NewPackage( // Account &BaseAccount{}, "BaseAccount", - // MemFile/MemPackage - MemFile{}, "MemFile", - MemPackage{}, "MemPackage", - // Errors InternalError{}, "InternalError", TxDecodeError{}, "TxDecodeError", diff --git a/tm2/pkg/std/std.proto b/tm2/pkg/std/std.proto index 2fad1eeff38..ead6dcf0113 100644 --- a/tm2/pkg/std/std.proto +++ b/tm2/pkg/std/std.proto @@ -15,17 +15,6 @@ message BaseAccount { uint64 sequence = 5; } -message MemFile { - string name = 1 [json_name = "Name"]; - string body = 2 [json_name = "Body"]; -} - -message MemPackage { - string name = 1 [json_name = "Name"]; - string path = 2 [json_name = "Path"]; - repeated MemFile files = 3 [json_name = "Files"]; -} - message InternalError { } diff --git a/tm2/pkg/store/README.md b/tm2/pkg/store/README.md index abf5c26bc07..24ae0c805ac 100644 --- a/tm2/pkg/store/README.md +++ b/tm2/pkg/store/README.md @@ -116,15 +116,3 @@ type traceOperation struct { ``` `traceOperation.Metadata` is filled with `Store.context` when it is not nil. `TraceContext` is a `map[string]interface{}`. - -## Transient - -`transient.Store` is a base-layer `KVStore` which is automatically discarded at the end of the block. - -```go -type Store struct { - dbadapter.Store -} -``` - -`Store.Store` is a `dbadapter.Store` with a `memdb.NewMemDB()`. All `KVStore` methods are reused. When `Store.Commit()` is called, new `dbadapter.Store` is assigned, discarding previous reference and making it garbage collected. diff --git a/tm2/pkg/store/cache/store_test.go b/tm2/pkg/store/cache/store_test.go index 4ac8cc64de9..1caf51ea52c 100644 --- a/tm2/pkg/store/cache/store_test.go +++ b/tm2/pkg/store/cache/store_test.go @@ -15,7 +15,7 @@ import ( ) func newCacheStore() types.Store { - mem := dbadapter.Store{memdb.NewMemDB()} + mem := dbadapter.Store{DB: memdb.NewMemDB()} return cache.New(mem) } @@ -25,7 +25,7 @@ func valFmt(i int) []byte { return bz(fmt.Sprintf("value%0.8d", i)) } func TestCacheStore(t *testing.T) { t.Parallel() - mem := dbadapter.Store{memdb.NewMemDB()} + mem := dbadapter.Store{DB: memdb.NewMemDB()} st := cache.New(mem) require.Empty(t, st.Get(keyFmt(1)), "Expected `key1` to be empty") @@ -70,7 +70,7 @@ func TestCacheStore(t *testing.T) { func TestCacheStoreNoNilSet(t *testing.T) { t.Parallel() - mem := dbadapter.Store{memdb.NewMemDB()} + mem := dbadapter.Store{DB: memdb.NewMemDB()} st := cache.New(mem) require.Panics(t, func() { st.Set([]byte("key"), nil) }, "setting a nil value should panic") } @@ -78,7 +78,7 @@ func TestCacheStoreNoNilSet(t *testing.T) { func TestCacheStoreNested(t *testing.T) { t.Parallel() - mem := dbadapter.Store{memdb.NewMemDB()} + mem := dbadapter.Store{DB: memdb.NewMemDB()} st := cache.New(mem) // set. check its there on st and not on mem. diff --git a/tm2/pkg/store/gas/store_test.go b/tm2/pkg/store/gas/store_test.go index 5b8cc7c656c..52c8dbf08e8 100644 --- a/tm2/pkg/store/gas/store_test.go +++ b/tm2/pkg/store/gas/store_test.go @@ -20,7 +20,7 @@ func valFmt(i int) []byte { return bz(fmt.Sprintf("value%0.8d", i)) } func TestGasKVStoreBasic(t *testing.T) { t.Parallel() - mem := dbadapter.Store{memdb.NewMemDB()} + mem := dbadapter.Store{DB: memdb.NewMemDB()} meter := types.NewGasMeter(10000) st := gas.New(mem, meter, types.DefaultGasConfig()) require.Empty(t, st.Get(keyFmt(1)), "Expected `key1` to be empty") @@ -34,7 +34,7 @@ func TestGasKVStoreBasic(t *testing.T) { func TestGasKVStoreIterator(t *testing.T) { t.Parallel() - mem := dbadapter.Store{memdb.NewMemDB()} + mem := dbadapter.Store{DB: memdb.NewMemDB()} meter := types.NewGasMeter(10000) st := gas.New(mem, meter, types.DefaultGasConfig()) require.Empty(t, st.Get(keyFmt(1)), "Expected `key1` to be empty") @@ -60,7 +60,7 @@ func TestGasKVStoreIterator(t *testing.T) { func TestGasKVStoreOutOfGasSet(t *testing.T) { t.Parallel() - mem := dbadapter.Store{memdb.NewMemDB()} + mem := dbadapter.Store{DB: memdb.NewMemDB()} meter := types.NewGasMeter(0) st := gas.New(mem, meter, types.DefaultGasConfig()) require.Panics(t, func() { st.Set(keyFmt(1), valFmt(1)) }, "Expected out-of-gas") @@ -69,7 +69,7 @@ func TestGasKVStoreOutOfGasSet(t *testing.T) { func TestGasKVStoreOutOfGasIterator(t *testing.T) { t.Parallel() - mem := dbadapter.Store{memdb.NewMemDB()} + mem := dbadapter.Store{DB: memdb.NewMemDB()} meter := types.NewGasMeter(20000) st := gas.New(mem, meter, types.DefaultGasConfig()) st.Set(keyFmt(1), valFmt(1)) diff --git a/tm2/pkg/store/iavl/store_test.go b/tm2/pkg/store/iavl/store_test.go index 6959e9172dc..9157394cb08 100644 --- a/tm2/pkg/store/iavl/store_test.go +++ b/tm2/pkg/store/iavl/store_test.go @@ -46,7 +46,7 @@ func newAlohaTree(t *testing.T, db dbm.DB) (*iavl.MutableTree, types.CommitID) { } hash, ver, err := tree.SaveVersion() require.Nil(t, err) - return tree, types.CommitID{ver, hash} + return tree, types.CommitID{Version: ver, Hash: hash} } func TestGetImmutable(t *testing.T) { @@ -58,7 +58,7 @@ func TestGetImmutable(t *testing.T) { require.True(t, tree.Set([]byte("hello"), []byte("adios"))) hash, ver, err := tree.SaveVersion() - cID = types.CommitID{ver, hash} + cID = types.CommitID{Version: ver, Hash: hash} require.Nil(t, err) _, err = store.GetImmutable(cID.Version + 1) diff --git a/tm2/pkg/store/prefix/store_test.go b/tm2/pkg/store/prefix/store_test.go index 701ceda17d5..d61b67462e8 100644 --- a/tm2/pkg/store/prefix/store_test.go +++ b/tm2/pkg/store/prefix/store_test.go @@ -106,7 +106,7 @@ func TestPrefixStoreNoNilSet(t *testing.T) { t.Parallel() meter := types.NewGasMeter(100000000) - mem := dbadapter.Store{memdb.NewMemDB()} + mem := dbadapter.Store{DB: memdb.NewMemDB()} gasStore := gas.New(mem, meter, types.DefaultGasConfig()) require.Panics(t, func() { gasStore.Set([]byte("key"), nil) }, "setting a nil value should panic") } @@ -115,7 +115,7 @@ func TestPrefixStoreIterate(t *testing.T) { t.Parallel() db := memdb.NewMemDB() - baseStore := dbadapter.Store{db} + baseStore := dbadapter.Store{DB: db} prefix := []byte("test") prefixStore := New(baseStore, prefix) @@ -165,7 +165,7 @@ func TestPrefixStoreIteratorEdgeCase(t *testing.T) { t.Parallel() db := memdb.NewMemDB() - baseStore := dbadapter.Store{db} + baseStore := dbadapter.Store{DB: db} // overflow in cpIncr prefix := []byte{0xAA, 0xFF, 0xFF} @@ -197,7 +197,7 @@ func TestPrefixStoreReverseIteratorEdgeCase(t *testing.T) { t.Parallel() db := memdb.NewMemDB() - baseStore := dbadapter.Store{db} + baseStore := dbadapter.Store{DB: db} // overflow in cpIncr prefix := []byte{0xAA, 0xFF, 0xFF} @@ -225,7 +225,7 @@ func TestPrefixStoreReverseIteratorEdgeCase(t *testing.T) { iter.Close() db = memdb.NewMemDB() - baseStore = dbadapter.Store{db} + baseStore = dbadapter.Store{DB: db} // underflow in cpDecr prefix = []byte{0xAA, 0x00, 0x00} @@ -256,7 +256,7 @@ func TestPrefixStoreReverseIteratorEdgeCase(t *testing.T) { func mockStoreWithStuff() types.Store { db := memdb.NewMemDB() - store := dbadapter.Store{db} + store := dbadapter.Store{DB: db} // Under "key" prefix store.Set(bz("key"), bz("value")) store.Set(bz("key1"), bz("value1")) diff --git a/tm2/pkg/telemetry/config/config.go b/tm2/pkg/telemetry/config/config.go index a9aa24d7848..47fc5666342 100644 --- a/tm2/pkg/telemetry/config/config.go +++ b/tm2/pkg/telemetry/config/config.go @@ -19,9 +19,9 @@ type Config struct { func DefaultTelemetryConfig() *Config { return &Config{ MetricsEnabled: false, - MeterName: "gno.land", - ServiceName: "gno.land", - ServiceInstanceID: "gno-node-1", + MeterName: "tm2", + ServiceName: "tm2", + ServiceInstanceID: "tm2-node-1", ExporterEndpoint: "", } }