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

statemanager: cache and other refactors #3569

Merged
merged 27 commits into from
Aug 12, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
fa3c2ec
Revert "statemanager: refactor logic into capabilities (#3554)"
gabrocheleau Aug 7, 2024
bd1f237
statemanager: refactor modifyAccountFields
gabrocheleau Aug 7, 2024
d5aaf30
statemanager: adjust return statements
gabrocheleau Aug 7, 2024
533fa8c
statemanager: refactor separate caches into caches class
gabrocheleau Aug 9, 2024
31c94af
chore: merge with master
gabrocheleau Aug 9, 2024
bba928b
statemanager: fix shallow copy logic
gabrocheleau Aug 9, 2024
a04158d
client: fix vmexecution statemanager cache opts
gabrocheleau Aug 9, 2024
2431594
statemanager: refactor some capabilities to caches methods
gabrocheleau Aug 9, 2024
814b9f7
statemanager: fix tests
gabrocheleau Aug 9, 2024
2439219
statemanager: refactor caches into optional opt passed in directly to…
gabrocheleau Aug 9, 2024
4c6240f
statemanager: adjust tests with refactored caches
gabrocheleau Aug 9, 2024
5e1666d
client: adjust vm execution with update cache
gabrocheleau Aug 9, 2024
c754eac
vm: fix vm tests
gabrocheleau Aug 9, 2024
5d4895c
vm: adjust test runners with non-default caches
gabrocheleau Aug 9, 2024
888b20e
statemanager: simplify handling of deactivate
gabrocheleau Aug 9, 2024
905a52e
statemanager: remove redundant checks
gabrocheleau Aug 9, 2024
f30288a
statemanager: remove non null asesertion
gabrocheleau Aug 9, 2024
ba00837
statemanager: remove cache opt from key naming
gabrocheleau Aug 10, 2024
c037ae2
statemanager: refactor rpc state manager to use caches
gabrocheleau Aug 11, 2024
fdcdb36
statemanager: fix rpc state manager tests
gabrocheleau Aug 11, 2024
3d93587
client: vmexecution cache stats refactor
gabrocheleau Aug 11, 2024
48baee3
Merge remote-tracking branch 'origin/master' into statemanager/capabi…
acolytec3 Aug 12, 2024
f0b66bf
Merge branch 'master' into statemanager/capabilities-refactor
acolytec3 Aug 12, 2024
5f4c253
statemanageR: updategetproof json-rpc call format
gabrocheleau Aug 12, 2024
7fe21fd
statemanager: remove deactivate from caches
gabrocheleau Aug 12, 2024
4864383
client: remove deactivate from vm execution instantiation
gabrocheleau Aug 12, 2024
b6ee97b
Merge branch 'statemanager/capabilities-refactor' of https://github.c…
gabrocheleau Aug 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 24 additions & 17 deletions packages/client/src/execution/vmexecution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,15 @@
DBSetHashToNumber,
DBSetTD,
} from '@ethereumjs/blockchain'
import { CacheType, ConsensusType, Hardfork } from '@ethereumjs/common'
import { ConsensusType, Hardfork } from '@ethereumjs/common'

Check warning on line 7 in packages/client/src/execution/vmexecution.ts

View check run for this annotation

Codecov / codecov/patch

packages/client/src/execution/vmexecution.ts#L7

Added line #L7 was not covered by tests
import { MCLBLS, RustBN254 } from '@ethereumjs/evm'
import { getGenesis } from '@ethereumjs/genesis'
import { DefaultStateManager, StatelessVerkleStateManager } from '@ethereumjs/statemanager'
import {
CacheType,
Caches,
DefaultStateManager,
StatelessVerkleStateManager,
} from '@ethereumjs/statemanager'

Check warning on line 15 in packages/client/src/execution/vmexecution.ts

View check run for this annotation

Codecov / codecov/patch

packages/client/src/execution/vmexecution.ts#L10-L15

Added lines #L10 - L15 were not covered by tests
import { createTrie } from '@ethereumjs/trie'
import {
BIGINT_0,
Expand Down Expand Up @@ -160,21 +165,23 @@
const stateManager = new DefaultStateManager({
trie,
prefixStorageTrieKeys: this.config.prefixStorageTrieKeys,
accountCacheOpts: {
deactivate: false,
type: CacheType.LRU,
size: this.config.accountCache,
},
storageCacheOpts: {
deactivate: false,
type: CacheType.LRU,
size: this.config.storageCache,
},
codeCacheOpts: {
deactivate: false,
type: CacheType.LRU,
size: this.config.codeCache,
},
caches: new Caches({
accountCacheOpts: {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can fully drop the CacheOpts from this key, makes it nicer to digest/read and remains fully expressive.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(same for others of course)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done!

deactivate: false,
type: CacheType.LRU,
size: this.config.accountCache,
},
storageCacheOpts: {
deactivate: false,
type: CacheType.LRU,
size: this.config.storageCache,
},
codeCacheOpts: {
deactivate: false,
type: CacheType.LRU,
size: this.config.codeCache,
},
}),

Check warning on line 184 in packages/client/src/execution/vmexecution.ts

View check run for this annotation

Codecov / codecov/patch

packages/client/src/execution/vmexecution.ts#L168-L184

Added lines #L168 - L184 were not covered by tests
common: this.config.chainCommon,
})

Expand Down
2 changes: 1 addition & 1 deletion packages/client/src/rpc/modules/eth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@
import type { FullEthereumService, Service } from '../../service/index.js'
import type { RpcTx } from '../types.js'
import type { Block, JsonRpcBlock } from '@ethereumjs/block'
import type { Proof } from '@ethereumjs/common'
import type { Log } from '@ethereumjs/evm'
import type { Proof } from '@ethereumjs/statemanager'

Check warning on line 49 in packages/client/src/rpc/modules/eth.ts

View check run for this annotation

Codecov / codecov/patch

packages/client/src/rpc/modules/eth.ts#L49

Added line #L49 was not covered by tests
import type {
FeeMarketEIP1559Transaction,
LegacyTransaction,
Expand Down
31 changes: 0 additions & 31 deletions packages/common/src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,35 +209,4 @@ export interface StateManagerInterface {
*/
clearCaches(): void
shallowCopy(downlevelCaches?: boolean): StateManagerInterface

/*
* Cache properties
*/
_accountCache?: Cache
_storageCache?: Cache
_codeCache?: Cache

_accountCacheSettings?: CacheSettings
_storageCacheSettings?: CacheSettings
_codeCacheSettings?: CacheSettings
}

/**
* Cache related
*/
export enum CacheType {
LRU = 'lru',
ORDERED_MAP = 'ordered_map',
}

export type CacheSettings = {
deactivate: boolean
type: CacheType
size: number
}

interface Cache {
checkpoint(): void
commit(): void
revert(): void
}
6 changes: 3 additions & 3 deletions packages/statemanager/src/cache/account.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { CacheType } from '@ethereumjs/common'
import { bytesToUnprefixedHex } from '@ethereumjs/util'
import { OrderedMap } from '@js-sdsl/ordered-map'
import debugDefault from 'debug'
import { LRUCache } from 'lru-cache'

import { Cache } from './cache.js'
import { CacheType } from './types.js'

import type { CacheOpts } from './types.js'
import type { Account, Address } from '@ethereumjs/util'
Expand Down Expand Up @@ -68,14 +68,14 @@ export class AccountCache extends Cache {
put(
address: Address,
account: Account | undefined,
couldBeParitalAccount: boolean = false,
couldBePartialAccount: boolean = false,
): void {
const addressHex = bytesToUnprefixedHex(address.bytes)
this._saveCachePreState(addressHex)
const elem = {
accountRLP:
account !== undefined
? couldBeParitalAccount
? couldBePartialAccount
? account.serializeWithPartialInfo()
: account.serialize()
: undefined,
Expand Down
93 changes: 93 additions & 0 deletions packages/statemanager/src/cache/caches.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { AccountCache } from './account.js'
import { CodeCache } from './code.js'
import { StorageCache } from './storage.js'
import { type CacheSettings, CacheType, type CachesStateManagerOpts } from './types.js'

import type { Address } from '@ethereumjs/util'

export class Caches {
account?: AccountCache
code?: CodeCache
storage?: StorageCache

settings: Record<'account' | 'code' | 'storage', CacheSettings>

constructor(opts: CachesStateManagerOpts = {}) {
const accountSettings = {
deactivate:
(opts.accountCacheOpts?.deactivate === true || opts.accountCacheOpts?.size === 0) ?? false,
type: opts.accountCacheOpts?.type ?? CacheType.ORDERED_MAP,
size: opts.accountCacheOpts?.size ?? 100000,
}
const storageSettings = {
deactivate:
(opts.storageCacheOpts?.deactivate === true || opts.storageCacheOpts?.size === 0) ?? false,
type: opts.storageCacheOpts?.type ?? CacheType.ORDERED_MAP,
size: opts.storageCacheOpts?.size ?? 20000,
}

const codeSettings = {
deactivate:
(opts.codeCacheOpts?.deactivate === true || opts.codeCacheOpts?.size === 0) ?? false,
type: opts.codeCacheOpts?.type ?? CacheType.ORDERED_MAP,
size: opts.codeCacheOpts?.size ?? 20000,
}

this.settings = {
account: accountSettings,
code: codeSettings,
storage: storageSettings,
}

if (this.settings.account.deactivate === false) {
this.account = new AccountCache({
size: this.settings.account.size,
type: this.settings.account.type,
})
}

if (this.settings.storage.deactivate === false) {
this.storage = new StorageCache({
size: this.settings.storage.size,
type: this.settings.storage.type,
})
}

if (this.settings.code.deactivate === false) {
this.code = new CodeCache({
size: this.settings.code.size,
type: this.settings.code.type,
})
}
}

checkpoint() {
this.account?.checkpoint()
this.storage?.checkpoint()
this.code?.checkpoint()
}

clear() {
this.account?.clear()
this.storage?.clear()
this.code?.clear()
}

commit() {
this.account?.commit()
this.storage?.commit()
this.code?.commit()
}

deleteAccount(address: Address) {
this.code?.del(address)
this.account?.del(address)
this.storage?.clearStorage(address)
}

revert() {
this.account?.revert()
this.storage?.revert()
this.code?.revert()
}
}
2 changes: 1 addition & 1 deletion packages/statemanager/src/cache/code.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { CacheType } from '@ethereumjs/common'
import { bytesToUnprefixedHex } from '@ethereumjs/util'
import { OrderedMap } from '@js-sdsl/ordered-map'
import debugDefault from 'debug'
import { LRUCache } from 'lru-cache'

import { Cache } from './cache.js'
import { CacheType } from './types.js'

import type { CacheOpts } from './types.js'
import type { Address } from '@ethereumjs/util'
Expand Down
1 change: 1 addition & 0 deletions packages/statemanager/src/cache/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './account.js'
export * from './caches.js'
export * from './code.js'
export * from './originalStorageCache.js'
export * from './storage.js'
Expand Down
2 changes: 1 addition & 1 deletion packages/statemanager/src/cache/storage.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { CacheType } from '@ethereumjs/common'
import { bytesToUnprefixedHex, hexToBytes } from '@ethereumjs/util'
import { OrderedMap } from '@js-sdsl/ordered-map'
import debugDefault from 'debug'
import { LRUCache } from 'lru-cache'

import { Cache } from './cache.js'
import { CacheType } from './types.js'

import type { CacheOpts } from './types.js'
import type { Address } from '@ethereumjs/util'
Expand Down
54 changes: 53 additions & 1 deletion packages/statemanager/src/cache/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,58 @@
import type { CacheType } from '@ethereumjs/common'
export enum CacheType {
LRU = 'lru',
ORDERED_MAP = 'ordered_map',
}

export interface CacheOpts {
size: number
type: CacheType
}

export type CacheSettings = {
deactivate: boolean
type: CacheType
size: number
}

export interface CacheStateManagerOpts {
/**
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe drop the StateManager here from the name

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we remove StateManager, we'll have a naming conflict with CacheOpts declared above. I am not 100% satisfied with the general naming, and there is some overlap between these interfaces/types (which makes me want to unify them somehow), but there does not seem to be sufficient overlap to really unify them. Open to suggestions!

Copy link
Member

@holgerd77 holgerd77 Aug 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe give this a second thought, but I would kill off the deactivate part and take the size === 0 as the one and only way to deactivate and then remove the CacheOpts and only use the CachesStateManagerOpts (then renamed to CacheOpts 😋) as the one thing for all.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting, just seeing this comment I'll give that a try, would really like to simplify further

* Allows for cache deactivation
*
* Depending on the use case and underlying datastore (and eventual concurrent cache
* mechanisms there), usage with or without cache can be faster
*
* Default: false
*/
deactivate?: boolean

/**
* Cache type to use.
*
* Available options:
*
* ORDERED_MAP: Cache with no fixed upper bound and dynamic allocation,
* use for dynamic setups like testing or similar.
*
* LRU: LRU cache with pre-allocation of memory and a fixed size.
* Use for larger and more persistent caches.
*/
type?: CacheType

/**
* Size of the cache (only for LRU cache)
*
* Default: 100000 (account cache) / 20000 (storage cache) / 20000 (code cache)
*
* Note: the cache/trie interplay mechanism is designed in a way that
* the theoretical number of max modified accounts between two flush operations
* should be smaller than the cache size, otherwise the cache will "forget" the
* old modifications resulting in an incomplete set of trie-flushed accounts.
*/
size?: number
}

export interface CachesStateManagerOpts {
accountCacheOpts?: CacheStateManagerOpts
codeCacheOpts?: CacheStateManagerOpts
storageCacheOpts?: CacheStateManagerOpts
}
Loading
Loading