Additional Abilities for Scripts

Right now, we more or less have two execution environments for Cadence (on the live network, not counting playground/emulator). We have the smart contract and transaction environment used to update the chain, and we have the scripting environment used for querying the chain. Currently, the differences between those two environments are minimal; and basically come down to “can you update the execution state?”

I have a couple of ideas for additional differences that could make the scripting environment more useful.

First: The “normal rules” of Cadence access control could be suspended in the scripting environment. This would allow any script to read any state in any account. Because there’s no way for that code to make changes to the on-chain state, there’s no reason why we should block access to any data, since all of that state is knowable off-chain anyway. This wouldn’t be a trivial change, since it would ideally “break” the normal rules of Cadence against down-casting, and accessing non-public variables, and would also let a script access any AuthAccount. (I know! It sounds scary at first. But think it through, it’s not as crazy at it might seem!)

Second: There is an approach for building dapps in a very “pure” way. The idea is that your dapp can be implemented as an entirely stateless web app. The only code is the smart contracts that live on chain and all client code is a bunch of static JS/HTML files on a server somewhere (or something like IPFS). We’re seeing this approach being used with some defi projects, for example.

The problem with this “pure dapp” vision is that there are certain read-only access patterns that are hard to implement efficiently this way. Consider a simple CryptoKitties gene-browser dapp; it just lets you look at the genes of any Kitty in existence. If you wanted to give the user the ability to search for cats by trait combinations, you’d either have to build some kind of search index on-chain (OOF!), or query and compare the search attributes against every single one of the 2M cats in existence from JS code running in a browser. (Double OOF!!)

So, here is the second idea. What if code running in the scripting environment could have some off-chain state to which it had both read and write access to? Give the scripting environment the ability to store data, but data that ONLY lives on the Access Node. And not all Access Nodes, just the ones that had been asked to run that script.

This should give developers the ability to build something that is deployed as static code (“a pure dapp”), while still allowing efficient data access capabilities. Obviously, the ANs would need to charge for the computational and storage costs of running scripts and storing the off-chain state, but those costs are likely to be a fraction of the cost of on-chain storage and computation. And, of course, a dapp developer could run their own AN, or get a contract with some company that provides monthly access to ANs as a service.

An open question is whether or not it makes sense to use these “stateful scripts” to store data that can’t be regenerated from on-chain data. In my example above, the Kitty index could be many times bigger (in terms of raw data storage) than the baseline Kitty data on chain, but it could always be recreated as a new projection if the AN went down or if the dapp developer/user switched to a different AN. I think that use case is really powerful.

But storing data that can’t be derived from on-chain information might also be useful. Imagine a dapp that let you choose between different interface skins (like a “dark mode”). Storing the selected skin on-chain seems potentially like overkill, but asking the user to chose their skin each time they log in (or the AN gets rebooted) seems unfortunate also.

5 Likes

@dete you’ve invented the new web.
I like both ideas.

Idea 1: makes sense to allow everyone to read everything as data is public anyway.
Idea 2: looks like “local storage” , would encourage to run an access node. I picture it like a nosql datastore, with the ability to declare an index for some of the fields. Maybe one of the field types could be blob, to store byte data.

1 Like

I think this is a pretty good idea. Making dapps even more serverless and make it easier to build and operate dapps.

I think another piece in the puzzle is to have a better integration with data storage and make it seamless to link the file object hash on chain with acutal data on storage and execution state in ANs.
Together this can probably take over 95% of the work cloud services do.

1 Like

Exactly, Hsuan! This is more or less the purpose of resource IDs in Cadence (also called UUIDs, even though they aren’t really universally unique… :sweat_smile:). The point of a resource iD is that you can follow on-chain objects in an off-chain data store, even as the on-chain asset evolves and moves around.

2 Likes

@dete

First:
Great idea! I don’t feel any negative side effects.

Second:
Syncing on-chain data to cloud databases is always a headache for us.

We are running the NFT marketplace “miime.io,” and we store all the minted NFT’s metadata. Some of the big titles like Gods Unchained, has more than 5 million tokens already minted. And when we tried to fetch metadata of all the tokens, it took us a week…

So if there is any service which we can query NFT by its owner information or some of the metadata’s property, and if it is provided as an interface similar to web-API or fcl, it is really great!!

1 Like

@dete
I totally agree with the first idea! Hiding the value of a private variable is not really possible.

As for the second idea, I understood it to be about making the access node function like Redis.
From the Dapps development side, this is very convenient and attractive. But I know that the amount of data in the NFT metadata can be very large in games with a large number of NFTs issued, so I’m concerned that this will increase the load on the access node. I think we need a project like Ethereum’s The Graph to implement functions like search.

1 Like

Hi, @dete I would like to follow up on the discussion to see if there is any update on relaxing the scripting environment. The Flow blockchain is not built as a privacy-preserving blockchain, so the private field and state are used for write protection and not read protection (unless you encrypt the data). So, relaxing Cadence access control for reading access makes sense for the scripting environment.

As for your second idea, to allow read and write access for off-chain data stored with an access node that has a relaxed environment to run the script, I want to make sure the write operation does not impact any on-chain state. Otherwise, we will have sync issues.