Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gas fees for gno.land versus transaction for calls to Render(path string) #947

Closed
schollz opened this issue Jul 4, 2023 · 4 comments
Closed

Comments

@schollz
Copy link
Contributor

schollz commented Jul 4, 2023

When browsing gno.land realms, the realms are essentially calling the Render(path string) function based on a path in the browser, e.g.: https://test3.gno.land/r/demo/users calls this function.

The same thing can be done on the command line, but in this case it will require using Gas:

> gnokey maketx call --pkgpath "gno.land/r/demo/users" --func "Render" --args "" --gas-fee "1000000ugnot" --gas-wanted "8000000" --broadcast --chainid dev --remote localhost:26657  --insecure-password-stdin=true zzkey1   

Enter password.
(" * [administrator](/r/demo/users:administrator)\n * [anarcher](/r/demo/users:anarcher)\n * [ideamour](/r/demo/users:ideamour)\n * [manfred](/r/demo/users:manfred)\n * [piupiu](/r/demo/users:piupiu)\n * [zo_oma](/r/demo/users:zo_oma)\n" string)
OK!
GAS WANTED: 8000000
GAS USED:   227586

Is there a command-line way of calling the specific Render(path string) function without having to have a Gas fee? Otherwise it seems like it might be viable for someone to make gas-free API calls to gno.land and parse the returned HTML for the response. Or, in the future, is it that the gno.land browsing will require gas?

@thehowl
Copy link
Member

thehowl commented Jul 4, 2023

The direct answer to the question is that there is a way to call Render without using gas (after all, gnoweb is in essence a frontend to the RPC API). The logic is in handleRealmRender, but in essence, we can do this:

$ gnokey query --data 'gno.land/r/gnoland/blog'$'\n' --remote test3.gno.land:36657 vm/qrender
height: 0
data: # Gnoland's Blog

## [▸ Announcing the Gno.land Funding and Grants Program](/r/gnoland/blog:p/funding-program)

## [▸ Gno.land Community Game of Realms AMA #1 - Recap](/r/gnoland/blog:p/gor-ama1)

## [▸ Game of Realms Is On: Win Rewards for Contributing to Gno.land](/r/gnoland/blog:p/gor-launch)

## [▸ All You Need to Know About Game of Realms: Phase One](/r/gnoland/blog:p/gor-phase1)

## [▸ Intro to Gnoland - The Smart Contract Platform to Improve Our Understanding of the World](/r/gnoland/blog:p/intro)

## [▸ The More You Gno: Gno.land Monthly Updates](/r/gnoland/blog:p/monthly-dev-1)

## [▸ The More You Gno: Gno.land Monthly Updates - 2](/r/gnoland/blog:p/monthly-dev-2)

## [▸ Gno.land Community Technical AMA #1 - Recap](/r/gnoland/blog:p/tech-ama1)


$ gnokey query --data 'gno.land/r/gnoland/blog'$'\n''p/funding-program' --remote test3.gno.land:36657 vm/qrender
height: 0
data: # [Gnoland's Blog](/r/gnoland/blog:) / p / Announcing the Gno.land Funding and Grants Program

If you’re interested in building in Gno.land and using the Gnolang (Gno) language [...]

One key difference (AFAIK, either current or desired) between Render and a tx call is that Render cannot modify state when called outside a transaction. So this makes the whole content of a realm's state read-only. And currently a call to Render still "uses" gas in terms of CPU cycles that need to be run on one node, which does open up a possibility for abuse if the Render function does more than a simple markdown rendering of content but requires instead complex computation. The same could be said about vm/qeval, which kind of allows to do the same thing.

Seeing as these are essentially public API calls, potentially exploitable, we'll probably need to figure out a good strategy before mainnet.


Related: #649

@schollz
Copy link
Contributor Author

schollz commented Jul 6, 2023

Thanks @thehowl, that is super helpful. I was thinking of prototyping a Gno-backed database, using the smart-contract to store data but utilizing the gas-free reads. The gas-free reading in that is really nice.

As a manner of exploits, it is less nice - one could make a realm that just causes CPU overruns and hits allocation limits:

package crash

func Render(p string) string {
	s := ""
	if p == "cpuoverrun" {
		for {
		}
	} else if p == "allocationlimit" {
		for {
			s += "z"
		}
	}
	return s
}

which is easily spammed from gno.land. The exploit itself is annoying, but, to me, the main issue it brings is the level of allocation limit and level CPU overrun and the tradeoff with normal code. Currently the Gno limits seem reasonable as protection, but I have run up against them already once or twice with normal code.

I don't know how it could be done, but I wish there was a way to have higher limits for "safe" code and tighter limits on "dubious"/"exploitive" code.

@thehowl
Copy link
Member

thehowl commented Jul 6, 2023

I don't know how it could be done, but I wish there was a way to have higher limits for "safe" code and tighter limits on "dubious"/"exploitive" code.

Well, it's hard to do. Probably things which are "expensive" to generate (like bytebeat audio) should be generated by the author (or by a paying tx, anyway), and instead public RPC calls follow the normal path for web2 like I suggested on #649: rate limiting.

public operations which are not transactions should probably be either removed before mainnet or limited in some way for safety. (ie. rate-limit cycles/allocs per ip per hour, make them in general low-priority so that blockchain TXs are executed first).

@moul moul moved this to 🌟 Wanted for Launch in 🚀 The Launch [DEPRECATED] Sep 5, 2023
@moul moul added this to the 🌟 main.gno.land (wanted) milestone Sep 8, 2023
moul added a commit that referenced this issue Sep 16, 2023
This realm implements the `avl.Tree` as a user-addressable key-store. I
wanted to have this realm to possibly use `gno.land` as a database where
writes may cost gnots but reads are free because they can be performed
through `Render` (related discussion:
#947). As a nice additional feature
it provides a UI for the database (through `gno.land`).

Data can be set/removed if the caller is the same as the owner of the
key-store (i.e. only owner's have write-access). For example:

```bash
# Set key,value for user at YOURKEY (write-protected)
gnokey maketx call --pkgpath "gno.land/r/demo/keystore" \
--func "Set" --args "hello" --args "world" \
--gas-fee "1000000ugnot" --gas-wanted "8000000" \
--broadcast --chainid dev --remote localhost:26657 YOURKEY
```

```bash
# Remove key for user at YOURKEY (write-protected)
gnokey maketx call --pkgpath "gno.land/r/demo/keystore" \
--func "Remove" --args "hello"  \
--gas-fee "1000000ugnot" --gas-wanted "8000000" \
--broadcast --chainid dev --remote localhost:26657 YOURKEY
```

```bash
# Get key
gnokey maketx call --pkgpath "gno.land/r/demo/keystore" \
--func "Get" --args "hello"  \
--gas-fee "1000000ugnot" --gas-wanted "8000000" \
--broadcast --chainid dev --remote localhost:26657 YOURKEY
```

All data is public and accessible as read-only from any user, as well as
from gno.land.

The main page lists all the available databases by owner
(`/r/demo/keystore`):


![image](https://github.com/gnolang/gno/assets/6550035/3e21827c-0a22-47eb-bf42-53f6ee005a7e)

Clicking on a user will show all the keys in their key-store
(`/r/demo/keystore:USER`):


![image](https://github.com/gnolang/gno/assets/6550035/7d4b3d58-20ad-47fc-8e41-095e111f5f30)

And the key values are accessible as well
(`r/demo/keystore:USER:get:KEY`)


![image](https://github.com/gnolang/gno/assets/6550035/888a8ddf-6044-42d4-aed6-ffc3989def35)





## 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](../.benchmarks/README.md).

## Maintainers Checklist

- [ ] Checked that the author followed the guidelines in
`CONTRIBUTING.md`
- [ ] Checked the conventional-commit (especially PR title and verb,
presence of `BREAKING CHANGE:` in the body)
- [ ] Ensured that this PR is not a significant change or confirmed that
the review/consideration process was appropriate for the change

---------

Co-authored-by: Manfred Touron <[email protected]>
@leohhhn
Copy link
Contributor

leohhhn commented May 28, 2024

Related: #1523

TL:DR any exported function will use gas if called with maketx call or maketx run. The way to avoid this is to use the gnokey query command. Upper limit on query computation is being discussed.

@leohhhn leohhhn closed this as completed May 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: 🌟 Wanted for Launch
Development

No branches or pull requests

4 participants