-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Deterministic genesis hash for --dev
runtime
#11131
Comments
I think it happens on every start. The chain spec is built at runtime. This is the code I was talking about: substrate/bin/node/cli/src/chain_spec.rs Lines 274 to 291 in 41567c3
|
@kianenigma @emostov can you use some seeded randomness or something else here that is deterministic? |
contracts-ui relies the fact that every re-start of a |
This doesn't sounds like a good idea ;) |
Both development and staging testnets are actually passing @@ -272,20 +272,12 @@ pub fn testnet_genesis(
});
// stakers: all validators and nominators.
- let mut rng = rand::thread_rng();
let stakers = initial_authorities
.iter()
.map(|x| (x.0.clone(), x.1.clone(), STASH, StakerStatus::Validator))
.chain(initial_nominators.iter().map(|x| {
- use rand::{seq::SliceRandom, Rng};
- let limit = (MaxNominations::get() as usize).min(initial_authorities.len());
- let count = rng.gen::<usize>() % limit;
- let nominations = initial_authorities
- .as_slice()
- .choose_multiple(&mut rng, count)
- .into_iter()
- .map(|choice| choice.0.clone())
- .collect::<Vec<_>>();
+ let nominations = initial_authorities.iter().take(MaxNominations::get() as usize).cloned().collect::<Vec<_>>();
(x.clone(), x.clone(), STASH, StakerStatus::Nominator(nominations))
}))
.collect::<Vec<_>>(); |
Contracts UI stores information about uploaded contracts in a local db, so when the chain is restarted we want to purge the db. We were using the genesis hash to check if there was a restart. Is there any value we can use that is unique to the chain instance? Worst case scenario we let the users deal with deleting contracts that are not on-chain anymore, but doing it automatically is much nicer UX |
just use hash of block 1 instead of block 0? |
we were doing that before |
We can keep the old behaviour with something like |
that could be interesting for other reasons, but there is no guarantee people will use it and the UI needs to handle all cases |
I think Where I agree with you is that relying on this implementation detail (staking nomination randomization) is bad. We should make it explicit. Just include some explicit randomness in the genesis for dev and local chains. Then we add a |
How would that work on live networks? There you can not cache contracts as well? So you would need to scrape them on restart of the UI or something? For local or dev networks, I would store something like latest block and if the chain is back at block 0, it means it was restarted. Or even less complicated, if the chain is at block 0 you know that there doesn't exists any contract, so you can delete any cache. |
I don't see why a dev chain should always have a different genesis hash. This was never the case before and only seems to be introduced by accident by @kianenigma. |
Yeah this is how polkadot.js Apps handles it currently. It is kind of annoying.
Contracts (more precisely the metadata) is stored in persistent browser memory. So unless the user resets the cache it stays there. It is about the opposite: The chain is purged and then we still have contracts shown in the UI which do not exist on-chain. Live chains do not have this problem as they are not restarted.
Yes storing the latest block per endpoint might be a solution that works. If it goes backwards it was reset. But is is not reliable: If you restart the chain but only open up the UI later this event can be missed. Another solution: Just automatically remove every contract which does not exist on chain from the UI. No need to have it stick around as "this is deleted". |
For sure, but you can remove contracts? Aka contracts are not required to stay on chain indefinitely? |
this could work, but better still would be to have some kind of random id that changes on restart for local/dev chains. like docker containers 🙂 |
Basically what we do is: |
A contract can self destruct if it chooses to do so. So yes, they can be removed. |
So that needs to be supported anyway for live chains? |
I guess in this case we would be OK to just have the user to click on "delete" as it is a rare occurrence as opposed to restarting a dev node. |
How should the user know that the contract doesn't exist anymore? Sounds like some complicated UX to me? If the app can find this out, why not let it find out if a contract still exists? |
Yes, it is complicated, but my goal is always to simplify the UX. |
I mean I get this, but I also don't see any reason why we can not just batch all these calls and then do some simple heuristic:
I mean I'm that far away from being anywhere an UX expert, you can not imagine, but I think you are good at this @statictype and come up with something way better than my stupid idea :D You will also don't need to use For this issue in general. @kianenigma slipped through these changes that make the chain spec of the Substrate node nondeterministic. I would say we remove this again, because there is no real need and for sure we don't add any "default" way of randomizing genesis states in some way. If someone wants this for their dev chain, like the contracts playground node (not sure how it is called), they can add some random value to the genesis storage. Then you would have the functionality you want. However, this will not happen in Substrate as any default way. |
sure, we can find a workaround. indeed it's not ideal for UIs to rely on the randomness of the genesis hash to check for restarts. |
I double checked the code, and @kianenigma is right. So sadly the |
I thought it does because the wasm blob is different (which in itself is in genesis). But it is an unintended side effect. |
Because the build is non-deterministic between rust versions or which "unintended side effect" do you mean? @athei |
Yeah this is what I meant. But yeah they shouldn't differ between launches of the same binary. |
This is also possible, however that is again chain specific. Aka we can not change this here on the Substrate side. Every chain implementation decides on its own about the |
I will close this now since it arose from a misunderstanding of what was happening. Thanks for clearing it up! |
When I start a substrate node in
--dev
node, it sometimes has different genesis hashes.It does not happen on every start but sometimes after building? I could not really track to what it is related.
It would be nice to have deterministic genesis hashes such that
import
/export-block
can be used for testing and in CI.Either by fixing it or using a
--seed
flag.@athei said it could be because of randomized staking nominations.
The text was updated successfully, but these errors were encountered: