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

Expose blockhash in ink! #1849

Closed
ltfschoen opened this issue Jul 18, 2023 · 13 comments
Closed

Expose blockhash in ink! #1849

ltfschoen opened this issue Jul 18, 2023 · 13 comments
Labels
A-ink_env [ink_env] work item C-discussion An issue for discussion for a given topic.

Comments

@ltfschoen
Copy link
Contributor

ltfschoen commented Jul 18, 2023

In the comments of the Stack Exchange answer here I've provided links to a Flipper Game written in Solidity where i get the previous block hash with blockhash(blockNumber - 1); and I also provide a link to the same Flipper Game written in ink!, but I don't know how to get the previous block hash using ink!

If I use a chain extension https://use.ink/macros-attributes/chain-extension/ then to get the block hash from a given block number I would have to modify the blockchain itself (which may not even be my own) through an on-chain upgrade and governance, and that might not be a permissionless process, and governance might even reject the proposal.

I'm also aware that there's an RPC endpoint here to get the block hash from a given block number, but I just want to be able to get it from the ink! smart contract itself.

So I'd like to be able to permissionlessly get the previous block hash of the chain that i've deployed an ink! smart contract on, directly from the ink! smart contract itself, like it's possible to do using Solidity.

Could anyone please provide guidance on how I could go about doing that?

@ltfschoen
Copy link
Contributor Author

@PierreOssun mentioned that the environment API for ink! is here for constructor is Self::env().block_number() or self::env().block_number()

So an additional environment function in constructor could be Self::env().block_hash(Self::env().block_number - 1)

@ltfschoen
Copy link
Contributor Author

ltfschoen commented Jul 18, 2023

For my specific use case i just realised that whilst this feature would be ideal i can get by with my existing solution, where i'm generating a source of randomness in the future from a future block hash, but only after it has occurred, and where the user provides the block hash as an argument to an ink! function set_block_for_entropy_for_market_id here, which i'm calling from a bash script at the moment here but that could become a call from a front-end.

The issue with my current solution is that whilst it provides a source of randomness, if it was used for a guessing game then i would need oracles or on-chain governance to verify that the block hash provided was a block hash that actually exists before a releasing a prize to the winner.

Another way around this to be able to access the blockhash could be to do the following, which is what i'll try next:

  • Deployed the FlipperGame flipper_game/lib.rs ink! smart contract on a on a chain like Astar that allows deployment of both ink! and Solidity EVM contracts, as well as supports cross-contract calls, and create another Solidity contract that it depends on that could be called FlipperGameBlockHash.sol, and it's sole purpose would be to provide a getter that returns the current or previous block hash with blockhash(blockNumber - 1); of the chain (i.e. Astar) that it was deployed on, and then in the calling function of the FlipperGame ink! contract i could use the Astar XVM SDK to call that getter in the Solidity FlipperGameBlockHash.sol contract and then decode it in ink! like in this example that @PierreOssun mentioned https://github.com/AstarNetwork/ink-xvm-sdk/blob/18944607edb83a61e9a016eb588c5ee0804f2c70/contracts/erc20/lib.rs#L53

So this solution to getting the blockhash should already work if:

  • Both the ink! contract FlipperGame and Solidity contract FlipperGameBlockHash.sol were deployed on Astar (or their testnets), since that parachain supports both ink! WASM and Solidity EVM contracts, and cross-contract calls are allowed, so i could get the blockhash in the dedicated Solidity contract deployed on the same chain

In future, when XCM is finalised then other chains that may still only support ink! WASM contracts could make cross-chain cross-contract calls to another chain that supports Solidity EVM contracts so they could get a blockhash as a source of randomness from that other chain trustlessly, or possibly even get a source of randomness from randomness precompile contracts on other chains like Moonbeam.

Or if someone works on this issue and allows ink! WASM smart contracts to access an environment function that gets the block hash for the a given current or previous block like is already possible in Solidity.

To provide some context, i was actually only getting the previous block hash here in a createGame function and that worked in Solidity, and i was using that to refer to the block hash when a guessing game started, but there's no reason why i can't just use the block number instead since it is obtained from in the Solidity function itself.
i re-wrote that contract in ink! here, but did not know the equivalent way to get the block hash

@ltfschoen
Copy link
Contributor Author

ltfschoen commented Jul 21, 2023

In the interim I've tried using XVM with Shibuya in this PR ltfschoen/XCMTemplate#24
Still draft, i'm not yet able to deploy to Shibuya using Truffle, and i'm going to try and get randomness from a future block by incorporating and using dapps/ink-rust/rand-future https://github.com/ltfschoen/XCMTemplate/pull/23/files#diff-8204ef18b173711414617cb0ab5680e976995169b27ba1767fac9589fa950f30

@SkymanOne
Copy link
Contributor

SkymanOne commented Aug 4, 2023

block_hash is not one of exposed FFI functions by pallet-contracts - https://github.com/paritytech/substrate/blob/a6b0d435995d7101e70ee0aab1707d0807024a3f/frame/contracts/src/wasm/runtime.rs#L1022C11-L1022C11
Adding this will take some time and cooperation with the substrate devs.

@athei wdyt?

@ltfschoen
Copy link
Contributor Author

so to get the block hash for a given block number i gather it needs either:

  • a single substrate implementation update to expose a FFI function by pallet-contracts
  • coordination with substrate devs to approve/reject, risk of long timeframe since Polkadot 2.0 monorepo migration would have higher priority
  • if approved and released then any new and existing blockchains just use that release to support that functionality

or for a new or existing blockchain

  • dapp developer creates a chain upgrade proposal campaign to try and get 'yes' votes to support single chain extension update
  • dapp developer coordinates with a new or existing blockchain by creating an on-chain governance chain upgrade proposal * wait until proposal approved/rejected if its an existing chain, but still possible for it to be rejected
  • if rejected then try again or find another chain and repeat the process, or dapp developer just creates their own chain where they can add the chain extensions that they need, or instead of just dapp development they try to learn how to create PRs to add FFI functions to pallet-contracts themselves?
  • dapp developer shares the FFI function code update required to pallet-contracts, or shares the chain extension code and chain upgrade campaign proposal, so other dapp developers and chain maintainers may add that functionality and repeat the same process without doing it all from scratch
  • dapp developers refer to to exposed FFI function comparison chart when choosing what chain to deploy their contracts on based on which ones support the FFI functions they need

@SkymanOne
Copy link
Contributor

Overall yes, not so many blockchains actually have pallet-contracts on the mainnets, so they can just upgrade the pallet quickly if necessary. The blocker lies in the coordination with pallet-contracts devs to add the function to the FFI interface.

@boyswan
Copy link

boyswan commented Aug 7, 2023

A big +1 for exposing the blockhash. It seems to be the most viable approach (when used in a commit/reveal scheme) to some sort of randomness in ink!. The prospect of RNG in ink was the very first thing that lead me to use ink, but after learning the original ink env random implementation was fit not for purpose I've been searching for the best way around it since.

Oracles are always the "advised solution" to rng/entropy but it just shifts the issue elsewhere. IIRC the substrate blockhash function doesn't have the access limit of only the last 256 blockhashes like EVM, so in comparison it would be at an advantage.

@SkymanOne SkymanOne added E-blocked The task is blocked on some other task to be finished. B-feature-request A request for a new feature. A-ink_env [ink_env] work item labels Aug 7, 2023
@SkymanOne
Copy link
Contributor

We should also think carefully about using block hash as a source of randomness. It is generally a not good source: https://hackingdistributed.com/2017/12/24/how-not-to-run-a-blockchain-lottery/. You should use oracle contract or chain extension. If we expose block_hash it may give a false sense of randomness to developers.

@0xf333
Copy link

0xf333 commented Aug 8, 2023

We should also think carefully about using block hash as a source of randomness. It is generally a not good source: https://hackingdistributed.com/2017/12/24/how-not-to-run-a-blockchain-lottery/. You should use oracle contract or chain extension. If we expose block_hash it may give a false sense of randomness to developers.

I'm wondering given the nuances of using Slot VRFs vs running hash, do you think there might be an approach that could bridge the gap? Something that Ink is ready to adopt presently, that people can look into and figure out implementation?
Keen to hear your perspective...

@SkymanOne
Copy link
Contributor

SkymanOne commented Aug 8, 2023

Unfortunately, I firmly believe it is up to the chain devs to expose necessary random function API to the smart contract developer. There is an ongoing issue to add support for multiple chain extensions - #1747. So perhaps it would be possible in future to ask Astar, Aleph Zero to implement the interface as a separate chain ext. AFAIK, Phala off-chain contracts allow you to bring some randomness manually since you are less restricted in resources.

We should also think carefully about using block hash as a source of randomness. It is generally a not good source: https://hackingdistributed.com/2017/12/24/how-not-to-run-a-blockchain-lottery/. You should use oracle contract or chain extension. If we expose block_hash it may give a false sense of randomness to developers.

I'm wondering given the nuances of using Slot VRFs vs running hash, do you think there might be an approach that could bridge the gap? Something that Ink is ready to adopt presently, that people can look into and figure out implementation? Keen to hear your perspective...

@0xf333
Copy link

0xf333 commented Aug 8, 2023

Unfortunately, I firmly believe it is up to the chain devs to expose necessary random function API to the smart contract developer. There is an ongoing issue to add support for multiple chain extensions - #1747. So perhaps it would be possible in future to ask Astar, Aleph Zero to implement the interface as a separate chain ext. AFAIK, Phala off-chain contracts allow you to bring some randomness manually since you are less restricted in resources.

Ok, thanks

@SkymanOne
Copy link
Contributor

Please see the reply in the corresponding issue in the substrate repo: paritytech/substrate#14724 (comment)

@SkymanOne
Copy link
Contributor

I will close the issue on Wednesday unless there are other concrete use cases for exposing a block hash.

@SkymanOne SkymanOne added C-discussion An issue for discussion for a given topic. and removed E-blocked The task is blocked on some other task to be finished. B-feature-request A request for a new feature. labels Aug 14, 2023
@SkymanOne SkymanOne closed this as not planned Won't fix, can't repro, duplicate, stale Sep 11, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-ink_env [ink_env] work item C-discussion An issue for discussion for a given topic.
Projects
None yet
Development

No branches or pull requests

4 participants