-
Notifications
You must be signed in to change notification settings - Fork 757
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
Possible race condition due to async IO in VM constructor #650
Comments
I generally have a queasy feeling about the precompile initialization...thanks for reporting this. I see three options:
Maybe there are other alternatives I'm missing, but between these 3 I'd go with the last one |
Some other possible solutions:
Actually, now that I've typed that out... I'm not a huge fan of this second approach, haha. As far as the async constructor idea goes... how would this be done? And for the lazy init call, like you, I feel like this could cause problems for applications that use the trie outside of the VM itself. This actually could cause problems for Ganache (in the future), depending on how it is implemented. Ganache has a mode where we persist the trie data to disk, and while we currently "reinitialize" precompiles every time we initialize a VM I've been planning on fixing this so we only init the precompiles on initial database creation. It could complicate the internal VM logic if |
Hm, so far it's a choice between bad and worse for me... @alcuadrado what do you think? do you see any alternatives, or which of these would you say makes more sense? |
Good catch @davidmurdoch! I think we could/should activate tslint's None of the solutions is ideal, but I think I like David's (1) the most. Precompiles activations is already one of the weirdest and most confusing things of the vm. Moving it to it's own clearly-named method would be a good thing, regardless of this bug. I also think the deprecation & removal plan also makes sense. |
Did someone has some evolved thoughts on this? |
Well, let me add my thoughts on that. I think all the constructors' async operations should be moved into |
Well, after a reading the project issues I found #652 (Hardforks backporting) which describes questions about new opcodes/prices and other problems and raises even more important questions which couldn't be done with scenarios in the way I described them. And such solution is a huge piece of work and researches. So I'll move discussion to that issue. What's about precompiles initialization. As I said It's unnecessary and should be removed. Because currently it has one goal is to prevent from spending extra gas on address creation. But, as I see in Go Ethereum implementation the VM intercepts all calls to precompiled contracts, and if precompiled contract isn't exists yet because Hardfork is not activated, then new account should be created. Go Ethereum Go EVM But in current JS implementation non-existent address would be created anyway: I think this is where this behavior should be changed. And |
Oops. Looks like I made wrong conclusion about Go implementation. Sorry for that. The good news I've fixed race condition in PR #660 and added customizable precompiles as VM option in the most backward compatible way as it was possible. So now developers can customize this set on their demand. VM option |
https://github.com/ethereumjs/ethereumjs-vm/blob/feef85f7d51c4e09da3105ebe473e86dcff45eb1/lib/index.ts#L121
This line begins writing data to the trie, which is an async operation that may perform file IO depending on the Trie's configuration. There doesn't seem to be a way of detecting when these writes operations are complete.
I only found this issue while debugging an issue in ganache that was causing a
TypeError: Cannot read property 'pop' of undefined
related to not waiting for this initialization to complete. Ganache currently uses a leveldb implementation for its trie storage which has a bug that permits db reads on values that were in the process of being written. If callers could wait for the VM to be fully initialized it would prevent this race condition from occuring*.I'll pull the precompile initialization logic into ganache-core for the time being, so a fix isn't urgent.
*aside: i'm actually very happy this race condition exists in the VM... as the ganache read/write bug would have been even harder to track down without this reliable way of triggering it! 😃.
The text was updated successfully, but these errors were encountered: