Skip to content

Commit

Permalink
statemanager: refactor cache related capabilities
Browse files Browse the repository at this point in the history
  • Loading branch information
gabrocheleau committed Aug 4, 2024
1 parent 12b45ba commit dcae495
Show file tree
Hide file tree
Showing 11 changed files with 150 additions and 150 deletions.
8 changes: 2 additions & 6 deletions packages/client/src/execution/vmexecution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,10 @@ import {
DBSetHashToNumber,
DBSetTD,
} from '@ethereumjs/blockchain'
import { ConsensusType, Hardfork } from '@ethereumjs/common'
import { CacheType, ConsensusType, Hardfork } from '@ethereumjs/common'
import { MCLBLS } from '@ethereumjs/evm'
import { getGenesis } from '@ethereumjs/genesis'
import {
CacheType,
DefaultStateManager,
StatelessVerkleStateManager,
} from '@ethereumjs/statemanager'
import { DefaultStateManager, StatelessVerkleStateManager } from '@ethereumjs/statemanager'
import { createTrie } from '@ethereumjs/trie'
import {
BIGINT_0,
Expand Down
31 changes: 31 additions & 0 deletions packages/common/src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,4 +209,35 @@ 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
}
2 changes: 1 addition & 1 deletion 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
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
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
5 changes: 1 addition & 4 deletions packages/statemanager/src/cache/types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
export enum CacheType {
LRU = 'lru',
ORDERED_MAP = 'ordered_map',
}
import type { CacheType } from '@ethereumjs/common'

export interface CacheOpts {
size: number
Expand Down
72 changes: 71 additions & 1 deletion packages/statemanager/src/capabilities.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,72 @@
import { type AccountFields, CacheType, type StateManagerInterface } from '@ethereumjs/common'
import { Account } from '@ethereumjs/util'

import type { AccountFields, StateManagerInterface } from '@ethereumjs/common'
import { AccountCache, CodeCache, OriginalStorageCache, StorageCache } from './cache/index.js'

import type { CacheStateManagerOpts } from './types.js'
import type { Address } from '@ethereumjs/util'

export function checkpointCaches(stateManager: StateManagerInterface): void {
stateManager._accountCache?.checkpoint()
stateManager._storageCache?.checkpoint()
stateManager._codeCache?.checkpoint()
}

export function commitCaches(stateManager: StateManagerInterface): void {
stateManager._accountCache?.commit()
stateManager._storageCache?.commit()
stateManager._codeCache?.commit()
}

export function initializeCaches(
stateManager: StateManagerInterface,
options: CacheStateManagerOpts,
): void {
stateManager.originalStorageCache = new OriginalStorageCache(
stateManager.getStorage.bind(stateManager),
)

stateManager._accountCacheSettings = {
deactivate: options.accountCacheOpts?.deactivate ?? false,
type: options.accountCacheOpts?.type ?? CacheType.ORDERED_MAP,
size: options.accountCacheOpts?.size ?? 100000,
}

if (stateManager._accountCacheSettings.deactivate === false) {
stateManager._accountCache = new AccountCache({
size: stateManager._accountCacheSettings.size,
type: stateManager._accountCacheSettings.type,
})
}

stateManager._storageCacheSettings = {
deactivate: options.storageCacheOpts?.deactivate ?? false,
type: options.storageCacheOpts?.type ?? CacheType.ORDERED_MAP,
size: options.storageCacheOpts?.size ?? 20000,
}

if (stateManager._storageCacheSettings.deactivate === false) {
stateManager._storageCache = new StorageCache({
size: stateManager._storageCacheSettings.size,
type: stateManager._storageCacheSettings.type,
})
}

stateManager._codeCacheSettings = {
deactivate:
(options.codeCacheOpts?.deactivate === true || options.codeCacheOpts?.size === 0) ?? false,
type: options.codeCacheOpts?.type ?? CacheType.ORDERED_MAP,
size: options.codeCacheOpts?.size ?? 20000,
}

if (stateManager._codeCacheSettings.deactivate === false) {
stateManager._codeCache = new CodeCache({
size: stateManager._codeCacheSettings.size,
type: stateManager._codeCacheSettings.type,
})
}
}

export async function modifyAccountFields(
stateManager: StateManagerInterface,
address: Address,
Expand All @@ -16,3 +80,9 @@ export async function modifyAccountFields(
account.codeHash = accountFields.codeHash ?? account.codeHash
await stateManager.putAccount(address, account)
}

export function revertCaches(stateManager: StateManagerInterface): void {
stateManager._accountCache?.revert()
stateManager._storageCache?.revert()
stateManager._codeCache?.revert()
}
14 changes: 8 additions & 6 deletions packages/statemanager/src/rpcStateManager.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Common, Mainnet } from '@ethereumjs/common'
import { CacheType, Common, Mainnet } from '@ethereumjs/common'
import { RLP } from '@ethereumjs/rlp'
import { verifyTrieProof } from '@ethereumjs/trie'
import {
Expand All @@ -16,7 +16,7 @@ import {
import debugDefault from 'debug'
import { keccak256 } from 'ethereum-cryptography/keccak.js'

import { AccountCache, CacheType, OriginalStorageCache, StorageCache } from './cache/index.js'
import { AccountCache, OriginalStorageCache, StorageCache } from './cache/index.js'
import * as Capabilities from './capabilities.js'

import type { Proof, RPCStateManagerOpts } from './index.js'
Expand All @@ -28,12 +28,14 @@ const KECCAK256_RLP_EMPTY_ACCOUNT = RLP.encode(new Account().serialize()).slice(

export class RPCStateManager implements StateManagerInterface {
protected _provider: string
protected _contractCache: Map<string, Uint8Array>
protected _storageCache: StorageCache
protected _blockTag: string
protected _accountCache: AccountCache

_accountCache: AccountCache
_storageCache: StorageCache
_contractCache: Map<string, Uint8Array>

originalStorageCache: OriginalStorageCache
protected _debug: Debugger
_debug: Debugger
protected DEBUG: boolean
private keccakFunction: Function
public readonly common: Common
Expand Down
79 changes: 15 additions & 64 deletions packages/statemanager/src/stateManager.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Common, Mainnet } from '@ethereumjs/common'
import { CacheType, Common, Mainnet } from '@ethereumjs/common'
import { RLP } from '@ethereumjs/rlp'
import {
Trie,
Expand Down Expand Up @@ -31,17 +31,11 @@ import {
import debugDefault from 'debug'
import { keccak256 } from 'ethereum-cryptography/keccak.js'

import {
AccountCache,
CacheType,
CodeCache,
OriginalStorageCache,
StorageCache,
} from './cache/index.js'
import * as Capabilities from './capabilities.js'

import { CODEHASH_PREFIX, type CacheSettings, type DefaultStateManagerOpts } from './index.js'

import type { AccountCache, CodeCache, OriginalStorageCache, StorageCache } from './cache/index.js'
import type { StorageProof } from './index.js'
import type {
AccountFields,
Expand Down Expand Up @@ -70,20 +64,21 @@ import type { Debugger } from 'debug'
*/
export class DefaultStateManager implements StateManagerInterface {
protected _debug: Debugger
protected _accountCache?: AccountCache
protected _storageCache?: StorageCache
protected _codeCache?: CodeCache

originalStorageCache: OriginalStorageCache
_accountCache?: AccountCache
_storageCache?: StorageCache
_codeCache?: CodeCache

protected _trie: Trie
protected _storageTries: { [key: string]: Trie }

protected readonly _prefixCodeHashes: boolean
protected readonly _prefixStorageTrieKeys: boolean
protected readonly _accountCacheSettings: CacheSettings
protected readonly _storageCacheSettings: CacheSettings
protected readonly _codeCacheSettings: CacheSettings

// Non-null assertion necessary to inform TypeScript that these properties are set in the constructor through a helper function
originalStorageCache!: OriginalStorageCache
readonly _accountCacheSettings!: CacheSettings
readonly _storageCacheSettings!: CacheSettings
readonly _codeCacheSettings!: CacheSettings

public readonly common: Common

Expand Down Expand Up @@ -121,48 +116,10 @@ export class DefaultStateManager implements StateManagerInterface {

this.keccakFunction = opts.common?.customCrypto.keccak256 ?? keccak256

this.originalStorageCache = new OriginalStorageCache(this.getStorage.bind(this))

this._prefixCodeHashes = opts.prefixCodeHashes ?? true
this._prefixStorageTrieKeys = opts.prefixStorageTrieKeys ?? false
this._accountCacheSettings = {
deactivate:
(opts.accountCacheOpts?.deactivate === true || opts.accountCacheOpts?.size === 0) ?? false,
type: opts.accountCacheOpts?.type ?? CacheType.ORDERED_MAP,
size: opts.accountCacheOpts?.size ?? 100000,
}
if (!this._accountCacheSettings.deactivate) {
this._accountCache = new AccountCache({
size: this._accountCacheSettings.size,
type: this._accountCacheSettings.type,
})
}

this._storageCacheSettings = {
deactivate:
(opts.storageCacheOpts?.deactivate === true || opts.storageCacheOpts?.size === 0) ?? false,
type: opts.storageCacheOpts?.type ?? CacheType.ORDERED_MAP,
size: opts.storageCacheOpts?.size ?? 20000,
}
if (!this._storageCacheSettings.deactivate) {
this._storageCache = new StorageCache({
size: this._storageCacheSettings.size,
type: this._storageCacheSettings.type,
})
}

this._codeCacheSettings = {
deactivate:
(opts.codeCacheOpts?.deactivate === true || opts.codeCacheOpts?.size === 0) ?? false,
type: opts.codeCacheOpts?.type ?? CacheType.ORDERED_MAP,
size: opts.codeCacheOpts?.size ?? 20000,
}
if (!this._codeCacheSettings.deactivate) {
this._codeCache = new CodeCache({
size: this._codeCacheSettings.size,
type: this._codeCacheSettings.type,
})
}
Capabilities.initializeCaches(this, opts)
}

/**
Expand Down Expand Up @@ -505,9 +462,7 @@ export class DefaultStateManager implements StateManagerInterface {
*/
async checkpoint(): Promise<void> {
this._trie.checkpoint()
this._storageCache?.checkpoint()
this._accountCache?.checkpoint()
this._codeCache?.checkpoint()
Capabilities.checkpointCaches(this)
this._checkpointCount++
}

Expand All @@ -518,9 +473,7 @@ export class DefaultStateManager implements StateManagerInterface {
async commit(): Promise<void> {
// setup trie checkpointing
await this._trie.commit()
this._storageCache?.commit()
this._accountCache?.commit()
this._codeCache?.commit()
Capabilities.commitCaches(this)
this._checkpointCount--

if (this._checkpointCount === 0) {
Expand All @@ -540,9 +493,7 @@ export class DefaultStateManager implements StateManagerInterface {
async revert(): Promise<void> {
// setup trie checkpointing
await this._trie.revert()
this._storageCache?.revert()
this._accountCache?.revert()
this._codeCache?.revert()
Capabilities.revertCaches(this)

this._storageTries = {}

Expand Down
Loading

0 comments on commit dcae495

Please sign in to comment.