Skip to content

Commit

Permalink
statemanager: refactor logic into capabilities (#3554)
Browse files Browse the repository at this point in the history
* statemanager; modifyAccountFields capability

* statemanager: refactor cache related capabilities

* statemanager: small fixes

* statemanager: remove duplicate types2

* client: fix import

* Merge remote-tracking branch 'origin/master' into statemanager/refactor-into-capabilities
  • Loading branch information
gabrocheleau authored Aug 5, 2024
1 parent 3810f1d commit d7d1dab
Show file tree
Hide file tree
Showing 18 changed files with 188 additions and 211 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
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 { EthProtocol } from '../../net/protocol/index.js'
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'
import type {
FeeMarketEIP1559Transaction,
LegacyTransaction,
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
88 changes: 88 additions & 0 deletions packages/statemanager/src/capabilities.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { type AccountFields, CacheType, type StateManagerInterface } from '@ethereumjs/common'
import { Account } from '@ethereumjs/util'

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,
accountFields: AccountFields,
): Promise<void> {
const account = (await stateManager.getAccount(address)) ?? new Account()

account.nonce = accountFields.nonce ?? account.nonce
account.balance = accountFields.balance ?? account.balance
account.storageRoot = accountFields.storageRoot ?? account.storageRoot
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()
}
29 changes: 12 additions & 17 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,23 +16,26 @@ 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'
import type { AccountFields, StateManagerInterface, StorageDump } from '@ethereumjs/common'
import type { RPCStateManagerOpts } from './index.js'
import type { AccountFields, Proof, StateManagerInterface, StorageDump } from '@ethereumjs/common'
import type { Address, PrefixedHexString } from '@ethereumjs/util'
import type { Debugger } from 'debug'

const KECCAK256_RLP_EMPTY_ACCOUNT = RLP.encode(new Account().serialize()).slice(2)

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 Expand Up @@ -317,15 +320,7 @@ export class RPCStateManager implements StateManagerInterface {
),
)
}
let account = await this.getAccount(address)
if (!account) {
account = new Account()
}
account.nonce = accountFields.nonce ?? account.nonce
account.balance = accountFields.balance ?? account.balance
account.storageRoot = accountFields.storageRoot ?? account.storageRoot
account.codeHash = accountFields.codeHash ?? account.codeHash
await this.putAccount(address, account)
await Capabilities.modifyAccountFields(this, address, accountFields)
}

/**
Expand Down
11 changes: 2 additions & 9 deletions packages/statemanager/src/simpleStateManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Account, bytesToHex } from '@ethereumjs/util'
import { keccak256 } from 'ethereum-cryptography/keccak.js'

import { OriginalStorageCache } from './cache/originalStorageCache.js'
import * as Capabilities from './capabilities.js'

import type { SimpleStateManagerOpts } from './index.js'
import type { AccountFields, Common, StateManagerInterface } from '@ethereumjs/common'
Expand Down Expand Up @@ -78,15 +79,7 @@ export class SimpleStateManager implements StateManagerInterface {
}

async modifyAccountFields(address: Address, accountFields: AccountFields): Promise<void> {
let account = await this.getAccount(address)
if (!account) {
account = new Account()
}
account.nonce = accountFields.nonce ?? account.nonce
account.balance = accountFields.balance ?? account.balance
account.storageRoot = accountFields.storageRoot ?? account.storageRoot
account.codeHash = accountFields.codeHash ?? account.codeHash
await this.putAccount(address, account)
await Capabilities.modifyAccountFields(this, address, accountFields)
}

async getCode(address: Address): Promise<Uint8Array> {
Expand Down
Loading

0 comments on commit d7d1dab

Please sign in to comment.