From 032d422302fea5599da612ca684ffc4d8dd83639 Mon Sep 17 00:00:00 2001 From: Morgan Date: Thu, 20 Jun 2024 13:51:36 +0200 Subject: [PATCH 1/9] feat(keeper)!: use . syntax for qeval; : for qrender (#2382) This is a switch that was discussed with @leohhhn and @moul. It switches the current syntax for qeval, which requires a newline as a separator, to use a dot `.` instead (ie. `gno.land/r/demo/users.MyFunction(123)`). For qrender, this is switched to a colon `:`, like the gnoweb render: `gno.land/r/demo/users:u/morgan`. BREAKING CHANGE: current qeval and qrender calls using the RPC endpoints will have to be changed. No changes are required for gnoclient users.
Contributors' checklist... - [x] Added new tests, or not needed, or not feasible - [x] Provided an example (e.g. screenshot) to aid review or the PR is self-explanatory - [x] Updated the official documentation or not needed - [x] No breaking changes were made, or a `BREAKING CHANGE: xxx` message was included in the description - [x] Added references to related issues and PRs - [x] Provided any useful hints for running manual tests - [x] 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).
--------- Co-authored-by: Manfred Touron <94029+moul@users.noreply.github.com> Co-authored-by: Leon Hudak <33522493+leohhhn@users.noreply.github.com> --- docs/gno-tooling/cli/gnokey.md | 10 +-- examples/gno.land/r/demo/boards/README.md | 11 +-- .../gnoland/testdata/gnokey_simulate.txtar | 12 +-- gno.land/genesis/genesis_txs.jsonl | 4 +- gno.land/pkg/gnoclient/client_queries.go | 4 +- gno.land/pkg/gnoweb/gnoweb.go | 4 +- gno.land/pkg/sdk/vm/handler.go | 48 +++++++---- gno.land/pkg/sdk/vm/handler_test.go | 86 +++++++++---------- 8 files changed, 90 insertions(+), 89 deletions(-) diff --git a/docs/gno-tooling/cli/gnokey.md b/docs/gno-tooling/cli/gnokey.md index 9ea51546864..bf110faec5f 100644 --- a/docs/gno-tooling/cli/gnokey.md +++ b/docs/gno-tooling/cli/gnokey.md @@ -124,8 +124,8 @@ gnokey query {QUERY_PATH} | `bank/balances/{ADDRESS}` | Returns balances of an account. | `gnokey query bank/balances/g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5` | | `vm/qfuncs` | Returns public facing function signatures as JSON. | `gnokey query vm/qfuncs --data "gno.land/r/demo/boards"` | | `vm/qfile` | Returns the file bytes, or list of files if directory. | `gnokey query vm/qfile --data "gno.land/r/demo/boards"` | -| `vm/qrender` | Calls .Render(path) in readonly mode. | `gnokey query vm/qrender --data "gno.land/r/demo/boards"` | -| `vm/qeval` | Evaluates any expression in readonly mode and returns the results. | `gnokey query vm/qeval --data "gno.land/r/demo/boards GetBoardIDFromName("my_board")"` | +| `vm/qrender` | Calls .Render(path) in readonly mode. | `gnokey query vm/qrender --data "gno.land/r/demo/boards:"` | +| `vm/qeval` | Evaluates any expression in readonly mode and returns the results. | `gnokey query vm/qeval --data "gno.land/r/demo/boards.GetBoardIDFromName("my_board")"` | | `vm/store` | (not yet supported) Fetches items from the store. | - | | `vm/package` | (not yet supported) Fetches a package's files. | - | @@ -205,16 +205,16 @@ gnokey maketx call \ > unsigned.tx ``` -:::warning `call` is a state-changing message +:::warning `call` is a state-changing message All exported functions, including `Render()`, can be called in two main ways: `call` and [`query vm/qeval`](#query). With `call`, any state change that happened in the function being called will be applied and persisted in on the blockchain, and the gas used for this call will -be subtracted from the caller balance. +be subtracted from the caller balance. -As opposed to this, an ABCI query, such as `vm/qeval` will not persist state +As opposed to this, an ABCI query, such as `vm/qeval` will not persist state changes and does not cost gas, only evaluating the expression in read-only mode. ::: diff --git a/examples/gno.land/r/demo/boards/README.md b/examples/gno.land/r/demo/boards/README.md index 6e3dac115b1..a9b68ec9c92 100644 --- a/examples/gno.land/r/demo/boards/README.md +++ b/examples/gno.land/r/demo/boards/README.md @@ -58,7 +58,7 @@ your `ACCOUNT_ADDR` and `KEYNAME` Instead of editing `gno.land/genesis/genesis_balances.txt`, a more general solution (with more steps) is to run a local "faucet" and use the web browser to add $GNOT. (This can be done at any time.) -See this page: https://github.com/gnolang/gno/blob/master/gno.land/cmd/gnofaucet/README.md +See this page: https://github.com/gnolang/gno/blob/master/gno.land/cmd/gnofaucet/README.md ### Start the `gnoland` node. @@ -97,8 +97,7 @@ Interactive documentation: https://test3.gno.land/r/demo/boards?help&__func=Crea Next, query for the permanent board ID by querying (you need this to create a new post): ```bash -./build/gnokey query "vm/qeval" -data "gno.land/r/demo/boards -GetBoardIDFromName(\"BOARDNAME\")" -remote localhost:26657 +./build/gnokey query "vm/qeval" -data 'gno.land/r/demo/boards.GetBoardIDFromName("BOARDNAME")' -remote localhost:26657 ``` ### Create a post of a board with a smart contract call. @@ -120,8 +119,7 @@ Interactive documentation: https://test3.gno.land/r/demo/boards?help&__func=Crea Interactive documentation: https://test3.gno.land/r/demo/boards?help&__func=CreateReply ```bash -./build/gnokey query "vm/qrender" -data "gno.land/r/demo/boards -BOARDNAME/1" -remote localhost:26657 +./build/gnokey query "vm/qrender" -data "gno.land/r/demo/boards:BOARDNAME/1" -remote localhost:26657 ``` ### Render page with optional path expression. @@ -130,8 +128,7 @@ The contents of `https://gno.land/r/demo/boards:` and `https://gno.land/r/demo/b the `Render(path string)` function like so: ```bash -./build/gnokey query "vm/qrender" -data "gno.land/r/demo/boards -gnolang" +./build/gnokey query "vm/qrender" -data "gno.land/r/demo/boards:gnolang" ``` ## View the board in the browser. diff --git a/gno.land/cmd/gnoland/testdata/gnokey_simulate.txtar b/gno.land/cmd/gnoland/testdata/gnokey_simulate.txtar index dab238a6122..8db2c7302fc 100644 --- a/gno.land/cmd/gnoland/testdata/gnokey_simulate.txtar +++ b/gno.land/cmd/gnoland/testdata/gnokey_simulate.txtar @@ -30,19 +30,19 @@ stdout '"sequence": "1"' gnokey maketx call -pkgpath gno.land/r/hello -func SetName -args John -gas-wanted 2000000 -gas-fee 1000000ugnot -broadcast -chainid tendermint_test -simulate test test1 gnokey query auth/accounts/$USER_ADDR_test1 stdout '"sequence": "2"' -gnokey query vm/qeval --data "gno.land/r/hello\nHello()" +gnokey query vm/qeval --data "gno.land/r/hello.Hello()" stdout 'Hello, John!' # -simulate only gnokey maketx call -pkgpath gno.land/r/hello -func SetName -args Paul -gas-wanted 2000000 -gas-fee 1000000ugnot -broadcast -chainid tendermint_test -simulate only test1 gnokey query auth/accounts/$USER_ADDR_test1 stdout '"sequence": "2"' -gnokey query vm/qeval --data "gno.land/r/hello\nHello()" +gnokey query vm/qeval --data "gno.land/r/hello.Hello()" stdout 'Hello, John!' # -simulate skip gnokey maketx call -pkgpath gno.land/r/hello -func SetName -args George -gas-wanted 2000000 -gas-fee 1000000ugnot -broadcast -chainid tendermint_test -simulate skip test1 gnokey query auth/accounts/$USER_ADDR_test1 stdout '"sequence": "3"' -gnokey query vm/qeval --data "gno.land/r/hello\nHello()" +gnokey query vm/qeval --data "gno.land/r/hello.Hello()" stdout 'Hello, George!' # attempt calling hello.Grumpy (always panics). @@ -52,19 +52,19 @@ stdout 'Hello, George!' ! gnokey maketx call -pkgpath gno.land/r/hello -func Grumpy -gas-wanted 2000000 -gas-fee 1000000ugnot -broadcast -chainid tendermint_test -simulate test test1 gnokey query auth/accounts/$USER_ADDR_test1 stdout '"sequence": "3"' -gnokey query vm/qeval --data "gno.land/r/hello\nHello()" +gnokey query vm/qeval --data "gno.land/r/hello.Hello()" stdout 'Hello, George!' # -simulate only ! gnokey maketx call -pkgpath gno.land/r/hello -func Grumpy -gas-wanted 2000000 -gas-fee 1000000ugnot -broadcast -chainid tendermint_test -simulate only test1 gnokey query auth/accounts/$USER_ADDR_test1 stdout '"sequence": "3"' -gnokey query vm/qeval --data "gno.land/r/hello\nHello()" +gnokey query vm/qeval --data "gno.land/r/hello.Hello()" stdout 'Hello, George!' # -simulate skip ! gnokey maketx call -pkgpath gno.land/r/hello -func Grumpy -gas-wanted 2000000 -gas-fee 1000000ugnot -broadcast -chainid tendermint_test -simulate skip test1 gnokey query auth/accounts/$USER_ADDR_test1 stdout '"sequence": "4"' -gnokey query vm/qeval --data "gno.land/r/hello\nHello()" +gnokey query vm/qeval --data "gno.land/r/hello.Hello()" stdout 'Hello, George!' -- test/test.gno -- diff --git a/gno.land/genesis/genesis_txs.jsonl b/gno.land/genesis/genesis_txs.jsonl index 04ec61b4e5d..3e9db62df46 100644 --- a/gno.land/genesis/genesis_txs.jsonl +++ b/gno.land/genesis/genesis_txs.jsonl @@ -8,10 +8,10 @@ {"msg":[{"@type":"/vm.m_call","caller":"g1ds24jj9kqjcskd0gzu24r9e4n62ggye230zuv5","send":"","pkg_path":"gno.land/r/demo/users","func":"Register","args":["g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj","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":"2000000000ugnot","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\nGetBoardIDFromName(\\\"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\ntestboard/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\ntestboard\"\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","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\nGetBoardIDFromName(\\\"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\nBOARDNAME/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\ngnolang\"\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/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":""} diff --git a/gno.land/pkg/gnoclient/client_queries.go b/gno.land/pkg/gnoclient/client_queries.go index a6c8ea60475..9d9d7305116 100644 --- a/gno.land/pkg/gnoclient/client_queries.go +++ b/gno.land/pkg/gnoclient/client_queries.go @@ -90,7 +90,7 @@ func (c *Client) Render(pkgPath string, args string) (string, *ctypes.ResultABCI } path := "vm/qrender" - data := []byte(fmt.Sprintf("%s\n%s", pkgPath, args)) + data := []byte(fmt.Sprintf("%s:%s", pkgPath, args)) qres, err := c.RPCClient.ABCIQuery(path, data) if err != nil { @@ -113,7 +113,7 @@ func (c *Client) QEval(pkgPath string, expression string) (string, *ctypes.Resul } path := "vm/qeval" - data := []byte(fmt.Sprintf("%s\n%s", pkgPath, expression)) + data := []byte(fmt.Sprintf("%s.%s", pkgPath, expression)) qres, err := c.RPCClient.ABCIQuery(path, data) if err != nil { diff --git a/gno.land/pkg/gnoweb/gnoweb.go b/gno.land/pkg/gnoweb/gnoweb.go index 0ccdc0b5d53..d8919fb0913 100644 --- a/gno.land/pkg/gnoweb/gnoweb.go +++ b/gno.land/pkg/gnoweb/gnoweb.go @@ -150,7 +150,7 @@ func handlerRealmAlias(logger *slog.Logger, app gotuna.App, cfg *Config, rlmpath } rlmname := strings.TrimPrefix(rlmfullpath, "gno.land/r/") qpath := "vm/qrender" - data := []byte(fmt.Sprintf("%s\n%s", rlmfullpath, querystr)) + data := []byte(fmt.Sprintf("%s:%s", rlmfullpath, querystr)) res, err := makeRequest(logger, cfg, qpath, data) if err != nil { writeError(logger, w, fmt.Errorf("gnoweb failed to query gnoland: %w", err)) @@ -323,7 +323,7 @@ func handleRealmRender(logger *slog.Logger, app gotuna.App, cfg *Config, w http. return } qpath := "vm/qrender" - data := []byte(fmt.Sprintf("%s\n%s", rlmpath, querystr)) + data := []byte(fmt.Sprintf("%s:%s", rlmpath, querystr)) res, err := makeRequest(logger, cfg, qpath, data) if err != nil { // XXX hack diff --git a/gno.land/pkg/sdk/vm/handler.go b/gno.land/pkg/sdk/vm/handler.go index ae77021aa06..7b26265f35d 100644 --- a/gno.land/pkg/sdk/vm/handler.go +++ b/gno.land/pkg/sdk/vm/handler.go @@ -150,12 +150,12 @@ func (vh vmHandler) queryStore(ctx sdk.Context, req abci.RequestQuery) (res abci // queryRender calls .Render() in readonly mode. func (vh vmHandler) queryRender(ctx sdk.Context, req abci.RequestQuery) (res abci.ResponseQuery) { reqData := string(req.Data) - reqParts := strings.Split(reqData, "\n") - if len(reqParts) != 2 { - panic("expected two lines in query input data") + dot := strings.IndexByte(reqData, ':') + if dot < 0 { + panic("expected : syntax in query input data") } - pkgPath := reqParts[0] - path := reqParts[1] + + pkgPath, path := reqData[:dot], reqData[dot+1:] expr := fmt.Sprintf("Render(%q)", path) result, err := vh.vm.QueryEvalString(ctx, pkgPath, expr) if err != nil { @@ -168,12 +168,7 @@ func (vh vmHandler) queryRender(ctx sdk.Context, req abci.RequestQuery) (res abc // queryFuncs returns public facing function signatures as JSON. func (vh vmHandler) queryFuncs(ctx sdk.Context, req abci.RequestQuery) (res abci.ResponseQuery) { - reqData := string(req.Data) - reqParts := strings.Split(reqData, "\n") - if len(reqParts) != 1 { - panic("expected one line in query input data") - } - pkgPath := reqParts[0] + pkgPath := string(req.Data) fsigs, err := vh.vm.QueryFuncs(ctx, pkgPath) if err != nil { res = sdk.ABCIResponseQueryFromError(err) @@ -185,13 +180,7 @@ func (vh vmHandler) queryFuncs(ctx sdk.Context, req abci.RequestQuery) (res abci // queryEval evaluates any expression in readonly mode and returns the results. func (vh vmHandler) queryEval(ctx sdk.Context, req abci.RequestQuery) (res abci.ResponseQuery) { - reqData := string(req.Data) - reqParts := strings.Split(reqData, "\n") - if len(reqParts) != 2 { - panic("expected two lines in query input data") - } - pkgPath := reqParts[0] - expr := reqParts[1] + pkgPath, expr := parseQueryEvalData(string(req.Data)) result, err := vh.vm.QueryEval(ctx, pkgPath, expr) if err != nil { res = sdk.ABCIResponseQueryFromError(err) @@ -201,6 +190,29 @@ func (vh vmHandler) queryEval(ctx sdk.Context, req abci.RequestQuery) (res abci. return } +// parseQueryEval parses the input string of vm/qeval. It takes the first dot +// after the first slash (if any) to separe the pkgPath and the expr. +// For instance, in gno.land/r/realm.MyFunction(), gno.land/r/realm is the +// pkgPath,and MyFunction() is the expr. +func parseQueryEvalData(data string) (pkgPath, expr string) { + slash := strings.IndexByte(data, '/') + if slash >= 0 { + pkgPath += data[:slash] + data = data[slash:] + } + dot := strings.IndexByte(data, '.') + if dot < 0 { + panic(panicInvalidQueryEvalData) + } + pkgPath += data[:dot] + expr = data[dot+1:] + return +} + +const ( + panicInvalidQueryEvalData = "expected . syntax in query input data" +) + // queryFile returns the file bytes, or list of files if directory. // if file, res.Value is []byte("file"). // if dir, res.Value is []byte("dir"). diff --git a/gno.land/pkg/sdk/vm/handler_test.go b/gno.land/pkg/sdk/vm/handler_test.go index 2110681d99d..38ac8fa61b9 100644 --- a/gno.land/pkg/sdk/vm/handler_test.go +++ b/gno.land/pkg/sdk/vm/handler_test.go @@ -1,58 +1,50 @@ package vm -/* - import ( - "fmt" - "strings" "testing" - "github.com/stretchr/testify/require" - - "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" - "github.com/gnolang/gno/tm2/pkg/sdk" - tu "github.com/gnolang/gno/tm2/pkg/sdk/testutils" - "github.com/gnolang/gno/tm2/pkg/std" + "github.com/stretchr/testify/assert" ) -func TestInvalidMsg(t *testing.T) { - h := NewHandler(BankKeeper{}) - res := h.Process(sdk.NewContext(nil, &bft.Header{}, false, nil), tu.NewTestMsg()) - require.False(t, res.IsOK()) - require.True(t, strings.Contains(res.Log, "unrecognized bank message type")) -} - -func TestBalances(t *testing.T) { - env := setupTestEnv() - h := NewHandler(env.bank) - req := abci.RequestQuery{ - Path: fmt.Sprintf("bank/%s", QueryBalance), - Data: []byte{}, +func Test_parseQueryEvalData(t *testing.T) { + t.Parallel() + tt := []struct { + input string + pkgpath string + expr string + }{ + { + "gno.land/r/realm.Expression()", + "gno.land/r/realm", + "Expression()", + }, + { + "a.b/c/d.e", + "a.b/c/d", + "e", + }, + { + "a.b.c.d.e/c/d.e", + "a.b.c.d.e/c/d", + "e", + }, + { + "abcde/c/d.e", + "abcde/c/d", + "e", + }, } + for _, tc := range tt { + path, expr := parseQueryEvalData(tc.input) + assert.Equal(t, tc.pkgpath, path) + assert.Equal(t, tc.expr, expr) + } +} - res := h.Query(env.ctx, req) - require.NotNil(t, res.Error) - - _, _, addr := tu.KeyTestPubAddr() - req.Data = amino.MustMarshalJSON(NewQueryBalanceParams(addr)) - res = h.Query(env.ctx, req) - require.Nil(t, res.Error) // the account does not exist, no error returned anyway - require.NotNil(t, res) - - var coins std.Coins - require.NoError(t, amino.UnmarshalJSON(res.Data, &coins)) - require.True(t, coins.IsZero()) +func Test_parseQueryEval_panic(t *testing.T) { + t.Parallel() - acc := env.acck.NewAccountWithAddress(env.ctx, addr) - acc.SetCoins(std.NewCoins(std.NewCoin("foo", 10))) - env.acck.SetAccount(env.ctx, acc) - res = h.Query(env.ctx, req) - require.Nil(t, res.Error) - require.NotNil(t, res) - require.NoError(t, amino.UnmarshalJSON(res.Data, &coins)) - require.True(t, coins.AmountOf("foo") == 10) + assert.PanicsWithValue(t, panicInvalidQueryEvalData, func() { + parseQueryEvalData("gno.land/r/demo/users") + }) } - -*/ From ed1601e602e90cf5c338eb86094466906806d25c Mon Sep 17 00:00:00 2001 From: sunspirit <167175638+linhpn99@users.noreply.github.com> Date: Thu, 20 Jun 2024 18:59:01 +0700 Subject: [PATCH 2/9] fix(gnoclient): Return error when getting keypair information (#2300) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Relate to https://github.com/gnolang/gno/issues/2133
Contributors' checklist... - [ ] Added new tests, or not needed, or not feasible - [ ] Provided an example (e.g. screenshot) to aid review or the PR is self-explanatory - [ ] Updated the official documentation or not needed - [ ] 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).
--------- Co-authored-by: Miloš Živković Co-authored-by: Manfred Touron <94029+moul@users.noreply.github.com> --- gno.land/pkg/gnoclient/client_test.go | 36 +++++++++++++-------------- gno.land/pkg/gnoclient/client_txs.go | 35 ++++++++++++++++++++------ gno.land/pkg/gnoclient/mock_test.go | 6 ++--- gno.land/pkg/gnoclient/signer.go | 15 +++++++---- 4 files changed, 58 insertions(+), 34 deletions(-) diff --git a/gno.land/pkg/gnoclient/client_test.go b/gno.land/pkg/gnoclient/client_test.go index 04ebb8e27b8..8aef07451d6 100644 --- a/gno.land/pkg/gnoclient/client_test.go +++ b/gno.land/pkg/gnoclient/client_test.go @@ -24,13 +24,13 @@ func TestRender(t *testing.T) { sign: func(cfg SignCfg) (*std.Tx, error) { return &std.Tx{}, nil }, - info: func() keys.Info { + info: func() (keys.Info, error) { return &mockKeysInfo{ getAddress: func() crypto.Address { adr, _ := crypto.AddressFromBech32("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") return adr }, - } + }, nil }, }, RPCClient: &mockRPCClient{ @@ -63,13 +63,13 @@ func TestCallSingle(t *testing.T) { sign: func(cfg SignCfg) (*std.Tx, error) { return &std.Tx{}, nil }, - info: func() keys.Info { + info: func() (keys.Info, error) { return &mockKeysInfo{ getAddress: func() crypto.Address { adr, _ := crypto.AddressFromBech32("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") return adr }, - } + }, nil }, }, RPCClient: &mockRPCClient{ @@ -117,13 +117,13 @@ func TestCallMultiple(t *testing.T) { sign: func(cfg SignCfg) (*std.Tx, error) { return &std.Tx{}, nil }, - info: func() keys.Info { + info: func() (keys.Info, error) { return &mockKeysInfo{ getAddress: func() crypto.Address { adr, _ := crypto.AddressFromBech32("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") return adr }, - } + }, nil }, }, RPCClient: &mockRPCClient{ @@ -482,13 +482,13 @@ func TestClient_Send_Errors(t *testing.T) { name: "Invalid To Address", client: Client{ Signer: &mockSigner{ - info: func() keys.Info { + info: func() (keys.Info, error) { return &mockKeysInfo{ getAddress: func() crypto.Address { adr, _ := crypto.AddressFromBech32("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") return adr }, - } + }, nil }, }, RPCClient: &mockRPCClient{}, @@ -512,13 +512,13 @@ func TestClient_Send_Errors(t *testing.T) { name: "Invalid Send Coins", client: Client{ Signer: &mockSigner{ - info: func() keys.Info { + info: func() (keys.Info, error) { return &mockKeysInfo{ getAddress: func() crypto.Address { adr, _ := crypto.AddressFromBech32("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") return adr }, - } + }, nil }, }, RPCClient: &mockRPCClient{}, @@ -561,13 +561,13 @@ func TestRunSingle(t *testing.T) { sign: func(cfg SignCfg) (*std.Tx, error) { return &std.Tx{}, nil }, - info: func() keys.Info { + info: func() (keys.Info, error) { return &mockKeysInfo{ getAddress: func() crypto.Address { adr, _ := crypto.AddressFromBech32("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") return adr }, - } + }, nil }, }, RPCClient: &mockRPCClient{ @@ -628,13 +628,13 @@ func TestRunMultiple(t *testing.T) { sign: func(cfg SignCfg) (*std.Tx, error) { return &std.Tx{}, nil }, - info: func() keys.Info { + info: func() (keys.Info, error) { return &mockKeysInfo{ getAddress: func() crypto.Address { adr, _ := crypto.AddressFromBech32("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") return adr }, - } + }, nil }, }, RPCClient: &mockRPCClient{ @@ -849,13 +849,13 @@ func TestRunErrors(t *testing.T) { name: "Invalid Empty Package", client: Client{ Signer: &mockSigner{ - info: func() keys.Info { + info: func() (keys.Info, error) { return &mockKeysInfo{ getAddress: func() crypto.Address { adr, _ := crypto.AddressFromBech32("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") return adr }, - } + }, nil }, }, RPCClient: &mockRPCClient{}, @@ -1040,13 +1040,13 @@ func TestAddPackageErrors(t *testing.T) { name: "Invalid Empty Package", client: Client{ Signer: &mockSigner{ - info: func() keys.Info { + info: func() (keys.Info, error) { return &mockKeysInfo{ getAddress: func() crypto.Address { adr, _ := crypto.AddressFromBech32("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") return adr }, - } + }, nil }, }, RPCClient: &mockRPCClient{}, diff --git a/gno.land/pkg/gnoclient/client_txs.go b/gno.land/pkg/gnoclient/client_txs.go index e306d737ede..a32a6899abe 100644 --- a/gno.land/pkg/gnoclient/client_txs.go +++ b/gno.land/pkg/gnoclient/client_txs.go @@ -86,9 +86,14 @@ func (c *Client) Call(cfg BaseTxCfg, msgs ...MsgCall) (*ctypes.ResultBroadcastTx return nil, err } + caller, err := c.Signer.Info() + if err != nil { + return nil, err + } + // Unwrap syntax sugar to vm.MsgCall slice vmMsgs = append(vmMsgs, std.Msg(vm.MsgCall{ - Caller: c.Signer.Info().GetAddress(), + Caller: caller.GetAddress(), PkgPath: msg.PkgPath, Func: msg.FuncName, Args: msg.Args, @@ -142,14 +147,17 @@ func (c *Client) Run(cfg BaseTxCfg, msgs ...MsgRun) (*ctypes.ResultBroadcastTxCo return nil, err } - caller := c.Signer.Info().GetAddress() + caller, err := c.Signer.Info() + if err != nil { + return nil, err + } msg.Package.Name = "main" msg.Package.Path = "" // Unwrap syntax sugar to vm.MsgCall slice vmMsgs = append(vmMsgs, std.Msg(vm.MsgRun{ - Caller: caller, + Caller: caller.GetAddress(), Package: msg.Package, Send: send, })) @@ -201,9 +209,14 @@ func (c *Client) Send(cfg BaseTxCfg, msgs ...MsgSend) (*ctypes.ResultBroadcastTx return nil, err } + caller, err := c.Signer.Info() + if err != nil { + return nil, err + } + // Unwrap syntax sugar to vm.MsgSend slice vmMsgs = append(vmMsgs, std.Msg(bank.MsgSend{ - FromAddress: c.Signer.Info().GetAddress(), + FromAddress: caller.GetAddress(), ToAddress: msg.ToAddress, Amount: send, })) @@ -255,11 +268,14 @@ func (c *Client) AddPackage(cfg BaseTxCfg, msgs ...MsgAddPackage) (*ctypes.Resul return nil, err } - caller := c.Signer.Info().GetAddress() + caller, err := c.Signer.Info() + if err != nil { + return nil, err + } // Unwrap syntax sugar to vm.MsgCall slice vmMsgs = append(vmMsgs, std.Msg(vm.MsgAddPackage{ - Creator: caller, + Creator: caller.GetAddress(), Package: msg.Package, Deposit: deposit, })) @@ -284,10 +300,13 @@ func (c *Client) AddPackage(cfg BaseTxCfg, msgs ...MsgAddPackage) (*ctypes.Resul // signAndBroadcastTxCommit signs a transaction and broadcasts it, returning the result func (c *Client) signAndBroadcastTxCommit(tx std.Tx, accountNumber, sequenceNumber uint64) (*ctypes.ResultBroadcastTxCommit, error) { - caller := c.Signer.Info().GetAddress() + caller, err := c.Signer.Info() + if err != nil { + return nil, err + } if sequenceNumber == 0 || accountNumber == 0 { - account, _, err := c.QueryAccount(caller) + account, _, err := c.QueryAccount(caller.GetAddress()) if err != nil { return nil, errors.Wrap(err, "query account") } diff --git a/gno.land/pkg/gnoclient/mock_test.go b/gno.land/pkg/gnoclient/mock_test.go index 385eeb0916e..64da62936c2 100644 --- a/gno.land/pkg/gnoclient/mock_test.go +++ b/gno.land/pkg/gnoclient/mock_test.go @@ -13,7 +13,7 @@ import ( // Signer mock type ( mockSign func(cfg SignCfg) (*std.Tx, error) - mockInfo func() keys.Info + mockInfo func() (keys.Info, error) mockValidate func() error ) @@ -30,11 +30,11 @@ func (m *mockSigner) Sign(cfg SignCfg) (*std.Tx, error) { return nil, nil } -func (m *mockSigner) Info() keys.Info { +func (m *mockSigner) Info() (keys.Info, error) { if m.info != nil { return m.info() } - return nil + return nil, nil } func (m *mockSigner) Validate() error { diff --git a/gno.land/pkg/gnoclient/signer.go b/gno.land/pkg/gnoclient/signer.go index f8e1e6b8522..0462865f2be 100644 --- a/gno.land/pkg/gnoclient/signer.go +++ b/gno.land/pkg/gnoclient/signer.go @@ -12,7 +12,7 @@ import ( // Signer provides an interface for signing transactions. type Signer interface { Sign(SignCfg) (*std.Tx, error) // Signs a transaction and returns a signed tx ready for broadcasting. - Info() keys.Info // Returns key information, including the address. + Info() (keys.Info, error) // Returns key information, including the address. Validate() error // Checks whether the signer is properly configured. } @@ -35,9 +35,14 @@ func (s SignerFromKeybase) Validate() error { return err } + caller, err := s.Info() + if err != nil { + return err + } + // To verify if the password unlocks the account, sign a blank transaction. msg := vm.MsgCall{ - Caller: s.Info().GetAddress(), + Caller: caller.GetAddress(), } signCfg := SignCfg{ UnsignedTX: std.Tx{ @@ -53,12 +58,12 @@ func (s SignerFromKeybase) Validate() error { } // Info gets keypair information. -func (s SignerFromKeybase) Info() keys.Info { +func (s SignerFromKeybase) Info() (keys.Info, error) { info, err := s.Keybase.GetByNameOrAddress(s.Account) if err != nil { - panic("should not happen") + return nil, err } - return info + return info, nil } // SignCfg provides the signing configuration, containing: From 25dba01268b863a04e8c25f6fd31ccdffdf8cfea Mon Sep 17 00:00:00 2001 From: Morgan Date: Thu, 20 Jun 2024 15:32:33 +0200 Subject: [PATCH 3/9] chore: remove stdshim (#2403) Somehow it slipped #1695
Contributors' checklist... - [x] Added new tests, or not needed, or not feasible - [x] Provided an example (e.g. screenshot) to aid review or the PR is self-explanatory - [x] Updated the official documentation or not needed - [x] No breaking changes were made, or a `BREAKING CHANGE: xxx` message was included in the description - [x] Added references to related issues and PRs - [x] Provided any useful hints for running manual tests - [x] 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).
--- gnovm/stdlibs/stdshim/stdshim.gno | 85 ------------------------------- 1 file changed, 85 deletions(-) delete mode 100644 gnovm/stdlibs/stdshim/stdshim.gno diff --git a/gnovm/stdlibs/stdshim/stdshim.gno b/gnovm/stdlibs/stdshim/stdshim.gno deleted file mode 100644 index 47a176296be..00000000000 --- a/gnovm/stdlibs/stdshim/stdshim.gno +++ /dev/null @@ -1,85 +0,0 @@ -package std - -const shimWarn = "stdshim cannot be used to run code" - -func AssertOriginCall() { - panic(shimWarn) -} - -func IsOriginCall() (isOrigin bool) { - panic(shimWarn) - return false -} - -func Hash(bz []byte) (hash [20]byte) { - panic(shimWarn) - return -} - -func GetChainID() string { - panic(shimWarn) - return "" -} - -func GetHeight() int64 { - panic(shimWarn) - return -1 -} - -func GetOrigSend() Coins { - panic(shimWarn) - return Coins{} -} - -func CurrentRealm() Realm { - panic(shimWarn) - return Realm{ - addr: Address(""), - pkgPath: "", - } -} - -func PrevRealm() Realm { - panic(shimWarn) - return Realm{ - addr: Address(""), - pkgPath: "", - } -} - -func GetOrigCaller() Address { - panic(shimWarn) - return Address("") -} - -func GetOrigPkgAddr() Address { - panic(shimWarn) - return Address("") -} - -func GetCallerAt(n int) Address { - panic(shimWarn) - return Address("") -} - -func GetBanker(bankerType BankerType) Banker { - panic(shimWarn) - return nil -} - -func EncodeBech32(prefix string, bytes [20]byte) (addr Address) { - panic(shimWarn) - return "" -} - -func DecodeBech32(addr Address) (prefix string, bytes [20]byte, ok bool) { - panic(shimWarn) -} - -func DerivePkgAddr(pkgPath string) (addr Address) { - panic(shimWarn) -} - -func Emit(typ string, attrs ...string) { - panic(shimWarn) -} From ea1ff3f6bbe5133e7363ef833046f715e1b8fa75 Mon Sep 17 00:00:00 2001 From: Albert Le Batteux Date: Thu, 20 Jun 2024 18:52:54 +0200 Subject: [PATCH 4/9] chore(tm2): OTEL / handle http metrics exporter (#2402)
Contributors' checklist... - [ ] Added new tests, or not needed, or not feasible - [ ] Provided an example (e.g. screenshot) to aid review or the PR is self-explanatory - [ ] Updated the official documentation or not needed - [ ] 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).
--- go.mod | 35 +++++++------- go.sum | 71 ++++++++++++++-------------- tm2/pkg/telemetry/metrics/metrics.go | 35 +++++++++++--- 3 files changed, 83 insertions(+), 58 deletions(-) diff --git a/go.mod b/go.mod index 76c42f0419c..1bc7c90e2e1 100644 --- a/go.mod +++ b/go.mod @@ -29,22 +29,23 @@ require ( github.com/stretchr/testify v1.9.0 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 go.etcd.io/bbolt v1.3.9 - go.opentelemetry.io/otel v1.25.0 + go.opentelemetry.io/otel v1.27.0 go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.25.0 - go.opentelemetry.io/otel/metric v1.25.0 - go.opentelemetry.io/otel/sdk v1.25.0 - go.opentelemetry.io/otel/sdk/metric v1.25.0 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.27.0 + go.opentelemetry.io/otel/metric v1.27.0 + go.opentelemetry.io/otel/sdk v1.27.0 + go.opentelemetry.io/otel/sdk/metric v1.27.0 go.uber.org/multierr v1.11.0 go.uber.org/zap v1.27.0 go.uber.org/zap/exp v0.2.0 - golang.org/x/crypto v0.21.0 + golang.org/x/crypto v0.23.0 golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 golang.org/x/mod v0.16.0 - golang.org/x/net v0.23.0 - golang.org/x/sync v0.6.0 - golang.org/x/term v0.18.0 + golang.org/x/net v0.25.0 + golang.org/x/sync v0.7.0 + golang.org/x/term v0.20.0 golang.org/x/tools v0.19.0 - google.golang.org/protobuf v1.33.0 + google.golang.org/protobuf v1.34.1 gopkg.in/yaml.v3 v3.0.1 ) @@ -56,18 +57,18 @@ require ( github.com/golang/snappy v0.0.4 // 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.19.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.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.25.0 // indirect - go.opentelemetry.io/proto/otlp v1.1.0 // indirect - golang.org/x/sys v0.18.0 // indirect - golang.org/x/text v0.14.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect - google.golang.org/grpc v1.63.0 // indirect + go.opentelemetry.io/otel/trace v1.27.0 // indirect + go.opentelemetry.io/proto/otlp v1.2.0 // indirect + golang.org/x/sys v0.20.0 // indirect + golang.org/x/text v0.15.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240515191416-fc5f0ca64291 // indirect + google.golang.org/grpc v1.64.0 // indirect ) diff --git a/go.sum b/go.sum index e4d728a106d..d563396d801 100644 --- a/go.sum +++ b/go.sum @@ -91,8 +91,8 @@ github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/ github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/gotuna/gotuna v0.6.0 h1:N1lQKXEi/lwRp8u3sccTYLhzOffA4QasExz/1M5Riws= github.com/gotuna/gotuna v0.6.0/go.mod h1:F/ecRt29ChB6Ycy1AFIBpBiMNK0j7Heq+gFbLWquhjc= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU= +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/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= @@ -153,20 +153,22 @@ github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfU 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.25.0 h1:gldB5FfhRl7OJQbUHt/8s0a7cE8fbsPAtdpRaApKy4k= -go.opentelemetry.io/otel v1.25.0/go.mod h1:Wa2ds5NOXEMkCmUou1WA7ZBfLTHWIsp034OVD7AO+Vg= +go.opentelemetry.io/otel v1.27.0 h1:9BZoF3yMK/O1AafMiQTVu0YDj5Ea4hPhxCs7sGva+cg= +go.opentelemetry.io/otel v1.27.0/go.mod h1:DMpAK8fzYRzs+bi3rS5REupisuqTheUlSZJ1WnZaPAQ= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.25.0 h1:hDKnobznDpcdTlNzO0S/owRB8tyVr1OoeZZhDoqY+Cs= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.25.0/go.mod h1:kUDQaUs1h8iTIHbQTk+iJRiUvSfJYMMKTtMCaiVu7B0= -go.opentelemetry.io/otel/metric v1.25.0 h1:LUKbS7ArpFL/I2jJHdJcqMGxkRdxpPHE0VU/D4NuEwA= -go.opentelemetry.io/otel/metric v1.25.0/go.mod h1:rkDLUSd2lC5lq2dFNrX9LGAbINP5B7WBkC78RXCpH5s= -go.opentelemetry.io/otel/sdk v1.25.0 h1:PDryEJPC8YJZQSyLY5eqLeafHtG+X7FWnf3aXMtxbqo= -go.opentelemetry.io/otel/sdk v1.25.0/go.mod h1:oFgzCM2zdsxKzz6zwpTZYLLQsFwc+K0daArPdIhuxkw= -go.opentelemetry.io/otel/sdk/metric v1.25.0 h1:7CiHOy08LbrxMAp4vWpbiPcklunUshVpAvGBrdDRlGw= -go.opentelemetry.io/otel/sdk/metric v1.25.0/go.mod h1:LzwoKptdbBBdYfvtGCzGwk6GWMA3aUzBOwtQpR6Nz7o= -go.opentelemetry.io/otel/trace v1.25.0 h1:tqukZGLwQYRIFtSQM2u2+yfMVTgGVeqRLPUYx1Dq6RM= -go.opentelemetry.io/otel/trace v1.25.0/go.mod h1:hCCs70XM/ljO+BeQkyFnbK28SBIJ/Emuha+ccrCRT7I= -go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= -go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.27.0 h1:CIHWikMsN3wO+wq1Tp5VGdVRTcON+DmOJSfDjXypKOc= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.27.0/go.mod h1:TNupZ6cxqyFEpLXAZW7On+mLFL0/g0TE3unIYL91xWc= +go.opentelemetry.io/otel/metric v1.27.0 h1:hvj3vdEKyeCi4YaYfNjv2NUje8FqKqUY8IlF0FxV/ik= +go.opentelemetry.io/otel/metric v1.27.0/go.mod h1:mVFgmRlhljgBiuk/MP/oKylr4hs85GZAylncepAX/ak= +go.opentelemetry.io/otel/sdk v1.27.0 h1:mlk+/Y1gLPLn84U4tI8d3GNJmGT/eXe3ZuOXN9kTWmI= +go.opentelemetry.io/otel/sdk v1.27.0/go.mod h1:Ha9vbLwJE6W86YstIywK2xFfPjbWlCuwPtMkKdz/Y4A= +go.opentelemetry.io/otel/sdk/metric v1.27.0 h1:5uGNOlpXi+Hbo/DRoI31BSb1v+OGcpv2NemcCrOL8gI= +go.opentelemetry.io/otel/sdk/metric v1.27.0/go.mod h1:we7jJVrYN2kh3mVBlswtPU22K0SA+769l93J6bsyvqw= +go.opentelemetry.io/otel/trace v1.27.0 h1:IqYb813p7cmbHk0a5y6pD5JPakbVfftRXABGt5/Rscw= +go.opentelemetry.io/otel/trace v1.27.0/go.mod h1:6RiD1hkAprV4/q+yd2ln1HG9GoPx39SuvvstaLBl+l4= +go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94= +go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -179,8 +181,8 @@ 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-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.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ= golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -196,14 +198,14 @@ golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81R 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.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= 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.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +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.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= @@ -220,21 +222,22 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc 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.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.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.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= -golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= +golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= 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 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= @@ -245,22 +248,20 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T 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 v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= -google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= -google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de h1:jFNzHPIeuzhdRwVhbZdiym9q0ory/xY3sA+v2wPg8I0= -google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:5iCWqnniDlqZHrd3neWVTOwvh/v6s3232omMecelax8= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= -google.golang.org/grpc v1.63.0 h1:WjKe+dnvABXyPJMD7KDNLxtoGk5tgk+YFWN6cBWjZE8= -google.golang.org/grpc v1.63.0/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5 h1:P8OJ/WCl/Xo4E4zoe4/bifHpSmmKwARqyqE4nW6J2GQ= +google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5/go.mod h1:RGnPtTG7r4i8sPlNyDeikXF99hMM+hN6QMm4ooG9g2g= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240515191416-fc5f0ca64291 h1:AgADTJarZTBqgjiUzRgfaBchgYB3/WFTC80GPwsMcRI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240515191416-fc5f0ca64291/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= +google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY= +google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= 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.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 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/pkg/telemetry/metrics/metrics.go b/tm2/pkg/telemetry/metrics/metrics.go index 9d1839fa862..05589ffb640 100644 --- a/tm2/pkg/telemetry/metrics/metrics.go +++ b/tm2/pkg/telemetry/metrics/metrics.go @@ -3,10 +3,12 @@ package metrics import ( "context" "fmt" + "net/url" "github.com/gnolang/gno/tm2/pkg/telemetry/config" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc" + "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp" "go.opentelemetry.io/otel/metric" sdkMetric "go.opentelemetry.io/otel/sdk/metric" "go.opentelemetry.io/otel/sdk/resource" @@ -112,14 +114,35 @@ var ( ) func Init(config config.Config) error { - // Use oltp metric exporter - exp, err := otlpmetricgrpc.New( - context.Background(), - otlpmetricgrpc.WithEndpoint(config.ExporterEndpoint), - otlpmetricgrpc.WithInsecure(), + var ( + ctx = context.Background() + exp sdkMetric.Exporter ) + + u, err := url.Parse(config.ExporterEndpoint) if err != nil { - return fmt.Errorf("unable to create metrics exporter, %w", err) + return fmt.Errorf("error parsing exporter endpoint: %s, %w", config.ExporterEndpoint, err) + } + + // Use oltp metric exporter with http/https or grpc + switch u.Scheme { + case "http", "https": + exp, err = otlpmetrichttp.New( + ctx, + otlpmetrichttp.WithEndpointURL(config.ExporterEndpoint), + ) + if err != nil { + return fmt.Errorf("unable to create http metrics exporter, %w", err) + } + default: + exp, err = otlpmetricgrpc.New( + ctx, + otlpmetricgrpc.WithEndpoint(config.ExporterEndpoint), + otlpmetricgrpc.WithInsecure(), + ) + if err != nil { + return fmt.Errorf("unable to create grpc metrics exporter, %w", err) + } } provider := sdkMetric.NewMeterProvider( From cac0b772702afa5e97048a9644517a0bf90edef4 Mon Sep 17 00:00:00 2001 From: Guilhem Fanton <8671905+gfanton@users.noreply.github.com> Date: Fri, 21 Jun 2024 10:05:05 +0200 Subject: [PATCH 5/9] fix(CI): ignored contribs folder on gno update - bis (#2412) `contribs` are actually ignored when `gno` packages are updated, this can lead to some errors being ignored (https://github.com/gnolang/gno/commit/ea1ff3f6bbe5133e7363ef833046f715e1b8fa75) . This PR ensures that the CI runs on the `contribs` folder for the `gnovm`, `tm2`, and `gno.land` updates. Additionally, it adds `go.mod` and `go.sum` to the list. --------- Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> --- .github/workflows/build_template.yml | 4 +- .github/workflows/contribs.yml | 8 +++- .github/workflows/gnoland.yml | 1 + .github/workflows/gnovm.yml | 3 +- .github/workflows/tm2.yml | 1 + contribs/gnodev/go.mod | 33 ++++++------- contribs/gnodev/go.sum | 72 ++++++++++++++-------------- contribs/gnokeykc/go.mod | 33 ++++++------- contribs/gnokeykc/go.sum | 68 +++++++++++++------------- 9 files changed, 117 insertions(+), 106 deletions(-) diff --git a/.github/workflows/build_template.yml b/.github/workflows/build_template.yml index a984589caaa..430aa393a73 100644 --- a/.github/workflows/build_template.yml +++ b/.github/workflows/build_template.yml @@ -16,10 +16,10 @@ jobs: uses: actions/setup-go@v5 with: go-version: ${{ inputs.go-version }} - + - name: Checkout code uses: actions/checkout@v4 - + - name: Check generated files are up to date working-directory: ${{ inputs.modulepath }} run: | diff --git a/.github/workflows/contribs.yml b/.github/workflows/contribs.yml index 8fdcce9332c..784dc9b71e5 100644 --- a/.github/workflows/contribs.yml +++ b/.github/workflows/contribs.yml @@ -9,6 +9,12 @@ on: paths: - "contribs/**" - ".github/**" + # Contribs directly depend on gno, so we need to test it whenever changes + # are made to one of those + - "go.*" # check on go.mod/sum update + - "gno.land/**" + - "tm2/**.go" + - "gnovm/**.go" jobs: setup: @@ -30,4 +36,4 @@ jobs: with: modulepath: contribs/${{ matrix.program }} secrets: - codecov-token: ${{ secrets.CODECOV_TOKEN }} \ No newline at end of file + codecov-token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/gnoland.yml b/.github/workflows/gnoland.yml index d84e9f62bd6..202933f8462 100644 --- a/.github/workflows/gnoland.yml +++ b/.github/workflows/gnoland.yml @@ -10,6 +10,7 @@ on: - "gno.land/**" - "tm2/**.go" - "gnovm/**.go" + - "go.*" # check on go.mod/sum update - ".github/**" jobs: diff --git a/.github/workflows/gnovm.yml b/.github/workflows/gnovm.yml index ac304328dbb..8212ec5871d 100644 --- a/.github/workflows/gnovm.yml +++ b/.github/workflows/gnovm.yml @@ -8,6 +8,7 @@ on: pull_request: paths: - "gnovm/**" + - "go.*" # check on go.mod/sum update - ".github/**" jobs: @@ -17,4 +18,4 @@ jobs: with: modulepath: "gnovm" secrets: - codecov-token: ${{ secrets.CODECOV_TOKEN }} \ No newline at end of file + codecov-token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/tm2.yml b/.github/workflows/tm2.yml index 7471fd74cb7..81b7abf27f9 100644 --- a/.github/workflows/tm2.yml +++ b/.github/workflows/tm2.yml @@ -8,6 +8,7 @@ on: pull_request: paths: - "tm2/**" + - "go.*" # check on go.mod/sum update - ".github/**" jobs: diff --git a/contribs/gnodev/go.mod b/contribs/gnodev/go.mod index 4741a5d7326..b7a757c36a5 100644 --- a/contribs/gnodev/go.mod +++ b/contribs/gnodev/go.mod @@ -13,7 +13,7 @@ require ( github.com/muesli/termenv v0.15.2 github.com/stretchr/testify v1.9.0 go.uber.org/zap v1.27.0 - golang.org/x/term v0.18.0 + golang.org/x/term v0.20.0 ) require ( @@ -36,7 +36,7 @@ require ( github.com/gorilla/securecookie v1.1.1 // indirect github.com/gorilla/sessions v1.2.1 // indirect github.com/gotuna/gotuna v0.6.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/mattn/go-isatty v0.0.18 // indirect @@ -54,25 +54,26 @@ require ( 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.25.0 // indirect + go.opentelemetry.io/otel v1.27.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.25.0 // indirect - go.opentelemetry.io/otel/metric v1.25.0 // indirect - go.opentelemetry.io/otel/sdk v1.25.0 // indirect - go.opentelemetry.io/otel/sdk/metric v1.25.0 // indirect - go.opentelemetry.io/otel/trace v1.25.0 // indirect - go.opentelemetry.io/proto/otlp v1.1.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.27.0 // indirect + go.opentelemetry.io/otel/metric v1.27.0 // indirect + go.opentelemetry.io/otel/sdk v1.27.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.27.0 // indirect + go.opentelemetry.io/otel/trace v1.27.0 // indirect + go.opentelemetry.io/proto/otlp v1.2.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap/exp v0.2.0 // indirect - golang.org/x/crypto v0.21.0 // indirect + golang.org/x/crypto v0.23.0 // indirect golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect golang.org/x/mod v0.16.0 // indirect - golang.org/x/net v0.23.0 // indirect - golang.org/x/sys v0.18.0 // indirect - golang.org/x/text v0.14.0 // indirect + golang.org/x/net v0.25.0 // indirect + golang.org/x/sys v0.20.0 // indirect + golang.org/x/text v0.15.0 // indirect golang.org/x/tools v0.19.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect - google.golang.org/grpc v1.63.0 // indirect - google.golang.org/protobuf v1.33.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240515191416-fc5f0ca64291 // indirect + google.golang.org/grpc v1.64.0 // indirect + google.golang.org/protobuf v1.34.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/contribs/gnodev/go.sum b/contribs/gnodev/go.sum index a2c9f154560..81d7a5a103e 100644 --- a/contribs/gnodev/go.sum +++ b/contribs/gnodev/go.sum @@ -95,8 +95,8 @@ github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/ github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/gotuna/gotuna v0.6.0 h1:N1lQKXEi/lwRp8u3sccTYLhzOffA4QasExz/1M5Riws= github.com/gotuna/gotuna v0.6.0/go.mod h1:F/ecRt29ChB6Ycy1AFIBpBiMNK0j7Heq+gFbLWquhjc= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU= +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/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= @@ -164,20 +164,22 @@ github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfU 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.25.0 h1:gldB5FfhRl7OJQbUHt/8s0a7cE8fbsPAtdpRaApKy4k= -go.opentelemetry.io/otel v1.25.0/go.mod h1:Wa2ds5NOXEMkCmUou1WA7ZBfLTHWIsp034OVD7AO+Vg= +go.opentelemetry.io/otel v1.27.0 h1:9BZoF3yMK/O1AafMiQTVu0YDj5Ea4hPhxCs7sGva+cg= +go.opentelemetry.io/otel v1.27.0/go.mod h1:DMpAK8fzYRzs+bi3rS5REupisuqTheUlSZJ1WnZaPAQ= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.25.0 h1:hDKnobznDpcdTlNzO0S/owRB8tyVr1OoeZZhDoqY+Cs= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.25.0/go.mod h1:kUDQaUs1h8iTIHbQTk+iJRiUvSfJYMMKTtMCaiVu7B0= -go.opentelemetry.io/otel/metric v1.25.0 h1:LUKbS7ArpFL/I2jJHdJcqMGxkRdxpPHE0VU/D4NuEwA= -go.opentelemetry.io/otel/metric v1.25.0/go.mod h1:rkDLUSd2lC5lq2dFNrX9LGAbINP5B7WBkC78RXCpH5s= -go.opentelemetry.io/otel/sdk v1.25.0 h1:PDryEJPC8YJZQSyLY5eqLeafHtG+X7FWnf3aXMtxbqo= -go.opentelemetry.io/otel/sdk v1.25.0/go.mod h1:oFgzCM2zdsxKzz6zwpTZYLLQsFwc+K0daArPdIhuxkw= -go.opentelemetry.io/otel/sdk/metric v1.25.0 h1:7CiHOy08LbrxMAp4vWpbiPcklunUshVpAvGBrdDRlGw= -go.opentelemetry.io/otel/sdk/metric v1.25.0/go.mod h1:LzwoKptdbBBdYfvtGCzGwk6GWMA3aUzBOwtQpR6Nz7o= -go.opentelemetry.io/otel/trace v1.25.0 h1:tqukZGLwQYRIFtSQM2u2+yfMVTgGVeqRLPUYx1Dq6RM= -go.opentelemetry.io/otel/trace v1.25.0/go.mod h1:hCCs70XM/ljO+BeQkyFnbK28SBIJ/Emuha+ccrCRT7I= -go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= -go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.27.0 h1:CIHWikMsN3wO+wq1Tp5VGdVRTcON+DmOJSfDjXypKOc= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.27.0/go.mod h1:TNupZ6cxqyFEpLXAZW7On+mLFL0/g0TE3unIYL91xWc= +go.opentelemetry.io/otel/metric v1.27.0 h1:hvj3vdEKyeCi4YaYfNjv2NUje8FqKqUY8IlF0FxV/ik= +go.opentelemetry.io/otel/metric v1.27.0/go.mod h1:mVFgmRlhljgBiuk/MP/oKylr4hs85GZAylncepAX/ak= +go.opentelemetry.io/otel/sdk v1.27.0 h1:mlk+/Y1gLPLn84U4tI8d3GNJmGT/eXe3ZuOXN9kTWmI= +go.opentelemetry.io/otel/sdk v1.27.0/go.mod h1:Ha9vbLwJE6W86YstIywK2xFfPjbWlCuwPtMkKdz/Y4A= +go.opentelemetry.io/otel/sdk/metric v1.27.0 h1:5uGNOlpXi+Hbo/DRoI31BSb1v+OGcpv2NemcCrOL8gI= +go.opentelemetry.io/otel/sdk/metric v1.27.0/go.mod h1:we7jJVrYN2kh3mVBlswtPU22K0SA+769l93J6bsyvqw= +go.opentelemetry.io/otel/trace v1.27.0 h1:IqYb813p7cmbHk0a5y6pD5JPakbVfftRXABGt5/Rscw= +go.opentelemetry.io/otel/trace v1.27.0/go.mod h1:6RiD1hkAprV4/q+yd2ln1HG9GoPx39SuvvstaLBl+l4= +go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94= +go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -189,8 +191,8 @@ 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.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ= golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic= @@ -200,11 +202,11 @@ golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73r 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.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.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= @@ -215,37 +217,35 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w 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.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -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/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= +golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= 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.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw= golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc= 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 v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= -google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= -google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de h1:jFNzHPIeuzhdRwVhbZdiym9q0ory/xY3sA+v2wPg8I0= -google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:5iCWqnniDlqZHrd3neWVTOwvh/v6s3232omMecelax8= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= -google.golang.org/grpc v1.63.0 h1:WjKe+dnvABXyPJMD7KDNLxtoGk5tgk+YFWN6cBWjZE8= -google.golang.org/grpc v1.63.0/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5 h1:P8OJ/WCl/Xo4E4zoe4/bifHpSmmKwARqyqE4nW6J2GQ= +google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5/go.mod h1:RGnPtTG7r4i8sPlNyDeikXF99hMM+hN6QMm4ooG9g2g= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240515191416-fc5f0ca64291 h1:AgADTJarZTBqgjiUzRgfaBchgYB3/WFTC80GPwsMcRI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240515191416-fc5f0ca64291/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= +google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY= +google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= 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.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 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/gnokeykc/go.mod b/contribs/gnokeykc/go.mod index d368402a3c3..4a45cbc83f2 100644 --- a/contribs/gnokeykc/go.mod +++ b/contribs/gnokeykc/go.mod @@ -25,7 +25,7 @@ require ( github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/gorilla/websocket v1.5.1 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.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 @@ -36,23 +36,24 @@ require ( 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.25.0 // indirect + go.opentelemetry.io/otel v1.27.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.25.0 // indirect - go.opentelemetry.io/otel/metric v1.25.0 // indirect - go.opentelemetry.io/otel/sdk v1.25.0 // indirect - go.opentelemetry.io/otel/sdk/metric v1.25.0 // indirect - go.opentelemetry.io/otel/trace v1.25.0 // indirect - go.opentelemetry.io/proto/otlp v1.1.0 // indirect - golang.org/x/crypto v0.21.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.27.0 // indirect + go.opentelemetry.io/otel/metric v1.27.0 // indirect + go.opentelemetry.io/otel/sdk v1.27.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.27.0 // indirect + go.opentelemetry.io/otel/trace v1.27.0 // indirect + go.opentelemetry.io/proto/otlp v1.2.0 // indirect + golang.org/x/crypto v0.23.0 // indirect golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect golang.org/x/mod v0.16.0 // indirect - golang.org/x/net v0.23.0 // indirect - golang.org/x/sys v0.18.0 // indirect - golang.org/x/term v0.18.0 // indirect - golang.org/x/text v0.14.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect - google.golang.org/grpc v1.63.0 // indirect - google.golang.org/protobuf v1.33.0 // indirect + golang.org/x/net v0.25.0 // indirect + golang.org/x/sys v0.20.0 // indirect + golang.org/x/term v0.20.0 // indirect + golang.org/x/text v0.15.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240515191416-fc5f0ca64291 // indirect + google.golang.org/grpc v1.64.0 // indirect + google.golang.org/protobuf v1.34.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/contribs/gnokeykc/go.sum b/contribs/gnokeykc/go.sum index 4027483eb1c..2e72631bd10 100644 --- a/contribs/gnokeykc/go.sum +++ b/contribs/gnokeykc/go.sum @@ -80,8 +80,8 @@ github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ 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.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU= +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/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= @@ -134,25 +134,27 @@ github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfU 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.25.0 h1:gldB5FfhRl7OJQbUHt/8s0a7cE8fbsPAtdpRaApKy4k= -go.opentelemetry.io/otel v1.25.0/go.mod h1:Wa2ds5NOXEMkCmUou1WA7ZBfLTHWIsp034OVD7AO+Vg= +go.opentelemetry.io/otel v1.27.0 h1:9BZoF3yMK/O1AafMiQTVu0YDj5Ea4hPhxCs7sGva+cg= +go.opentelemetry.io/otel v1.27.0/go.mod h1:DMpAK8fzYRzs+bi3rS5REupisuqTheUlSZJ1WnZaPAQ= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.25.0 h1:hDKnobznDpcdTlNzO0S/owRB8tyVr1OoeZZhDoqY+Cs= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.25.0/go.mod h1:kUDQaUs1h8iTIHbQTk+iJRiUvSfJYMMKTtMCaiVu7B0= -go.opentelemetry.io/otel/metric v1.25.0 h1:LUKbS7ArpFL/I2jJHdJcqMGxkRdxpPHE0VU/D4NuEwA= -go.opentelemetry.io/otel/metric v1.25.0/go.mod h1:rkDLUSd2lC5lq2dFNrX9LGAbINP5B7WBkC78RXCpH5s= -go.opentelemetry.io/otel/sdk v1.25.0 h1:PDryEJPC8YJZQSyLY5eqLeafHtG+X7FWnf3aXMtxbqo= -go.opentelemetry.io/otel/sdk v1.25.0/go.mod h1:oFgzCM2zdsxKzz6zwpTZYLLQsFwc+K0daArPdIhuxkw= -go.opentelemetry.io/otel/sdk/metric v1.25.0 h1:7CiHOy08LbrxMAp4vWpbiPcklunUshVpAvGBrdDRlGw= -go.opentelemetry.io/otel/sdk/metric v1.25.0/go.mod h1:LzwoKptdbBBdYfvtGCzGwk6GWMA3aUzBOwtQpR6Nz7o= -go.opentelemetry.io/otel/trace v1.25.0 h1:tqukZGLwQYRIFtSQM2u2+yfMVTgGVeqRLPUYx1Dq6RM= -go.opentelemetry.io/otel/trace v1.25.0/go.mod h1:hCCs70XM/ljO+BeQkyFnbK28SBIJ/Emuha+ccrCRT7I= -go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= -go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.27.0 h1:CIHWikMsN3wO+wq1Tp5VGdVRTcON+DmOJSfDjXypKOc= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.27.0/go.mod h1:TNupZ6cxqyFEpLXAZW7On+mLFL0/g0TE3unIYL91xWc= +go.opentelemetry.io/otel/metric v1.27.0 h1:hvj3vdEKyeCi4YaYfNjv2NUje8FqKqUY8IlF0FxV/ik= +go.opentelemetry.io/otel/metric v1.27.0/go.mod h1:mVFgmRlhljgBiuk/MP/oKylr4hs85GZAylncepAX/ak= +go.opentelemetry.io/otel/sdk v1.27.0 h1:mlk+/Y1gLPLn84U4tI8d3GNJmGT/eXe3ZuOXN9kTWmI= +go.opentelemetry.io/otel/sdk v1.27.0/go.mod h1:Ha9vbLwJE6W86YstIywK2xFfPjbWlCuwPtMkKdz/Y4A= +go.opentelemetry.io/otel/sdk/metric v1.27.0 h1:5uGNOlpXi+Hbo/DRoI31BSb1v+OGcpv2NemcCrOL8gI= +go.opentelemetry.io/otel/sdk/metric v1.27.0/go.mod h1:we7jJVrYN2kh3mVBlswtPU22K0SA+769l93J6bsyvqw= +go.opentelemetry.io/otel/trace v1.27.0 h1:IqYb813p7cmbHk0a5y6pD5JPakbVfftRXABGt5/Rscw= +go.opentelemetry.io/otel/trace v1.27.0/go.mod h1:6RiD1hkAprV4/q+yd2ln1HG9GoPx39SuvvstaLBl+l4= +go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94= +go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A= 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.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ= golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic= @@ -162,8 +164,8 @@ golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73r 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.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 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= @@ -174,35 +176,33 @@ 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.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/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= +golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= 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.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 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 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= -google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= -google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de h1:jFNzHPIeuzhdRwVhbZdiym9q0ory/xY3sA+v2wPg8I0= -google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:5iCWqnniDlqZHrd3neWVTOwvh/v6s3232omMecelax8= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= -google.golang.org/grpc v1.63.0 h1:WjKe+dnvABXyPJMD7KDNLxtoGk5tgk+YFWN6cBWjZE8= -google.golang.org/grpc v1.63.0/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5 h1:P8OJ/WCl/Xo4E4zoe4/bifHpSmmKwARqyqE4nW6J2GQ= +google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5/go.mod h1:RGnPtTG7r4i8sPlNyDeikXF99hMM+hN6QMm4ooG9g2g= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240515191416-fc5f0ca64291 h1:AgADTJarZTBqgjiUzRgfaBchgYB3/WFTC80GPwsMcRI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240515191416-fc5f0ca64291/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= +google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY= +google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= 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.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 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= From 31a5f2ea63ab1f069201bfa7ad35e9eada8ec6d9 Mon Sep 17 00:00:00 2001 From: Leon Hudak <33522493+leohhhn@users.noreply.github.com> Date: Fri, 21 Jun 2024 19:00:40 +0200 Subject: [PATCH 6/9] feat: docs linter improvements (#2404) ## Description This PR improves the recently merged docs linter. It adds checks for improperly escaped JSX tags, and makes the addition of further linter checks easier with better pipelining. It also implements a change to the gnoclient docs by introducing godoc, as well as a few minor fixes.
Contributors' checklist... - [x] Added new tests, or not needed, or not feasible - [x] Provided an example (e.g. screenshot) to aid review or the PR is self-explanatory - [x] Updated the official documentation or not needed - [x] No breaking changes were made, or a `BREAKING CHANGE: xxx` message was included in the description - [x] Added references to related issues and PRs - [x] Provided any useful hints for running manual tests - [x] 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).
--- docs/concepts/proof-of-contribution.md | 2 + docs/gno-tooling/cli/gnodev.md | 38 ++-- docs/reference/gno-js-client/gno-provider.md | 2 +- docs/reference/gno-js-client/gno-wallet.md | 2 +- docs/reference/gnoclient/client.md | 192 ------------------ docs/reference/gnoclient/gnoclient.md | 11 +- docs/reference/gnoclient/signer.md | 86 -------- docs/reference/network-config.md | 2 +- .../Provider/json-rpc-provider.md | 2 +- misc/docs-linter/errors.go | 11 + misc/docs-linter/jsx.go | 56 +++++ misc/docs-linter/links.go | 107 ++++++++++ misc/docs-linter/main.go | 147 +++----------- misc/docs-linter/main_test.go | 113 ++++++++--- 14 files changed, 321 insertions(+), 450 deletions(-) delete mode 100644 docs/reference/gnoclient/client.md delete mode 100644 docs/reference/gnoclient/signer.md create mode 100644 misc/docs-linter/errors.go create mode 100644 misc/docs-linter/jsx.go create mode 100644 misc/docs-linter/links.go diff --git a/docs/concepts/proof-of-contribution.md b/docs/concepts/proof-of-contribution.md index 5446fa83a69..c855b3db8ed 100644 --- a/docs/concepts/proof-of-contribution.md +++ b/docs/concepts/proof-of-contribution.md @@ -24,6 +24,7 @@ Presentation: https://github.com/gnolang/workshops/tree/main/presentations/2023- ## High-level schema +``` ____ ____ ____ __ _ __ __ _ / __ \_________ ____ / __/ ____ / __/ _________ ____ / /______(_) /_ __ __/ /_(_)___ ____ _____ / /_/ / ___/ __ \/ __ \/ /_ / __ \/ /_ / ___/ __ \/ __ \/ __/ ___/ / __ \/ / / / __/ / __ \/ __ \/ ___/ @@ -55,6 +56,7 @@ Presentation: https://github.com/gnolang/workshops/tree/main/presentations/2023- ^ | | | +---------------user TXs can publish and call contracts--------------------+ +``` ## Components diff --git a/docs/gno-tooling/cli/gnodev.md b/docs/gno-tooling/cli/gnodev.md index 184eb92f721..c641a986a4e 100644 --- a/docs/gno-tooling/cli/gnodev.md +++ b/docs/gno-tooling/cli/gnodev.md @@ -8,13 +8,13 @@ Gnodev allows for quick and efficient development of Gno code. By watching your development directory, gnodev detects changes in your Gno code, reflecting them in the state of the node immediately. Gnodev also runs a -local instance of `gnoweb`, allowing you to see the rendering of your Gno code instantly. +local instance of `gnoweb`, allowing you to see the rendering of your Gno code instantly. ## Features - **In-Memory Node**: Gnodev starts an in-memory node, and automatically loads the **examples** folder and any user-specified paths. - **Web Interface Server**: Gnodev automatically starts a `gnoweb` server on -[`localhost:8888`](https://localhost:8888). + [`localhost:8888`](https://localhost:8888). - **Balances and Keybase Customization**: Users can set account balances, load them from a file, or add new accounts via a flag. - **Hot Reload**: Gnodev monitors the **examples** folder, as well as any folder specified as an argument for @@ -120,20 +120,20 @@ While `gnodev` is running, the following shortcuts are available: ### Options -| Flag | Effect | -|---------------------|---------------------------------------------------------------------| -| --minimal | Start `gnodev` without loading the examples folder. | -| --no-watch | Disable hot reload. | -| --add-account | Pre-add account(s) in the form `[=]` | -| --balances-file | Load a balance for the user(s) from a balance file. | -| --chain-id | Set node ChainID | -| --deploy-key | Default key name or Bech32 address for uploading packages. | -| --home | Set the path to load user's Keybase. | -| --max-gas | Set the maximum gas per block | -| --no-replay | Do not replay previous transactions upon reload | -| --node-rpc-listener | listening address for GnoLand RPC node | -| --root | gno root directory | -| --server-mode | disable interaction, and adjust logging for server use. | -| --verbose | enable verbose output for development | -| --web-listener | web server listening address | -| --web-help-remote | web server help page's remote addr - default to | +| Flag | Effect | +|---------------------|-----------------------------------------------------------------------| +| --minimal | Start `gnodev` without loading the examples folder. | +| --no-watch | Disable hot reload. | +| --add-account | Pre-add account(s) in the form `[=]` | +| --balances-file | Load a balance for the user(s) from a balance file. | +| --chain-id | Set node ChainID | +| --deploy-key | Default key name or Bech32 address for uploading packages. | +| --home | Set the path to load user's Keybase. | +| --max-gas | Set the maximum gas per block | +| --no-replay | Do not replay previous transactions upon reload | +| --node-rpc-listener | listening address for GnoLand RPC node | +| --root | gno root directory | +| --server-mode | disable interaction, and adjust logging for server use. | +| --verbose | enable verbose output for development | +| --web-listener | web server listening address | +| --web-help-remote | web server help page's remote addr - defaults to | diff --git a/docs/reference/gno-js-client/gno-provider.md b/docs/reference/gno-js-client/gno-provider.md index a5248349d35..df808106cc3 100644 --- a/docs/reference/gno-js-client/gno-provider.md +++ b/docs/reference/gno-js-client/gno-provider.md @@ -39,7 +39,7 @@ Fetches public facing function signatures * `height` **number** the height for querying. If omitted, the latest height is used (optional, default `0`) -Returns **Promise** +Returns **Promise** #### Usage diff --git a/docs/reference/gno-js-client/gno-wallet.md b/docs/reference/gno-js-client/gno-wallet.md index 7f7c44cd9b0..247c3d52878 100644 --- a/docs/reference/gno-js-client/gno-wallet.md +++ b/docs/reference/gno-js-client/gno-wallet.md @@ -63,7 +63,7 @@ Deploys the specified package / realm #### Parameters * `gnoPackage` **MemPackage** the package / realm to be deployed -* `funds` **Map** the denomination -> value map for funds +* `funds` **Map** the denomination -> value map for funds * `fee` **TxFee** the custom transaction fee, if any Returns **Promise** diff --git a/docs/reference/gnoclient/client.md b/docs/reference/gnoclient/client.md deleted file mode 100644 index 0fbef3f5f93..00000000000 --- a/docs/reference/gnoclient/client.md +++ /dev/null @@ -1,192 +0,0 @@ ---- -id: client ---- - -# Client - -## type [Client]() - -`Client` provides an interface for interacting with the blockchain. It is the main -struct of the `gnoclient` package, exposing all APIs used to communicate with a -Gno.land chain. - -```go -type Client struct { - Signer Signer // Signer for transaction authentication - RPCClient rpcclient.Client // RPC client for blockchain communication -} -``` - -### func \(\*Client\) [AddPackage]() - -```go -func (c *Client) AddPackage(cfg BaseTxCfg, msgs ...MsgAddPackage) (*ctypes.ResultBroadcastTxCommit, error) -``` - -`AddPackage` executes one or more [AddPackage](#type-msgaddpackage) calls on the blockchain. - -### func \(\*Client\) [Block]() - -```go -func (c *Client) Block(height int64) (*ctypes.ResultBlock, error) -``` - -`Block` gets the latest block at height, if any. Height must be larger than 0. - -### func \(\*Client\) [BlockResult]() - -```go -func (c *Client) BlockResult(height int64) (*ctypes.ResultBlockResults, error) -``` - -`BlockResult` gets the block results at height, if any. Height must be larger than 0. - -### func \(\*Client\) [LatestBlockHeight]() - -```go -func (c *Client) LatestBlockHeight() (int64, error) -``` - -`LatestBlockHeight` gets the latest block height on the chain. - -### func \(\*Client\) [Call]() - -```go -func (c *Client) Call(cfg BaseTxCfg, msgs ...MsgCall) (*ctypes.ResultBroadcastTxCommit, error) -``` - -`Call` executes a one or more [MsgCall](#type-msgcall) calls on the blockchain. - -### func \(\*Client\) [Send]() - -```go -func (c *Client) Send(cfg BaseTxCfg, msgs ...MsgSend) (*ctypes.ResultBroadcastTxCommit, error) -``` - -`Send` executes one or more [MsgSend](#type-msgsend) calls on the blockchain. - -### func \(\*Client\) [Run]() - -```go -func (c *Client) Run(cfg BaseTxCfg, msgs ...MsgRun) (*ctypes.ResultBroadcastTxCommit, error) -``` - -`Run` executes a one or more MsgRun calls on the blockchain. - -### func \(\*Client\) [QEval]() - -```go -func (c *Client) QEval(pkgPath string, expression string) (string, *ctypes.ResultABCIQuery, error) -``` - -`QEval` evaluates the given expression with the realm code at `pkgPath`. -The `pkgPath` should include the prefix like `gno.land/`. The expression is -usually a function call like `Render("")`. - -### func \(*Client\) [Query]() - -```go -func (c *Client) Query(cfg QueryCfg) (*ctypes.ResultABCIQuery, error) -``` - -`Query` performs a generic query on the blockchain. - -### func \(*Client\) [QueryAccount]() - -```go -func (c *Client) QueryAccount(addr crypto.Address) (*std.BaseAccount, *ctypes.ResultABCIQuery, error) -``` - -`QueryAccount` retrieves account information for a given address. - -### func \(*Client\) [QueryAppVersion]() - -```go -func (c *Client) QueryAppVersion() (string, *ctypes.ResultABCIQuery, error) -``` - -`QueryAppVersion` retrieves information about the Gno.land app version. - -### func \(*Client\) [Render]() - -```go -func (c *Client) Render(pkgPath string, args string) (string, *ctypes.ResultABCIQuery, error) -``` - -`Render` calls the Render function for pkgPath with optional args. The `pkgPath` -should include the prefix like `gno.land/`. This is similar to using a browser -URL `/:` where `` doesn't have the prefix like -`gno.land/`. - -## type [BaseTxCfg]() - -`BaseTxCfg` defines the base transaction configuration, shared by all message -types. - -```go -type BaseTxCfg struct { - GasFee string // Gas fee - GasWanted int64 // Gas wanted - AccountNumber uint64 // Account number - SequenceNumber uint64 // Sequence number - Memo string // Memo -} -``` - -## type [MsgAddPackage]() - -`MsgAddPackage` \- syntax sugar for `vm.MsgAddPackage`. - -```go -type MsgAddPackage struct { - Package *std.MemPackage // Package to add - Deposit string // Coin deposit -} -``` - -## type [MsgCall]() - -`MsgCall` \- syntax sugar for `vm.MsgCall`. - -```go -type MsgCall struct { - PkgPath string // Package path - FuncName string // Function name - Args []string // Function arguments - Send string // Send amount -} -``` - -## type [MsgRun]() - -`MsgRun` \- syntax sugar for `vm.MsgRun`. - -```go -type MsgRun struct { - Package *std.MemPackage // Package to run - Send string // Send amount -} -``` - -## type [MsgSend]() - -`MsgSend` \- syntax sugar for `bank.MsgSend`. - -```go -type MsgSend struct { - ToAddress crypto.Address // Send to address - Send string // Send amount -} -``` - -## type [QueryCfg]() - -`QueryCfg` contains configuration options for performing ABCI queries. - -```go -type QueryCfg struct { - Path string // Query path - Data []byte // Query data - rpcclient.ABCIQueryOptions // ABCI query options -} -``` \ No newline at end of file diff --git a/docs/reference/gnoclient/gnoclient.md b/docs/reference/gnoclient/gnoclient.md index f5baa9fc03a..5b9a9f5d43e 100644 --- a/docs/reference/gnoclient/gnoclient.md +++ b/docs/reference/gnoclient/gnoclient.md @@ -22,4 +22,13 @@ your Go code To add Gnoclient to your Go project, run the following command: ```bash go get github.com/gnolang/gno/gno.land/pkg/gnoclient -``` \ No newline at end of file +``` + +## Reference documentation & usage + +To see the full reference documentation for the `gnoclient` package, we recommend +visiting the [`gnoclient godoc page`](https://gnolang.github.io/gno/github.com/gnolang/gno@v0.0.0/gno.land/pkg/gnoclient.html). + +For a tutorial on how to use the `gnoclient` package, check out +["How to connect a Go app to Gno.land"](../../how-to-guides/connecting-from-go.md.) + diff --git a/docs/reference/gnoclient/signer.md b/docs/reference/gnoclient/signer.md deleted file mode 100644 index 75c69a9f7c2..00000000000 --- a/docs/reference/gnoclient/signer.md +++ /dev/null @@ -1,86 +0,0 @@ ---- -id: signer ---- - -# Signer - -`Signer` is an interface that provides functionality for signing transactions. -The signer can be created from a local keybase, or from a bip39 mnemonic phrase. - -Useful types and functions when using the `Signer` can be found below. - -## type [Signer]() - -`Signer` provides an interface for signing transactions. - -```go -type Signer interface { - Sign(SignCfg) (*std.Tx, error) // Signs a transaction and returns a signed tx ready for broadcasting. - Info() keys.Info // Returns key information, including the address. - Validate() error // Checks whether the signer is properly configured. -} -``` - -## type [SignCfg]() - -`SignCfg` provides the signing configuration, containing the unsigned transaction -data, account number, and account sequence. - -```go -type SignCfg struct { - UnsignedTX std.Tx - SequenceNumber uint64 - AccountNumber uint64 -} -``` - -## type [SignerFromKeybase]() - -`SignerFromKeybase` represents a signer created from a Keybase. - -```go -type SignerFromKeybase struct { - Keybase keys.Keybase // Stores keys in memory or on disk - Account string // Account name or bech32 format - Password string // Password for encryption - ChainID string // Chain ID for transaction signing -} -``` - -### func \(SignerFromKeybase\) [Info]() - -```go -func (s SignerFromKeybase) Info() keys.Info -``` - -`Info` gets keypair information. - -### func \(SignerFromKeybase\) [Sign]() - -```go -func (s SignerFromKeybase) Sign(cfg SignCfg) (*std.Tx, error) -``` - -`Sign` implements the Signer interface for SignerFromKeybase. - -### func \(SignerFromKeybase\) [Validate]() - -```go -func (s SignerFromKeybase) Validate() error -``` - -`Validate` checks if the signer is properly configured. - -## func [SignerFromBip39]() - -```go -func SignerFromBip39(mnemonic string, chainID string, passphrase string, account uint32, index uint32) (Signer, error) -``` - -`SignerFromBip39` creates a `Signer` from an in-memory keybase with a single default -account, derived from the given mnemonic. -This can be useful in scenarios where storing private keys in the filesystem -isn't feasible, or for generating a signer for testing. - -> Using `keys.NewKeyBaseFromDir()` to get a keypair from local storage is -recommended where possible, as it is more secure. \ No newline at end of file diff --git a/docs/reference/network-config.md b/docs/reference/network-config.md index 0da179e8f17..7902ec5e7f6 100644 --- a/docs/reference/network-config.md +++ b/docs/reference/network-config.md @@ -9,7 +9,7 @@ id: network-config | Portal Loop | https://rpc.gno.land:443 | `portal-loop` | | Testnet 4 | upcoming | upcoming | | Testnet 3 | https://rpc.test3.gno.land:443 | `test3` | -| Staging | http://rpc.staging.gno.land:26657 | `staging` | +| Staging | http://rpc.staging.gno.land:36657 | `staging` | ### WebSocket endpoints All networks follow the same pattern for websocket connections: diff --git a/docs/reference/tm2-js-client/Provider/json-rpc-provider.md b/docs/reference/tm2-js-client/Provider/json-rpc-provider.md index 50d816e89f9..b7700e1d97c 100644 --- a/docs/reference/tm2-js-client/Provider/json-rpc-provider.md +++ b/docs/reference/tm2-js-client/Provider/json-rpc-provider.md @@ -17,6 +17,6 @@ Creates a new instance of the JSON-RPC Provider #### Usage ```ts -new JSONRPCProvider('http://staging.gno.land:26657'); +new JSONRPCProvider('http://staging.gno.land:36657'); // provider is created ``` diff --git a/misc/docs-linter/errors.go b/misc/docs-linter/errors.go new file mode 100644 index 00000000000..8702f6f7de9 --- /dev/null +++ b/misc/docs-linter/errors.go @@ -0,0 +1,11 @@ +package main + +import "errors" + +var ( + errEmptyPath = errors.New("you need to pass in a path to scan") + err404Link = errors.New("link returned a 404") + errFound404Links = errors.New("found links resulting in a 404 response status") + errFoundUnescapedJSXTags = errors.New("found unescaped JSX tags") + errFoundLintItems = errors.New("found items that need linting") +) diff --git a/misc/docs-linter/jsx.go b/misc/docs-linter/jsx.go new file mode 100644 index 00000000000..50b16d842c0 --- /dev/null +++ b/misc/docs-linter/jsx.go @@ -0,0 +1,56 @@ +package main + +import ( + "context" + "fmt" + "regexp" + "strings" +) + +func extractJSX(fileContent []byte) []string { + text := string(fileContent) + + // Remove code blocks + reCodeBlocks := regexp.MustCompile("(?s)```.*?```") + contentNoCodeBlocks := reCodeBlocks.ReplaceAllString(text, "") + + // Remove inline code + reInlineCode := regexp.MustCompile("`[^`]*`") + contentNoInlineCode := reInlineCode.ReplaceAllString(contentNoCodeBlocks, "") + + // Extract JSX/HTML elements + reJSX := regexp.MustCompile("(?s)<[^>]+>") + + matches := reJSX.FindAllString(contentNoInlineCode, -1) + + filteredMatches := make([]string, 0) + // Ignore HTML comments and escaped JSX + for _, m := range matches { + if !strings.Contains(m, "!--") && !strings.Contains(m, "\\>") { + filteredMatches = append(filteredMatches, m) + } + } + + return filteredMatches +} + +func lintJSX(fileUrlMap map[string][]string, ctx context.Context) error { + found := false + for filePath, tags := range fileUrlMap { + filePath := filePath + for _, tag := range tags { + if !found { + fmt.Println("Tags that need checking:") + found = true + } + + fmt.Printf(">>> %s (found in file: %s)\n", tag, filePath) + } + } + + if found { + return errFoundUnescapedJSXTags + } + + return nil +} diff --git a/misc/docs-linter/links.go b/misc/docs-linter/links.go new file mode 100644 index 00000000000..41b90207aa5 --- /dev/null +++ b/misc/docs-linter/links.go @@ -0,0 +1,107 @@ +package main + +import ( + "bufio" + "bytes" + "context" + "fmt" + "golang.org/x/sync/errgroup" + "io" + "mvdan.cc/xurls/v2" + "net/http" + "strings" + "sync" +) + +// extractUrls extracts URLs from a file and maps them to the file +func extractUrls(fileContent []byte) []string { + scanner := bufio.NewScanner(bytes.NewReader(fileContent)) + urls := make([]string, 0) + + // Scan file line by line + for scanner.Scan() { + line := scanner.Text() + + // Extract links + rxStrict := xurls.Strict() + url := rxStrict.FindString(line) + + // Check for empty links and skip them + if url == " " || len(url) == 0 { + continue + } + + // Look for http & https only + if strings.HasPrefix(url, "http://") || strings.HasPrefix(url, "https://") { + // Ignore localhost + if !strings.Contains(url, "localhost") && !strings.Contains(url, "127.0.0.1") { + urls = append(urls, url) + } + } + } + + return urls +} + +func lintLinks(fileUrlMap map[string][]string, ctx context.Context) error { + // Filter links by prefix & ignore localhost + // Setup parallel checking for links + g, _ := errgroup.WithContext(ctx) + + var ( + lock sync.Mutex + notFoundUrls []string + ) + + for filePath, urls := range fileUrlMap { + filePath := filePath + for _, url := range urls { + url := url + g.Go(func() error { + if err := checkUrl(url); err != nil { + lock.Lock() + notFoundUrls = append(notFoundUrls, fmt.Sprintf(">>> %s (found in file: %s)", url, filePath)) + lock.Unlock() + } + + return nil + }) + } + } + + if err := g.Wait(); err != nil { + return err + } + + // Print out the URLs that returned a 404 along with the file names + if len(notFoundUrls) > 0 { + fmt.Println("Links that need checking:") + for _, result := range notFoundUrls { + fmt.Println(result) + } + + return errFound404Links + } + + return nil +} + +// checkUrl checks if a URL is a 404 +func checkUrl(url string) error { + // Attempt to retrieve the HTTP header + resp, err := http.Get(url) + if err != nil || resp.StatusCode == http.StatusNotFound { + return err404Link + } + + // Ensure the response body is closed properly + cleanup := func(Body io.ReadCloser) error { + if err := Body.Close(); err != nil { + return fmt.Errorf("could not close response properly: %w", err) + } + + return nil + } + + return cleanup(resp.Body) +} diff --git a/misc/docs-linter/main.go b/misc/docs-linter/main.go index 029b2bf387a..035170ca5ae 100644 --- a/misc/docs-linter/main.go +++ b/misc/docs-linter/main.go @@ -1,26 +1,14 @@ package main import ( - "bufio" "context" - "errors" "flag" "fmt" "github.com/gnolang/gno/tm2/pkg/commands" "golang.org/x/sync/errgroup" - "io" - "mvdan.cc/xurls/v2" - "net/http" "os" "path/filepath" "strings" - "sync" -) - -var ( - errEmptyPath = errors.New("you need to pass in a path to scan") - err404Link = errors.New("link returned a 404") - errFound404Links = errors.New("found links resulting in a 404 response status") ) type cfg struct { @@ -34,7 +22,8 @@ func main() { commands.Metadata{ Name: "docs-linter", ShortUsage: "docs-linter [flags]", - ShortHelp: "Finds broken 404 links in the .md files in the given folder & subfolders", + ShortHelp: `Lints the .md files in the given folder & subfolders. +Checks for 404 links, as well as improperly escaped JSX tags.`, }, cfg, func(ctx context.Context, args []string) error { @@ -58,73 +47,53 @@ func execLint(cfg *cfg, ctx context.Context) error { return errEmptyPath } - fmt.Println("Linting docs/") + absPath, err := filepath.Abs(cfg.docsPath) + if err != nil { + return fmt.Errorf("error getting absolute path for docs folder: %w", err) + } + + fmt.Printf("Linting %s...\n", absPath) + // Find docs files to lint mdFiles, err := findFilePaths(cfg.docsPath) if err != nil { return fmt.Errorf("error finding .md files: %w", err) } - urlFileMap := make(map[string]string) + // Make storage maps for tokens to analyze + fileUrlMap := make(map[string][]string) // file path > [urls] + fileJSXMap := make(map[string][]string) // file path > [JSX items] + + // Extract tokens from files for _, filePath := range mdFiles { - // Extract URLs from each file - urls, err := extractUrls(filePath) + // Read file content once and pass it to linters + fileContents, err := os.ReadFile(filePath) if err != nil { - fmt.Printf("Error extracting URLs from file: %s, %v", filePath, err) - continue + return err } - // For each url, save what file it was found in - for url, file := range urls { - urlFileMap[url] = file - } - } - // Filter links by prefix & ignore localhost - var validUrls []string - for url := range urlFileMap { - // Look for http & https only - if strings.HasPrefix(url, "http://") || strings.HasPrefix(url, "https://") { - // Ignore localhost - if !strings.Contains(url, "localhost") && !strings.Contains(url, "127.0.0.1") { - validUrls = append(validUrls, url) - } - } + fileJSXMap[filePath] = extractJSX(fileContents) + + // Execute URL extractor + fileUrlMap[filePath] = extractUrls(fileContents) } - // Setup parallel checking for links + // Run linters in parallel g, _ := errgroup.WithContext(ctx) - var ( - lock sync.Mutex - notFoundUrls []string - ) - - for _, url := range validUrls { - url := url - g.Go(func() error { - if err := checkUrl(url); err != nil { - lock.Lock() - notFoundUrls = append(notFoundUrls, fmt.Sprintf(">>> %s (found in file: %s)", url, urlFileMap[url])) - lock.Unlock() - } + g.Go(func() error { + return lintJSX(fileJSXMap, ctx) + }) - return nil - }) - } + g.Go(func() error { + return lintLinks(fileUrlMap, ctx) + }) if err := g.Wait(); err != nil { - return err - } - - // Print out the URLs that returned a 404 along with the file names - if len(notFoundUrls) > 0 { - for _, result := range notFoundUrls { - fmt.Println(result) - } - - return errFound404Links + return errFoundLintItems } + fmt.Println("Lint complete, no issues found.") return nil } @@ -160,59 +129,3 @@ func findFilePaths(startPath string) ([]string, error) { return filePaths, nil } - -// extractUrls extracts URLs from a file and maps them to the file -func extractUrls(filePath string) (map[string]string, error) { - file, err := os.Open(filePath) - if err != nil { - return nil, err - } - - cleanup := func() error { - if closeErr := file.Close(); closeErr != nil { - return fmt.Errorf("unable to gracefully close file, %w", closeErr) - } - return nil - } - - scanner := bufio.NewScanner(file) - urls := make(map[string]string) - - // Scan file line by line - for scanner.Scan() { - line := scanner.Text() - - // Extract links - rxStrict := xurls.Strict() - url := rxStrict.FindString(line) - - // Check for empty links and skip them - if url == " " || len(url) == 0 { - continue - } - - urls[url] = filePath - } - - return urls, cleanup() -} - -// checkUrl checks if a URL is a 404 -func checkUrl(url string) error { - // Attempt to retrieve the HTTP header - resp, err := http.Get(url) - if err != nil || resp.StatusCode == http.StatusNotFound { - return err404Link - } - - // Ensure the response body is closed properly - cleanup := func(Body io.ReadCloser) error { - if err := Body.Close(); err != nil { - return fmt.Errorf("could not close response properly: %w", err) - } - - return nil - } - - return cleanup(resp.Body) -} diff --git a/misc/docs-linter/main_test.go b/misc/docs-linter/main_test.go index ceb87fefeda..27393236215 100644 --- a/misc/docs-linter/main_test.go +++ b/misc/docs-linter/main_test.go @@ -28,45 +28,96 @@ func TestEmptyPathError(t *testing.T) { func TestExtractLinks(t *testing.T) { t.Parallel() - // Generate temporary source dir - sourceDir, err := os.MkdirTemp(".", "sourceDir") - require.NoError(t, err) - t.Cleanup(removeDir(t, sourceDir)) + // Create mock file content with random links + mockFileContent := `# Lorem Ipsum +Lorem ipsum dolor sit amet, +[consectetur](https://example.org) +adipiscing elit. Vivamus lacinia odio +vitae [vestibulum vestibulum](http://localhost:3000). +Cras [vel ex](http://192.168.1.1) et +turpis egestas luctus. Nullam +[eleifend](https://www.wikipedia.org) +nulla ac [blandit tempus](https://gitlab.org). +## Valid Links Here are some valid links: +- [Mozilla](https://mozilla.org) +- [Valid URL](https://valid-url.net) +- [Another Valid URL](https://another-valid-url.info) +- [Valid Link](https://valid-link.edu) +` + + // Expected URLs + expectedUrls := []string{ + "https://example.org", + "http://192.168.1.1", + "https://www.wikipedia.org", + "https://gitlab.org", + "https://mozilla.org", + "https://valid-url.net", + "https://another-valid-url.info", + "https://valid-link.edu", + } + + // Extract URLs from each file in the sourceDir + extractedUrls := extractUrls([]byte(mockFileContent)) - // Create mock files with random links - mockFiles := map[string]string{ - "file1.md": "This is a test file with a link: https://example.com.\nAnother link: http://example.org.", - "file2.md": "Markdown content with a link: https://example.com/page.", - "file3.md": "Links in a list:\n- https://example.com/item1\n- https://example.org/item2", + if len(expectedUrls) != len(extractedUrls) { + t.Fatal("did not extract correct amount of URLs") } - for fileName, content := range mockFiles { - filePath := filepath.Join(sourceDir, fileName) - err := os.WriteFile(filePath, []byte(content), 0644) - require.NoError(t, err) + sort.Strings(extractedUrls) + sort.Strings(expectedUrls) + + for i, u := range expectedUrls { + require.Equal(t, u, extractedUrls[i]) } +} + +func TestExtractJSX(t *testing.T) { + t.Parallel() + + // Create mock file content with random JSX tags + mockFileContent := ` +#### Usage + +### getFunctionSignatures + +Fetches public facing function signatures + +#### Parameters - // Expected URLs and their corresponding files - expectedUrls := map[string]string{ - "https://example.com": filepath.Join(sourceDir, "file1.md"), - "http://example.org": filepath.Join(sourceDir, "file1.md"), - "https://example.com/page": filepath.Join(sourceDir, "file2.md"), - "https://example.com/item1": filepath.Join(sourceDir, "file3.md"), - "https://example.org/item2": filepath.Join(sourceDir, "file3.md"), +Returns **Promise** + +# test text from gnodev.md + +#### Usage +### evaluateExpression + +Evaluates any expression in readonly mode and returns the results + +#### Parameters + +Returns **Promise** +` + + // Expected JSX tags + expectedTags := []string{ + "", + "", + "", } - // Extract URLs from each file in the sourceDir - for fileName := range mockFiles { - filePath := filepath.Join(sourceDir, fileName) - extractedUrls, err := extractUrls(filePath) - require.NoError(t, err) + // Extract JSX tags from the mock file content + extractedTags := extractJSX([]byte(mockFileContent)) - // Verify that the extracted URLs match the expected URLs - for url, expectedFile := range expectedUrls { - if expectedFile == filePath { - require.Equal(t, expectedFile, extractedUrls[url], "URL: %s not correctly mapped to file: %s", url, expectedFile) - } - } + if len(expectedTags) != len(extractedTags) { + t.Fatal("did not extract the correct amount of JSX tags") + } + + sort.Strings(extractedTags) + sort.Strings(expectedTags) + + for i, tag := range expectedTags { + require.Equal(t, tag, extractedTags[i]) } } From 6243b56858257e204bcd86c6d8d5522a8e11f691 Mon Sep 17 00:00:00 2001 From: Jae Kwon <53785+jaekwon@users.noreply.github.com> Date: Sun, 23 Jun 2024 20:15:15 -0700 Subject: [PATCH 7/9] feat: small improvements for #1702 (#2276) Also includes improved coloredbytes and debug printing, and more comments. At first I thought #1702's passing of the store was not ideal, but upon much confusion with cache invalidation, it became clear that passing in a store to getPackage() makes sense. This means that any store operations that occur through the loading of dependencies will incur gas charges for the transaction, e.g. for AddPkg() with dependencies like "time" or "strconv". Rather than clear cache-misses from the cacheStore, which is confusing, we would be better off passing in a mutated store go getPackage (if we need to). Or, just load the standard packages upon genesis. Also added improvements to ColoredBytes; this is now faster since not every character needs to be escaped, but rather escaping happens in chunks. As part of this refactor, the key & values are also clipped. I suppose we could maybe 1. improve ColoredBytesN() to clip exactly to N, but implementing this is non-trivial, and also 2. make the key/value limits perhps depend on a configuration or environment variable. Poll... would you be sad if the Print() output for databases clipped the values? I think it makes it much better for dev experience; and if you need the full value you can tinker with the source where appropriate. The downside is, we might lose information from logs. But I'm not sure we even use the Print() feature for any logs as of now. --- .gitignore | 4 ++ gno.land/pkg/gnoland/app.go | 4 +- gno.land/pkg/sdk/vm/builtins.go | 57 +++++++++++----------- gno.land/pkg/sdk/vm/keeper.go | 4 +- gnovm/pkg/gnolang/go2gno.go | 1 + gnovm/pkg/gnolang/store.go | 49 +++++++++++++------ gnovm/tests/imports.go | 24 +++++----- tm2/pkg/colors/colors.go | 74 +++++++++++++++++++++++++++-- tm2/pkg/db/goleveldb/go_level_db.go | 7 +-- tm2/pkg/db/memdb/mem_db.go | 16 ++----- tm2/pkg/db/prefix_db.go | 15 +++--- tm2/pkg/sdk/auth/ante.go | 1 - tm2/pkg/sdk/baseapp.go | 3 ++ tm2/pkg/store/cache/store.go | 44 ++++++++++++++++- tm2/pkg/store/gas/store.go | 17 +++++++ tm2/pkg/store/store.go | 26 ---------- tm2/pkg/store/types/store.go | 20 +++++++- tm2/pkg/store/utils/print.go | 38 +++++++++++++++ tm2/pkg/strings/string.go | 9 ++++ 19 files changed, 297 insertions(+), 116 deletions(-) create mode 100644 tm2/pkg/store/utils/print.go diff --git a/.gitignore b/.gitignore index 019c0be3c98..7d3f3f92b41 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,7 @@ pbbindings.go # Test coverage leftovers cover.out coverage.out + +*.swp +*.swo +*.bak diff --git a/gno.land/pkg/gnoland/app.go b/gno.land/pkg/gnoland/app.go index 7669d5cce95..8f5f33d0d9a 100644 --- a/gno.land/pkg/gnoland/app.go +++ b/gno.land/pkg/gnoland/app.go @@ -120,7 +120,9 @@ func NewAppWithOptions(cfg *AppOptions) (abci.Application, error) { } // Initialize the VMKeeper. - vmKpr.Initialize(baseApp.GetCacheMultiStore()) + ms := baseApp.GetCacheMultiStore() + vmKpr.Initialize(ms) + ms.MultiWrite() // XXX why was't this needed? return baseApp, nil } diff --git a/gno.land/pkg/sdk/vm/builtins.go b/gno.land/pkg/sdk/vm/builtins.go index 368ada6ff82..cbf6df02e93 100644 --- a/gno.land/pkg/sdk/vm/builtins.go +++ b/gno.land/pkg/sdk/vm/builtins.go @@ -5,42 +5,41 @@ import ( "path/filepath" gno "github.com/gnolang/gno/gnovm/pkg/gnolang" - "github.com/gnolang/gno/gnovm/stdlibs" "github.com/gnolang/gno/tm2/pkg/crypto" osm "github.com/gnolang/gno/tm2/pkg/os" "github.com/gnolang/gno/tm2/pkg/sdk" "github.com/gnolang/gno/tm2/pkg/std" ) -func (vm *VMKeeper) initBuiltinPackagesAndTypes(store gno.Store) { - // NOTE: native functions/methods added here must be quick operations, - // or account for gas before operation. - // TODO: define criteria for inclusion, and solve gas calculations. - getPackage := func(pkgPath string, newStore gno.Store) (pn *gno.PackageNode, pv *gno.PackageValue) { - // otherwise, built-in package value. - // first, load from filepath. - stdlibPath := filepath.Join(vm.stdlibsDir, pkgPath) - if !osm.DirExists(stdlibPath) { - // does not exist. - return nil, nil - } - memPkg := gno.ReadMemPackage(stdlibPath, pkgPath) - if memPkg.IsEmpty() { - // no gno files are present, skip this package - return nil, nil - } - - m2 := gno.NewMachineWithOptions(gno.MachineOptions{ - PkgPath: "gno.land/r/stdlibs/" + pkgPath, - // PkgPath: pkgPath, - Output: os.Stdout, - Store: newStore, - }) - defer m2.Release() - return m2.RunMemPackage(memPkg, true) +// NOTE: this function may add loaded dependencies to store if they don't +// already exist, including mem packages. If this happens during a transaction +// with the tx context store, the transaction caller will pay for operations. +// NOTE: native functions/methods added here must be quick operations, or +// account for gas before operation. +// TODO: define criteria for inclusion, and solve gas calculations(???). +func (vm *VMKeeper) getPackage(pkgPath string, store gno.Store) (pn *gno.PackageNode, pv *gno.PackageValue) { + // otherwise, built-in package value. + // first, load from filepath. + stdlibPath := filepath.Join(vm.stdlibsDir, pkgPath) + if !osm.DirExists(stdlibPath) { + // does not exist. + return nil, nil + } + memPkg := gno.ReadMemPackage(stdlibPath, pkgPath) + if memPkg.IsEmpty() { + // no gno files are present, skip this package + return nil, nil } - store.SetPackageGetter(getPackage) - store.SetNativeStore(stdlibs.NativeStore) + + m2 := gno.NewMachineWithOptions(gno.MachineOptions{ + PkgPath: "gno.land/r/stdlibs/" + pkgPath, + // PkgPath: pkgPath, + Output: os.Stdout, + Store: store, + }) + defer m2.Release() + pn, pv = m2.RunMemPackage(memPkg, true) + return } // ---------------------------------------- diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index a77ddac3e28..95f17ce09f0 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -81,7 +81,8 @@ func (vm *VMKeeper) Initialize(ms store.MultiStore) { baseSDKStore := ms.GetStore(vm.baseKey) iavlSDKStore := ms.GetStore(vm.iavlKey) vm.gnoStore = gno.NewStore(alloc, baseSDKStore, iavlSDKStore) - vm.initBuiltinPackagesAndTypes(vm.gnoStore) + vm.gnoStore.SetPackageGetter(vm.getPackage) + vm.gnoStore.SetNativeStore(stdlibs.NativeStore) if vm.gnoStore.NumMemPackages() > 0 { // for now, all mem packages must be re-run after reboot. // TODO remove this, and generally solve for in-mem garbage collection @@ -157,7 +158,6 @@ func (vm *VMKeeper) AddPackage(ctx sdk.Context, msg MsgAddPackage) (err error) { if pv := gnostore.GetPackage(pkgPath, false); pv != nil { return ErrInvalidPkgPath("package already exists: " + pkgPath) } - if gno.ReGnoRunPath.MatchString(pkgPath) { return ErrInvalidPkgPath("reserved package name: " + pkgPath) } diff --git a/gnovm/pkg/gnolang/go2gno.go b/gnovm/pkg/gnolang/go2gno.go index 4ae65211231..fa958798653 100644 --- a/gnovm/pkg/gnolang/go2gno.go +++ b/gnovm/pkg/gnolang/go2gno.go @@ -478,6 +478,7 @@ func Go2Gno(fs *token.FileSet, gon ast.Node) (n Node) { //---------------------------------------- // type checking (using go/types) +// XXX move to gotypecheck.go. // MemPackageGetter implements the GetMemPackage() method. It is a subset of // [Store], separated for ease of testing. diff --git a/gnovm/pkg/gnolang/store.go b/gnovm/pkg/gnolang/store.go index b2ec25e2778..12666c3d7ad 100644 --- a/gnovm/pkg/gnolang/store.go +++ b/gnovm/pkg/gnolang/store.go @@ -9,8 +9,12 @@ import ( "strings" "github.com/gnolang/gno/tm2/pkg/amino" + "github.com/gnolang/gno/tm2/pkg/colors" "github.com/gnolang/gno/tm2/pkg/std" "github.com/gnolang/gno/tm2/pkg/store" + "github.com/gnolang/gno/tm2/pkg/store/types" + "github.com/gnolang/gno/tm2/pkg/store/utils" + stringz "github.com/gnolang/gno/tm2/pkg/strings" ) // PackageGetter specifies how the store may retrieve packages which are not @@ -18,7 +22,8 @@ import ( // package does not exist. store should be used to run the machine, or otherwise // call any methods which may call store.GetPackage; avoid using any "global" // store as the one passed to the PackageGetter may be a fork of that (ie. -// the original is not meant to be written to). +// the original is not meant to be written to). Loading dependencies may +// cause writes to happen to the store, such as MemPackages to iavlstore. type PackageGetter func(pkgPath string, store Store) (*PackageNode, *PackageValue) // inject natives into a new or loaded package (value and node) @@ -68,6 +73,8 @@ type Store interface { LogSwitchRealm(rlmpath string) // to mark change of realm boundaries ClearCache() Print() + Write() + Flush() } // Used to keep track of in-mem objects during tx. @@ -86,7 +93,7 @@ type defaultStore struct { // transient opslog []StoreOp // for debugging and testing. - current []string + current []string // for detecting import cycles. } func NewStore(alloc *Allocator, baseStore, iavlStore store.Store) *defaultStore { @@ -115,6 +122,7 @@ func (ds *defaultStore) SetPackageGetter(pg PackageGetter) { // Gets package from cache, or loads it from baseStore, or gets it from package getter. func (ds *defaultStore) GetPackage(pkgPath string, isImport bool) *PackageValue { + // helper to detect circular imports if isImport { if slices.Contains(ds.current, pkgPath) { panic(fmt.Sprintf("import cycle detected: %q (through %v)", pkgPath, ds.current)) @@ -672,8 +680,16 @@ func (ds *defaultStore) GetNative(pkgPath string, name Name) func(m *Machine) { return nil } +// Writes one level of cache to store. +func (ds *defaultStore) Write() { + ds.baseStore.(types.Writer).Write() + ds.iavlStore.(types.Writer).Write() +} + +// Flush cached writes to disk. func (ds *defaultStore) Flush() { - // XXX + ds.baseStore.(types.Flusher).Flush() + ds.iavlStore.(types.Flusher).Flush() } // ---------------------------------------- @@ -755,22 +771,25 @@ func (ds *defaultStore) ClearCache() { // for debugging func (ds *defaultStore) Print() { - fmt.Println("//----------------------------------------") - fmt.Println("defaultStore:baseStore...") - store.Print(ds.baseStore) - fmt.Println("//----------------------------------------") - fmt.Println("defaultStore:iavlStore...") - store.Print(ds.iavlStore) - fmt.Println("//----------------------------------------") - fmt.Println("defaultStore:cacheTypes...") + fmt.Println(colors.Yellow("//----------------------------------------")) + fmt.Println(colors.Green("defaultStore:baseStore...")) + utils.Print(ds.baseStore) + fmt.Println(colors.Yellow("//----------------------------------------")) + fmt.Println(colors.Green("defaultStore:iavlStore...")) + utils.Print(ds.iavlStore) + fmt.Println(colors.Yellow("//----------------------------------------")) + fmt.Println(colors.Green("defaultStore:cacheTypes...")) for tid, typ := range ds.cacheTypes { - fmt.Printf("- %v: %v\n", tid, typ) + fmt.Printf("- %v: %v\n", tid, + stringz.TrimN(fmt.Sprintf("%v", typ), 50)) } - fmt.Println("//----------------------------------------") - fmt.Println("defaultStore:cacheNodes...") + fmt.Println(colors.Yellow("//----------------------------------------")) + fmt.Println(colors.Green("defaultStore:cacheNodes...")) for loc, bn := range ds.cacheNodes { - fmt.Printf("- %v: %v\n", loc, bn) + fmt.Printf("- %v: %v\n", loc, + stringz.TrimN(fmt.Sprintf("%v", bn), 50)) } + fmt.Println(colors.Red("//----------------------------------------")) } // ---------------------------------------- diff --git a/gnovm/tests/imports.go b/gnovm/tests/imports.go index 6a3e6ab2bbb..3dbd292ea68 100644 --- a/gnovm/tests/imports.go +++ b/gnovm/tests/imports.go @@ -61,8 +61,8 @@ const ( ) // NOTE: this isn't safe, should only be used for testing. -func TestStore(rootDir, filesPath string, stdin io.Reader, stdout, stderr io.Writer, mode importMode) (store gno.Store) { - getPackage := func(pkgPath string, newStore gno.Store) (pn *gno.PackageNode, pv *gno.PackageValue) { +func TestStore(rootDir, filesPath string, stdin io.Reader, stdout, stderr io.Writer, mode importMode) (resStore gno.Store) { + getPackage := func(pkgPath string, store gno.Store) (pn *gno.PackageNode, pv *gno.PackageValue) { if pkgPath == "" { panic(fmt.Sprintf("invalid zero package path in testStore().pkgGetter")) } @@ -83,7 +83,7 @@ func TestStore(rootDir, filesPath string, stdin io.Reader, stdout, stderr io.Wri m2 := gno.NewMachineWithOptions(gno.MachineOptions{ PkgPath: "test", Output: stdout, - Store: newStore, + Store: store, Context: ctx, }) // pkg := gno.NewPackageNode(gno.Name(memPkg.Name), memPkg.Path, nil) @@ -96,7 +96,7 @@ func TestStore(rootDir, filesPath string, stdin io.Reader, stdout, stderr io.Wri // if stdlibs package is preferred , try to load it first. if mode == ImportModeStdlibsOnly || mode == ImportModeStdlibsPreferred { - pn, pv = loadStdlib(rootDir, pkgPath, newStore, stdout) + pn, pv = loadStdlib(rootDir, pkgPath, store, stdout) if pn != nil { return } @@ -375,7 +375,7 @@ func TestStore(rootDir, filesPath string, stdin io.Reader, stdout, stderr io.Wri // if native package is preferred, try to load stdlibs/* as backup. if mode == ImportModeNativePreferred { - pn, pv = loadStdlib(rootDir, pkgPath, newStore, stdout) + pn, pv = loadStdlib(rootDir, pkgPath, store, stdout) if pn != nil { return } @@ -394,7 +394,7 @@ func TestStore(rootDir, filesPath string, stdin io.Reader, stdout, stderr io.Wri m2 := gno.NewMachineWithOptions(gno.MachineOptions{ PkgPath: "test", Output: stdout, - Store: newStore, + Store: store, Context: ctx, }) pn, pv = m2.RunMemPackage(memPkg, true) @@ -402,15 +402,15 @@ func TestStore(rootDir, filesPath string, stdin io.Reader, stdout, stderr io.Wri } return nil, nil } - // NOTE: store is also used in closure above. db := memdb.NewMemDB() baseStore := dbadapter.StoreConstructor(db, stypes.StoreOptions{}) iavlStore := iavl.StoreConstructor(db, stypes.StoreOptions{}) - store = gno.NewStore(nil, baseStore, iavlStore) - store.SetPackageGetter(getPackage) - store.SetNativeStore(teststdlibs.NativeStore) - store.SetPackageInjector(testPackageInjector) - store.SetStrictGo2GnoMapping(false) + // make a new store + resStore = gno.NewStore(nil, baseStore, iavlStore) + resStore.SetPackageGetter(getPackage) + resStore.SetNativeStore(teststdlibs.NativeStore) + resStore.SetPackageInjector(testPackageInjector) + resStore.SetStrictGo2GnoMapping(false) return } diff --git a/tm2/pkg/colors/colors.go b/tm2/pkg/colors/colors.go index d2af56c892a..84a0353d880 100644 --- a/tm2/pkg/colors/colors.go +++ b/tm2/pkg/colors/colors.go @@ -96,14 +96,80 @@ func Gray(args ...interface{}) string { return treatAll(ANSIFgGray, args...) } -func ColoredBytes(data []byte, textColor, bytesColor func(...interface{}) string) string { +// result may be 4 ASNSII chars longer than they should be to denote the +// elipses (...), and one for a trailing hex nibble in case the last byte is +// non-ascii. +// NOTE: it is annoying to try make this perfect and always fit within n, so we +// don't do this yet, but left as an exercise. :) +func ColoredBytesN(data []byte, n int, textColor, bytesColor func(...interface{}) string) string { + _n := 0 s := "" - for _, b := range data { + buf := "" // buffer + bufIsText := true // is buf text or hex + for i, b := range data { + RESTART: if 0x21 <= b && b < 0x7F { - s += textColor(string(b)) + if !bufIsText { + s += bytesColor(buf) + buf = "" + bufIsText = true + goto RESTART + } + buf += string(b) + _n += 1 + if n != 0 && _n >= n { + if i == len(data)-1 { + // done + s += textColor(buf) + buf = "" + } else { + s += textColor(buf) + "..." + buf = "" + } + break + } + } else { + if bufIsText { + s += textColor(buf) + buf = "" + bufIsText = false + goto RESTART + } + buf += fmt.Sprintf("%02X", b) + _n += 2 + if n != 0 && _n >= n { + if i == len(data)-1 { + // done + s += bytesColor(buf) + buf = "" + } else { + s += bytesColor(buf) + "..." + buf = "" + } + break + } + } + } + if buf != "" { + if bufIsText { + s += textColor(buf) + buf = "" } else { - s += bytesColor(fmt.Sprintf("%02X", b)) + s += bytesColor(buf) + buf = "" } } return s } + +func DefaultColoredBytesN(data []byte, n int) string { + return ColoredBytesN(data, n, Blue, Green) +} + +func ColoredBytes(data []byte, textColor, bytesColor func(...interface{}) string) string { + return ColoredBytesN(data, 0, textColor, bytesColor) +} + +func DefaultColoredBytes(data []byte) string { + return ColoredBytes(data, Blue, Green) +} diff --git a/tm2/pkg/db/goleveldb/go_level_db.go b/tm2/pkg/db/goleveldb/go_level_db.go index 27db61bb680..4f011cb8395 100644 --- a/tm2/pkg/db/goleveldb/go_level_db.go +++ b/tm2/pkg/db/goleveldb/go_level_db.go @@ -6,6 +6,7 @@ import ( "fmt" "path/filepath" + "github.com/gnolang/gno/tm2/pkg/colors" "github.com/gnolang/gno/tm2/pkg/db" "github.com/gnolang/gno/tm2/pkg/db/internal" "github.com/syndtr/goleveldb/leveldb" @@ -115,9 +116,9 @@ func (db *GoLevelDB) Print() { itr := db.db.NewIterator(nil, nil) for itr.Next() { - key := itr.Key() - value := itr.Value() - fmt.Printf("[%X]:\t[%X]\n", key, value) + key := colors.DefaultColoredBytesN(itr.Key(), 50) + value := colors.DefaultColoredBytesN(itr.Value(), 100) + fmt.Printf("%v: %v\n", key, value) } } diff --git a/tm2/pkg/db/memdb/mem_db.go b/tm2/pkg/db/memdb/mem_db.go index 6d1d6a35af9..09b90b6be44 100644 --- a/tm2/pkg/db/memdb/mem_db.go +++ b/tm2/pkg/db/memdb/mem_db.go @@ -5,9 +5,9 @@ import ( "sort" "sync" + "github.com/gnolang/gno/tm2/pkg/colors" dbm "github.com/gnolang/gno/tm2/pkg/db" "github.com/gnolang/gno/tm2/pkg/db/internal" - "github.com/gnolang/gno/tm2/pkg/strings" ) func init() { @@ -128,17 +128,9 @@ func (db *MemDB) Print() { for key, value := range db.db { var keystr, valstr string - if strings.IsASCIIText(key) { - keystr = key - } else { - keystr = fmt.Sprintf("0x%X", []byte(key)) - } - if strings.IsASCIIText(string(value)) { - valstr = string(value) - } else { - valstr = fmt.Sprintf("0x%X", value) - } - fmt.Printf("%s:\t%s\n", keystr, valstr) + keystr = colors.DefaultColoredBytesN([]byte(key), 50) + valstr = colors.DefaultColoredBytesN(value, 100) + fmt.Printf("%s: %s\n", keystr, valstr) } } diff --git a/tm2/pkg/db/prefix_db.go b/tm2/pkg/db/prefix_db.go index 29ed53639e8..a38850c2173 100644 --- a/tm2/pkg/db/prefix_db.go +++ b/tm2/pkg/db/prefix_db.go @@ -4,6 +4,8 @@ import ( "bytes" "fmt" "sync" + + "github.com/gnolang/gno/tm2/pkg/colors" ) // IteratePrefix is a convenience function for iterating over a key domain @@ -188,15 +190,10 @@ func (pdb *PrefixDB) Close() { // Implements DB. func (pdb *PrefixDB) Print() { - fmt.Printf("prefix: %X\n", pdb.prefix) - - itr := pdb.Iterator(nil, nil) - defer itr.Close() - for ; itr.Valid(); itr.Next() { - key := itr.Key() - value := itr.Value() - fmt.Printf("[%X]:\t[%X]\n", key, value) - } + fmt.Println(colors.Blue("prefix ---------------------")) + fmt.Printf("prefix: %v\n", colors.DefaultColoredBytes(pdb.prefix)) + pdb.db.Print() + fmt.Println(colors.Blue("prefix --------------------- end")) } // Implements DB. diff --git a/tm2/pkg/sdk/auth/ante.go b/tm2/pkg/sdk/auth/ante.go index 5066a7b1fde..49662b47a55 100644 --- a/tm2/pkg/sdk/auth/ante.go +++ b/tm2/pkg/sdk/auth/ante.go @@ -157,7 +157,6 @@ func NewAnteHandler(ak AccountKeeper, bank BankKeeperI, sigGasConsumer Signature if err != nil { return newCtx, res, true } - signerAccs[i], res = processSig(newCtx, sacc, stdSigs[i], signBytes, simulate, params, sigGasConsumer) if !res.IsOK() { return newCtx, res, true diff --git a/tm2/pkg/sdk/baseapp.go b/tm2/pkg/sdk/baseapp.go index f7c7f5c73b0..748aa424111 100644 --- a/tm2/pkg/sdk/baseapp.go +++ b/tm2/pkg/sdk/baseapp.go @@ -615,6 +615,9 @@ func (app *BaseApp) getContextForTx(mode RunTxMode, txBytes []byte) (ctx Context WithVoteInfos(app.voteInfos). WithConsensusParams(app.consensusParams) + // NOTE: This is especially required to simulate transactions because + // otherwise baseapp writes the antehandler mods (sequence and balance) + // to the underlying store for deliver and checktx. if mode == RunTxModeSimulate { ctx, _ = ctx.CacheContext() } diff --git a/tm2/pkg/store/cache/store.go b/tm2/pkg/store/cache/store.go index 1c5c2e27783..6bc6ad3b71f 100644 --- a/tm2/pkg/store/cache/store.go +++ b/tm2/pkg/store/cache/store.go @@ -3,13 +3,17 @@ package cache import ( "bytes" "container/list" + "fmt" + "reflect" "sort" "sync" + "github.com/gnolang/gno/tm2/pkg/colors" dbm "github.com/gnolang/gno/tm2/pkg/db" "github.com/gnolang/gno/tm2/pkg/std" "github.com/gnolang/gno/tm2/pkg/store/types" + "github.com/gnolang/gno/tm2/pkg/store/utils" ) // If value is nil but deleted is false, it means the parent doesn't have the @@ -20,6 +24,12 @@ type cValue struct { dirty bool } +func (cv cValue) String() string { + return fmt.Sprintf("cValue{%s,%v,%v}", + colors.DefaultColoredBytes(cv.value), + cv.deleted, cv.dirty) +} + // cacheStore wraps an in-memory cache around an underlying types.Store. type cacheStore struct { mtx sync.Mutex @@ -32,12 +42,13 @@ type cacheStore struct { var _ types.Store = (*cacheStore)(nil) func New(parent types.Store) *cacheStore { - return &cacheStore{ + cs := &cacheStore{ cache: make(map[string]*cValue), unsortedCache: make(map[string]struct{}), sortedCache: list.New(), parent: parent, } + return cs } // Implements types.Store. @@ -112,6 +123,17 @@ func (store *cacheStore) Write() { } // Clear the cache + store.clear() +} + +func (store *cacheStore) Flush() { + store.Write() + if fs, ok := store.parent.(types.Flusher); ok { + fs.Flush() + } +} + +func (store *cacheStore) clear() { store.cache = make(map[string]*cValue) store.unsortedCache = make(map[string]struct{}) store.sortedCache = list.New() @@ -209,3 +231,23 @@ func (store *cacheStore) setCacheValue(key, value []byte, deleted bool, dirty bo store.unsortedCache[string(key)] = struct{}{} } } + +func (store *cacheStore) Print() { + fmt.Println(colors.Cyan("cacheStore.Print"), fmt.Sprintf("%p", store)) + for key, value := range store.cache { + fmt.Println( + colors.DefaultColoredBytesN([]byte(key), 50), + colors.DefaultColoredBytesN(value.value, 100), + "deleted", value.deleted, + "dirty", value.dirty, + ) + } + fmt.Println(colors.Cyan("cacheStore.Print"), fmt.Sprintf("%p", store), + "print parent", fmt.Sprintf("%p", store.parent), reflect.TypeOf(store.parent)) + if ps, ok := store.parent.(types.Printer); ok { + ps.Print() + } else { + utils.Print(store.parent) + } + fmt.Println(colors.Cyan("cacheStore.Print END"), fmt.Sprintf("%p", store)) +} diff --git a/tm2/pkg/store/gas/store.go b/tm2/pkg/store/gas/store.go index 4ffe46dc275..db5ea7a79b0 100644 --- a/tm2/pkg/store/gas/store.go +++ b/tm2/pkg/store/gas/store.go @@ -2,6 +2,7 @@ package gas import ( "github.com/gnolang/gno/tm2/pkg/store/types" + "github.com/gnolang/gno/tm2/pkg/store/utils" "github.com/gnolang/overflow" ) @@ -100,6 +101,22 @@ func (gs *Store) iterator(start, end []byte, ascending bool) types.Iterator { return gi } +func (gs *Store) Print() { + if ps, ok := gs.parent.(types.Printer); ok { + ps.Print() + } else { + utils.Print(gs.parent) + } +} + +func (gs *Store) Flush() { + if cts, ok := gs.parent.(types.Flusher); ok { + cts.Flush() + } else { + panic("underlying store does not implement Flush()") + } +} + type gasIterator struct { gasMeter types.GasMeter gasConfig types.GasConfig diff --git a/tm2/pkg/store/store.go b/tm2/pkg/store/store.go index 2950937f951..ba939fa1793 100644 --- a/tm2/pkg/store/store.go +++ b/tm2/pkg/store/store.go @@ -1,10 +1,7 @@ package store import ( - "fmt" - dbm "github.com/gnolang/gno/tm2/pkg/db" - "github.com/gnolang/gno/tm2/pkg/strings" "github.com/gnolang/gno/tm2/pkg/store/rootmulti" "github.com/gnolang/gno/tm2/pkg/store/types" @@ -27,26 +24,3 @@ func NewPruningOptionsFromString(strategy string) (opt PruningOptions) { } return } - -// TODO move to another file. -func Print(store Store) { - fmt.Println("//----------------------------------------") - fmt.Println("// store:", store) - itr := store.Iterator(nil, nil) - defer itr.Close() - for ; itr.Valid(); itr.Next() { - key, value := itr.Key(), itr.Value() - var keystr, valuestr string - if strings.IsASCIIText(string(key)) { - keystr = string(key) - } else { - keystr = fmt.Sprintf("0x%X", key) - } - if strings.IsASCIIText(string(value)) { - valuestr = string(value) - } else { - valuestr = fmt.Sprintf("0x%X", value) - } - fmt.Printf("%s: %s\n", keystr, valuestr) - } -} diff --git a/tm2/pkg/store/types/store.go b/tm2/pkg/store/types/store.go index 68ee110586c..a0e3925a265 100644 --- a/tm2/pkg/store/types/store.go +++ b/tm2/pkg/store/types/store.go @@ -40,7 +40,8 @@ type Store interface { // Returns a cache-wrapped store. CacheWrap() Store - // If cache-wrapped store, flushes to underlying store. + // If cache-wrapped store, writes to underlying store. + // Does not writes through layers of cache. Write() } @@ -55,6 +56,23 @@ type Queryable interface { Query(abci.RequestQuery) abci.ResponseQuery } +// Useful for debugging. +type Printer interface { + Print() +} + +// Write through all caches. +// You probably don't want this, rather write your program to Write() where +// appropriate. Not included in the main Store interface to discourage usage. +type Flusher interface { + Flush() +} + +// Write throgh +type Writer interface { + Write() +} + // ---------------------------------------- // MultiStore diff --git a/tm2/pkg/store/utils/print.go b/tm2/pkg/store/utils/print.go new file mode 100644 index 00000000000..d47f4188db7 --- /dev/null +++ b/tm2/pkg/store/utils/print.go @@ -0,0 +1,38 @@ +package utils + +import ( + "fmt" + "reflect" + + "github.com/gnolang/gno/tm2/pkg/colors" + "github.com/gnolang/gno/tm2/pkg/store/types" +) + +// TODO move to another file. +func Print(store types.Store) { + fmt.Println(colors.Blue("//----------------------------------------")) + if store == nil { + fmt.Println("") + } else if ps, ok := store.(types.Printer); ok { + ps.Print() + } else { + fmt.Println(colors.Blue(fmt.Sprintf("// store:%p %v", store, reflect.TypeOf(store)))) + itr := store.Iterator(nil, nil) + defer itr.Close() + for ; itr.Valid(); itr.Next() { + key, value := itr.Key(), itr.Value() + var keystr, valuestr string + keystr = colors.DefaultColoredBytesN(key, 100) + valuestr = fmt.Sprintf("(%d)", len(value)) + /* + if true || strings.IsASCIIText(string(value)) { + valuestr = string(value) + } else { + valuestr = fmt.Sprintf("0x%X", value) + } + */ + fmt.Printf("%s: %s\n", keystr, valuestr) + } + } + fmt.Println(colors.Blue("//------------------------------------ end")) +} diff --git a/tm2/pkg/strings/string.go b/tm2/pkg/strings/string.go index 46675923319..86ed70373a3 100644 --- a/tm2/pkg/strings/string.go +++ b/tm2/pkg/strings/string.go @@ -75,3 +75,12 @@ func StringSliceEqual(a, b []string) bool { } return true } + +// TrimN naively appens "..." to fit within n bytes. +func TrimN(s string, n int) string { + if len(s) <= n { + return s + } else { + return s[:n-3] + "..." + } +} From 900bb2ff22a52034492d0850f4bf3a3250e59208 Mon Sep 17 00:00:00 2001 From: Jeff Thompson Date: Mon, 24 Jun 2024 11:50:58 +0200 Subject: [PATCH 8/9] chore(examples): In r/demo/boards public API, change AssertOriginCall() to PrevRealm().IsUser() (#2358) In r/demo/boards, `std.AssertOriginCall()` blocks calling the API from another realm. But it also prevents using MsgRun for testing as we do in PR #1583. Therefore, we change to check `std.PrevRealm().IsUser()`. This still blocks another realm from calling the code, but allows being [called by MsgRun](https://github.com/gnolang/gno/blob/d7f12167eff72cd4a12e9e8b8aaa30dc241bfb6c/misc/stress-test/stress-test-many-posts/main.go#L148-L156) where a user keypair sends the transaction.
Contributors' checklist... - [x] Added new tests, or not needed, or not feasible - [x] Provided an example (e.g. screenshot) to aid review or the PR is self-explanatory - [x] Updated the official documentation or not needed - [x] No breaking changes were made, or a `BREAKING CHANGE: xxx` message was included in the description - [x] Added references to related issues and PRs
--------- Signed-off-by: Jeff Thompson Co-authored-by: Leon Hudak <33522493+leohhhn@users.noreply.github.com> --- examples/gno.land/r/demo/boards/public.gno | 24 ++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/examples/gno.land/r/demo/boards/public.gno b/examples/gno.land/r/demo/boards/public.gno index 1ef2e72f4c2..1d26126fcb2 100644 --- a/examples/gno.land/r/demo/boards/public.gno +++ b/examples/gno.land/r/demo/boards/public.gno @@ -17,7 +17,9 @@ func GetBoardIDFromName(name string) (BoardID, bool) { } func CreateBoard(name string) BoardID { - std.AssertOriginCall() + if !(std.IsOriginCall() || std.PrevRealm().IsUser()) { + panic("invalid non-user call") + } bid := incGetBoardID() caller := std.GetOrigCaller() if usernameOf(caller) == "" { @@ -41,7 +43,9 @@ func checkAnonFee() bool { } func CreateThread(bid BoardID, title string, body string) PostID { - std.AssertOriginCall() + if !(std.IsOriginCall() || std.PrevRealm().IsUser()) { + panic("invalid non-user call") + } caller := std.GetOrigCaller() if usernameOf(caller) == "" { if !checkAnonFee() { @@ -57,7 +61,9 @@ func CreateThread(bid BoardID, title string, body string) PostID { } func CreateReply(bid BoardID, threadid, postid PostID, body string) PostID { - std.AssertOriginCall() + if !(std.IsOriginCall() || std.PrevRealm().IsUser()) { + panic("invalid non-user call") + } caller := std.GetOrigCaller() if usernameOf(caller) == "" { if !checkAnonFee() { @@ -85,7 +91,9 @@ func CreateReply(bid BoardID, threadid, postid PostID, body string) PostID { // If dstBoard is private, does not ping back. // If board specified by bid is private, panics. func CreateRepost(bid BoardID, postid PostID, title string, body string, dstBoardID BoardID) PostID { - std.AssertOriginCall() + if !(std.IsOriginCall() || std.PrevRealm().IsUser()) { + panic("invalid non-user call") + } caller := std.GetOrigCaller() if usernameOf(caller) == "" { // TODO: allow with gDefaultAnonFee payment. @@ -113,7 +121,9 @@ func CreateRepost(bid BoardID, postid PostID, title string, body string, dstBoar } func DeletePost(bid BoardID, threadid, postid PostID, reason string) { - std.AssertOriginCall() + if !(std.IsOriginCall() || std.PrevRealm().IsUser()) { + panic("invalid non-user call") + } caller := std.GetOrigCaller() board := getBoard(bid) if board == nil { @@ -143,7 +153,9 @@ func DeletePost(bid BoardID, threadid, postid PostID, reason string) { } func EditPost(bid BoardID, threadid, postid PostID, title, body string) { - std.AssertOriginCall() + if !(std.IsOriginCall() || std.PrevRealm().IsUser()) { + panic("invalid non-user call") + } caller := std.GetOrigCaller() board := getBoard(bid) if board == nil { From bedd0f9171d9a3ef66a0afb955842abdfe07f21e Mon Sep 17 00:00:00 2001 From: deelawn Date: Mon, 24 Jun 2024 14:51:08 +0100 Subject: [PATCH 9/9] fix: allow LICENSE rendering via gnoweb (#2417) We allow LICENSE files to be included when adding packages, so we should also allow them to be viewed via gnoweb.
Contributors' checklist... - [x] Added new tests, or not needed, or not feasible - [x] Provided an example (e.g. screenshot) to aid review or the PR is self-explanatory - [x] Updated the official documentation or not needed - [x] No breaking changes were made, or a `BREAKING CHANGE: xxx` message was included in the description - [x] Added references to related issues and PRs - [x] Provided any useful hints for running manual tests - [x] 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).
--- .../p/demo/flow/{LICENSE.md => LICENSE} | 0 gno.land/pkg/gnoweb/gnoweb.go | 2 +- gno.land/pkg/gnoweb/gnoweb_test.go | 2 +- tm2/pkg/std/memfile.go | 15 ++++-- tm2/pkg/std/memfile_test.go | 51 +++++++++++++++++++ 5 files changed, 63 insertions(+), 7 deletions(-) rename examples/gno.land/p/demo/flow/{LICENSE.md => LICENSE} (100%) diff --git a/examples/gno.land/p/demo/flow/LICENSE.md b/examples/gno.land/p/demo/flow/LICENSE similarity index 100% rename from examples/gno.land/p/demo/flow/LICENSE.md rename to examples/gno.land/p/demo/flow/LICENSE diff --git a/gno.land/pkg/gnoweb/gnoweb.go b/gno.land/pkg/gnoweb/gnoweb.go index d8919fb0913..b997de7840d 100644 --- a/gno.land/pkg/gnoweb/gnoweb.go +++ b/gno.land/pkg/gnoweb/gnoweb.go @@ -111,7 +111,7 @@ func MakeApp(logger *slog.Logger, cfg Config) gotuna.App { } // realm routes // NOTE: see rePathPart. - app.Router.Handle("/r/{rlmname:[a-z][a-z0-9_]*(?:/[a-z][a-z0-9_]*)+}/{filename:(?:.*\\.(?:gno|md|txt|mod)$)?}", handlerRealmFile(logger, app, &cfg)) + app.Router.Handle("/r/{rlmname:[a-z][a-z0-9_]*(?:/[a-z][a-z0-9_]*)+}/{filename:(?:(?:.*\\.(?:gno|md|txt|mod)$)|(?:LICENSE$))?}", handlerRealmFile(logger, app, &cfg)) app.Router.Handle("/r/{rlmname:[a-z][a-z0-9_]*(?:/[a-z][a-z0-9_]*)+}", handlerRealmMain(logger, app, &cfg)) app.Router.Handle("/r/{rlmname:[a-z][a-z0-9_]*(?:/[a-z][a-z0-9_]*)+}:{querystr:.*}", handlerRealmRender(logger, app, &cfg)) app.Router.Handle("/p/{filepath:.*}", handlerPackageFile(logger, app, &cfg)) diff --git a/gno.land/pkg/gnoweb/gnoweb_test.go b/gno.land/pkg/gnoweb/gnoweb_test.go index 55434e3b9fc..d6b93b37d69 100644 --- a/gno.land/pkg/gnoweb/gnoweb_test.go +++ b/gno.land/pkg/gnoweb/gnoweb_test.go @@ -46,6 +46,7 @@ func TestRoutes(t *testing.T) { {"/%ED%85%8C%EC%8A%A4%ED%8A%B8", notFound, "/테스트"}, {"/グノー", notFound, "/グノー"}, {"/⚛️", notFound, "/⚛️"}, + {"/p/demo/flow/LICENSE", ok, "BSD 3-Clause"}, } config, _ := integration.TestingNodeConfig(t, gnoenv.RootDir()) @@ -67,7 +68,6 @@ func TestRoutes(t *testing.T) { response := httptest.NewRecorder() app.Router.ServeHTTP(response, request) assert.Equal(t, r.status, response.Code) - assert.Contains(t, response.Body.String(), r.substring) }) } diff --git a/tm2/pkg/std/memfile.go b/tm2/pkg/std/memfile.go index f41619b56bd..ce73995a22a 100644 --- a/tm2/pkg/std/memfile.go +++ b/tm2/pkg/std/memfile.go @@ -90,18 +90,23 @@ func (mempkg *MemPackage) Validate() error { return nil } +const licenseName = "LICENSE" + // Splits a path into the dirpath and filename. func SplitFilepath(filepath string) (dirpath string, filename string) { parts := strings.Split(filepath, "/") if len(parts) == 1 { return parts[0], "" } - last := parts[len(parts)-1] - if strings.Contains(last, ".") { + + switch last := parts[len(parts)-1]; { + case strings.Contains(last, "."): return strings.Join(parts[:len(parts)-1], "/"), last - } else if last == "" { + case last == "": return strings.Join(parts[:len(parts)-1], "/"), "" - } else { - return strings.Join(parts, "/"), "" + case last == licenseName: + return strings.Join(parts[:len(parts)-1], "/"), licenseName } + + return strings.Join(parts, "/"), "" } diff --git a/tm2/pkg/std/memfile_test.go b/tm2/pkg/std/memfile_test.go index 7b944f75c4f..3e1fb49e131 100644 --- a/tm2/pkg/std/memfile_test.go +++ b/tm2/pkg/std/memfile_test.go @@ -270,3 +270,54 @@ func TestMemPackage_Validate(t *testing.T) { }) } } + +func TestSplitFilepath(t *testing.T) { + t.Parallel() + tests := []struct { + name string + filepath string + expDirPath string + expFilename string + }{ + { + name: "empty", + }, + { + name: "one part", + filepath: "root", + expDirPath: "root", + }, + { + name: "file", + filepath: "gno.land/r/demo/avl/avl.gno", + expDirPath: "gno.land/r/demo/avl", + expFilename: "avl.gno", + }, + { + name: "trailing slash", + filepath: "gno.land/r/demo/avl/", + expDirPath: "gno.land/r/demo/avl", + }, + { + name: "license", + filepath: "gno.land/r/demo/avl/LICENSE", + expDirPath: "gno.land/r/demo/avl", + expFilename: "LICENSE", + }, + { + name: "regular path", + filepath: "gno.land/p/demo/avl", + expDirPath: "gno.land/p/demo/avl", + }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + dirPath, filename := SplitFilepath(tt.filepath) + assert.Equal(t, tt.expDirPath, dirPath) + assert.Equal(t, tt.expFilename, filename) + }) + } +}