-
Notifications
You must be signed in to change notification settings - Fork 773
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
EVM/Common: SimpleStateManager #3482
Conversation
Ok, ready! 🎉 All EVM tests passing, the one thing I needed to do for this is to also move the So: I think for the EVM this is a big deal! So this lifts a weight of close to 400KB to the EVM in addition to the other reductions, and so brings this package in the realm of becoming a "normal" browser library which people just side-integrate among other dependencies. The overall code adition "on the other side" is still < 8 KB. Beyond the code reduction this frees EVM users from all browser-related hazzles coming from the Want to nevertheless make some more cases here respectively give some additional context/explanation about design choices, so to make things more transparent and "followable". Why Common ?So, this is admittedly relatively low in the stack. This was mainly guided by the following design "needs":
We could also think about moving this to the I think this new state manager will be generally useful, also for our own use cases, mainly e.g. regarding testing, stumbled upon this thought yesterday when seeing you guys battling with the Anyhow: ready for review! 🙂 Note that this PR builds upon the BLS PR (for bundle comparison reasons). I think it's better to merge BLS first since these are conceptually unrelated. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some comments, LGTM in general (and indeed, also super simple yet elegant! 😄 )
For the state manager tests, some now run on the DefaultStateManager and the SimpleStateManager - but only the checkpoint tests. Are there other tests which we want to incorporate here?
Also, small side note, for code coverage the tests from StateManager -> Common will not get tracked, so our common
coverage will likely go down, since likely (?) SimpleStateManager
is not covered by the tests.
packages/common/src/state/simple.ts
Outdated
if ((await this.getAccount(address)) === undefined) { | ||
await this.putAccount(address, new Account()) | ||
} | ||
await this.modifyAccountFields(address, { codeHash: keccak256(value) }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not have a super strong opinion on this but it seems like we should follow the same pattern we follow through the rest of the libraries where we allow users to pass in their own crypto and not require use of this keccak256
function (like we do here) in the DefaultStateManager
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do/integrate. First thought in terms of "simplification", but this might not be one actually. 😆
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was going to suggest the same and then saw Andrew's comment. I agree that it would be preferable not to "hardcode" this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have added
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome implementation, love the simple
ness of this :-). That said, I've read through the explanation of why this should be in Common
and I'm not tracking. This is only used in evm
and nowhere else so doesn't make sense to me include this in common
. What is the driving goal for not putting this in statemanager
? If it implements the EVMstateManagerInterface
, I don't see any reason that tree shaking wouldn't take care of any excess bundle size concerns if a user imports it from @ethereumjs/statemanager
.
packages/common/src/state/simple.ts
Outdated
for (const [address, account] of newTopA) { | ||
const accountCopy = | ||
account !== undefined | ||
? Object.assign(Object.create(Object.getPrototypeOf(account)), account) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe that this would be more efficient:
Object.create(Object.getPrototypeOf(account), Object.getOwnPropertyDescriptors(account));
Since it avoids the intermediate step of creating an empty object and then copying properties over to it, and it ensures all properties, including non-enumerable ones, are copied.
packages/common/src/state/simple.ts
Outdated
} | ||
|
||
async getContractStorage(address: Address, key: Uint8Array): Promise<Uint8Array> { | ||
return this.topS().get(`${address.toString()}_${bytesToHex(key)}`) ?? new Uint8Array(0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps we could create a helper for storageKeyFormatting
that parsed an address + key into the expected string? This could be helpful notably if we need to switch around the format (pre and post verkle comes to mind), then we don't have to modify it in multiple places.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will keep for now, we can still easily do later on
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow, that's some great work! Really like how this removes the statemanager package dependency from the evm. Left some minor comments.
…ependency (already in through Util dependency)
The git diff is looking messed up 🤔 It tries to re-import the changes to BLS? |
Yeah, I've cherry picked the commits out locally, will force-push |
d701dfa
to
2252759
Compare
Co-authored-by: Gabriel Rocheleau <contact@rockwaterweb.com>
* | ||
* The `@ethereumjs/statemanager` package provides a variety of state manager | ||
* implementations for different needs (tree backed, RPC, experimental verkle) | ||
* which can be used by this option as a replacement. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please update the docs to now reflect the new SSM location?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks otherwise good, feel free to merge (also ok to spare out this one doc change from my side, just saw it's really this one very mention, can also update later, not sure if worth to trigger whole CI)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
3 small-ish comments
account.nonce = accountFields.nonce ?? account.nonce | ||
account.balance = accountFields.balance ?? account.balance | ||
account.storageRoot = accountFields.storageRoot ?? account.storageRoot | ||
account.codeHash = accountFields.codeHash ?? account.codeHash |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just checked, even if account
is returned undefined
, and we provide the accountFields
which is Partial<Account>
this still works fine (we default the account to default values)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a question here? I'm not sure what you're getting at?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
This is a proof of concept if it is possibleThis PR implements aSimpleStateManager
with the goal to replace the default state manager implementation and depdendency from the EVM with a very simple < 5KB state manager located inCommon
without any further depdencies.This would allow to ship with a significantly trimmed down base EVM, both with a substantially reduced dependency set and bundle size, going from 1.23 MB to 850 KB.
Before:
After (also note the "number of boxes": statemanager out, trie out, js-sdsl out, readable-stream out, Buffer out, lru-cache out). So if you click to enlarge, this is so much more a representation of what the EVM is about than before:
This would ease browser usage for simple EVM use cases and integrations.
Some more comments to make here, short on time right now.
I have integrated this into the general SM test suite, all checkpoint tests are passing.
For the EVM this also already gives pretty solid results, with adhoc (without any modification) only 4 / 1107 tests failing.