-
Notifications
You must be signed in to change notification settings - Fork 759
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
statemanager: refactor logic into capabilities #3554
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files
Flags with carried forward coverage won't be shown. Click here to find out more. |
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.
DRY! LGTM!
Ah, TBH: I do not like this yet, this structural accessing on private properties. 🤔 Will give this some thought. |
interface Cache { | ||
checkpoint(): void | ||
commit(): void | ||
revert(): void |
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.
These Common
interfaces should really only be used for the "3 big defining interfaces" (like StateManager) which are important beyond the scope of a single package and therefore should get some solid visibility and the possibility to re-use.
(so generally it's already too crowded in here and some interfaces do not really belong here)
So these Cache interfaces should definitely not be placed here and should go back if it's not absolutely structurally necessary (I guess it's not?).
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.
(maybe this should be stated better at the top of this file)
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.
Ok, so I am not satisfied with this structure yet and I think we should continue to evolve.
So, this capabilities concept holds for the modfiyAccountFields()
method (not sure if we should still call this Capabilities
for this one single method or a bit overblown, but rather secondary question), but not for the caches.
Maybe we do a separate wrapping Caches
class which holds all the three caches together (maybe you meantioned this as well in the chat?) (also the settings should the fully move over there), which can then be initialized separately?
This would abstract all this a lot better away (then maybe though forget my comment on Common
interface inclusion, guess this is still needed then (or maybe not, and we handle this more internally in the StateManager package? So this would definitely be prefered!)).
Then a StateManager would have a property caches
(not sure if needed to be public or not), and this would have (public) properties for the account/code/storage cache so that one could do this.caches.account.delete()
from within the SMs.
I think we could then also make a lot of code like this a lot more atomic:
/**
* Deletes an account from state under the provided `address`.
* @param address - Address of the account which should be deleted
*/
async deleteAccount(address: Address) {
if (this.DEBUG) {
this._debug(`Delete account ${address}`)
}
this._codeCache?.del(address)
if (this._accountCacheSettings.deactivate) {
await this._trie.del(address.bytes)
} else {
this._accountCache!.del(address)
}
if (!this._storageCacheSettings.deactivate) {
this._storageCache?.clearStorage(address)
}
}
so that this could be more or less replaced with this.caches?.deleteAccount()
or so (+ the trie deletion).
I would then also pledge that we make it mandatory to have this Caches
object intitialized manually along SM instantiation (if wished to be used), like:
new StateManager({ caches: new Caches() })
Then we can tree shake away the whole cache code for non users as a side effect.
For the Capabilities
I think there is a lot more room on the other hand to integrate (partial) methods on the account/code/storage side.
So for something like this it should be likely possible to move everything except the first line into a capability method? (guess this is similarly used in another SM? but didn't have a look)
/**
* Adds `value` to the state trie as code, and sets `codeHash` on the account
* corresponding to `address` to reference this.
* @param address - Address of the `account` to add the `code` for
* @param value - The value of the `code`
*/
async putCode(address: Address, value: Uint8Array): Promise<void> {
this._codeCache?.put(address, value)
const codeHash = this.keccakFunction(value)
if (this.DEBUG) {
this._debug(`Update codeHash (-> ${short(codeHash)}) for account ${address}`)
}
if ((await this.getAccount(address)) === undefined) {
await this.putAccount(address, new Account())
}
await this.modifyAccountFields(address, { codeHash })
}
Ok, so far! 🙂
|
||
_accountCacheSettings?: CacheSettings | ||
_storageCacheSettings?: CacheSettings | ||
_codeCacheSettings?: CacheSettings |
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.
Ah, yeah, and the StateManager
interface should generally not be bloated in any way, that was one big reason for the refactor of the interface we did 1-2 weeks ago.
This should remain minimal (also regarding optional properties, though it's a bit less urgent here), so that third-party users are not burdened with the internals of state manager.
So all these properties should definitely go out again.
This reverts commit d7d1dab.
This reverts commit d7d1dab.
Thanks for the suggestion. Went back and forth on this, wasn't sure how much caching updates we were comfortable doing, as cache can differ from one state manager to the next, will experiment and come back with something :) |
Ah, no, you somewhere got me wrong here. That was no suggestion to change the number of caching updates whatsoever (we definitely should not do that, especially just for a form-refactor) |
So this is just a suggestion how to re-package stuff a bit.
Optimally we do not expose cache stuff at all in the For something like the Caches {
deleteAccount(address: Address) {
this.code.del(address)
this.account.del(address)
this.storage.clearStorage(address)
}
} And in the main SM only this remains: async deleteAccount(address: Address) {
if (this.DEBUG) {
this._debug(`Delete account ${address}`)
}
this._caches?.deleteAccount(address)
if (this._caches === undefined) {
await this._trie.del(address.bytes)
}
} So but these kind of optimizations (if possible) are just somewhat of an extra I guess. The general restructuring would already bring most of the encapsuation benefits. If you want we can also have a call on this later the (my) day! |
* Revert "statemanager: refactor logic into capabilities (#3554)" This reverts commit d7d1dab. * statemanager: refactor modifyAccountFields * statemanager: adjust return statements * statemanager: refactor separate caches into caches class * statemanager: fix shallow copy logic * client: fix vmexecution statemanager cache opts * statemanager: refactor some capabilities to caches methods * statemanager: fix tests * statemanager: refactor caches into optional opt passed in directly to the sm * statemanager: adjust tests with refactored caches * client: adjust vm execution with update cache * vm: fix vm tests * vm: adjust test runners with non-default caches * statemanager: simplify handling of deactivate * statemanager: remove redundant checks * statemanager: remove non null asesertion * statemanager: remove cache opt from key naming * statemanager: refactor rpc state manager to use caches * statemanager: fix rpc state manager tests * client: vmexecution cache stats refactor * statemanageR: updategetproof json-rpc call format * statemanager: remove deactivate from caches * client: remove deactivate from vm execution instantiation --------- Co-authored-by: acolytec3 <[email protected]>
This PR refactors some duplicate logic from statemanager classes into a separate capabilities helper