Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@ethereumjs/statemanager

Package Overview
Dependencies
Maintainers
4
Versions
20
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ethereumjs/statemanager - npm Package Compare versions

Comparing version 2.0.0 to 2.1.0

dist/cjs/cache/code.d.ts

6

dist/cjs/cache/account.js

@@ -37,4 +37,4 @@ "use strict";

_saveCachePreState(cacheKeyHex) {
const it = this._diffCache[this._checkpoints].get(cacheKeyHex);
if (it === undefined) {
const diffMap = this._diffCache[this._checkpoints];
if (!diffMap.has(cacheKeyHex)) {
let oldElem;

@@ -47,3 +47,3 @@ if (this._lruCache) {

}
this._diffCache[this._checkpoints].set(cacheKeyHex, oldElem);
diffMap.set(cacheKeyHex, oldElem);
}

@@ -50,0 +50,0 @@ }

export * from './account.js';
export * from './code.js';
export * from './storage.js';
export * from './types.js';
//# sourceMappingURL=index.d.ts.map

@@ -18,4 +18,5 @@ "use strict";

__exportStar(require("./account.js"), exports);
__exportStar(require("./code.js"), exports);
__exportStar(require("./storage.js"), exports);
__exportStar(require("./types.js"), exports);
//# sourceMappingURL=index.js.map

@@ -93,4 +93,10 @@ import { OrderedMap } from 'js-sdsl';

clear(): void;
/**
* Dumps the RLP-encoded storage values for an `account` specified by `address`.
* @param address - The address of the `account` to return storage for
* @returns {StorageCacheMap | undefined} - The storage values for the `account` or undefined if the `account` is not in the cache
*/
dump(address: Address): StorageCacheMap | undefined;
}
export {};
//# sourceMappingURL=storage.d.ts.map

@@ -40,9 +40,3 @@ "use strict";

const addressStoragePreState = this._diffCache[this._checkpoints].get(addressHex);
let diffStorageMap;
if (addressStoragePreState === undefined) {
diffStorageMap = new Map();
}
else {
diffStorageMap = addressStoragePreState;
}
const diffStorageMap = addressStoragePreState ?? new Map();
if (!diffStorageMap.has(keyHex)) {

@@ -327,4 +321,19 @@ let oldStorageMap;

}
/**
* Dumps the RLP-encoded storage values for an `account` specified by `address`.
* @param address - The address of the `account` to return storage for
* @returns {StorageCacheMap | undefined} - The storage values for the `account` or undefined if the `account` is not in the cache
*/
dump(address) {
let storageMap;
if (this._lruCache) {
storageMap = this._lruCache.get((0, util_1.bytesToUnprefixedHex)(address.bytes));
}
else {
storageMap = this._orderedMapCache?.getElementByKey((0, util_1.bytesToUnprefixedHex)(address.bytes));
}
return storageMap;
}
}
exports.StorageCache = StorageCache;
//# sourceMappingURL=storage.js.map

@@ -167,3 +167,3 @@ "use strict";

dumpStorage(address) {
const storageMap = this._storageCache._lruCache?.get(address.toString());
const storageMap = this._storageCache.dump(address);
const dump = {};

@@ -170,0 +170,0 @@ if (storageMap !== undefined) {

import { Common } from '@ethereumjs/common';
import { Trie } from '@ethereumjs/trie';
import { Account, Address } from '@ethereumjs/util';
import { AccountCache, CacheType, StorageCache } from './cache/index.js';
import { AccountCache, CacheType, CodeCache, StorageCache } from './cache/index.js';
import { OriginalStorageCache } from './cache/originalStorageCache.js';
import type { AccountFields, EVMStateManagerInterface, StorageDump } from '@ethereumjs/common';
import type { StorageRange } from '@ethereumjs/common/src';
import type { PrefixedHexString } from '@ethereumjs/util';
import type { DB, PrefixedHexString } from '@ethereumjs/util';
import type { Debugger } from 'debug';

@@ -49,3 +49,3 @@ export declare type StorageProof = {

*
* Default: 100000 (account cache) / 20000 (storage cache)
* Default: 100000 (account cache) / 20000 (storage cache) / 20000 (code cache)
*

@@ -88,4 +88,16 @@ * Note: the cache/trie interplay mechanism is designed in a way that

prefixCodeHashes?: boolean;
/**
* Option to prefix the keys for the storage tries with the first 7 bytes from the
* associated account address. Activating this option gives a noticeable performance
* boost for storage DB reads when operating on larger tries.
*
* Note: Activating/deactivating this option causes continued state reads to be
* incompatible with existing databases.
*
* Default: false (for backwards compatibility reasons)
*/
prefixStorageTrieKeys?: boolean;
accountCacheOpts?: CacheOptions;
storageCacheOpts?: CacheOptions;
codeCacheOpts?: CacheOptions;
/**

@@ -110,2 +122,3 @@ * The common to use

protected _storageCache?: StorageCache;
protected _codeCache?: CodeCache;
originalStorageCache: OriginalStorageCache;

@@ -116,8 +129,7 @@ protected _trie: Trie;

};
protected _codeCache: {
[key: string]: Uint8Array;
};
protected readonly _prefixCodeHashes: boolean;
protected readonly _prefixStorageTrieKeys: boolean;
protected readonly _accountCacheSettings: CacheSettings;
protected readonly _storageCacheSettings: CacheSettings;
protected readonly _codeCacheSettings: CacheSettings;
readonly common: Common;

@@ -182,4 +194,16 @@ protected _checkpointCount: number;

*/
protected _getStorageTrie(address: Address, account: Account): Promise<Trie>;
protected _getStorageTrie(addressOrHash: Address | Uint8Array, account?: Account): Trie;
/**
* Gets the storage trie for an account from the storage
* cache or does a lookup.
* @private
*/
protected _getAccountTrie(): Trie;
/**
* Gets the storage trie for an account from the storage
* cache or does a lookup.
* @private
*/
protected _getCodeDB(): DB;
/**
* Gets the storage value associated with the provided `address` and `key`. This method returns

@@ -296,3 +320,6 @@ * the shortest representation of the stored value.

*
* Note on caches:
* Caches are downleveled (so: adopted for short-term usage)
* by default.
*
* This means in particular:
* 1. For caches instantiated as an LRU cache type

@@ -303,5 +330,11 @@ * the copy() method will instantiate with an ORDERED_MAP cache

* a large overhead here.
* 2. Cache values are generally not copied along
* 2. The underlying trie object is initialized with 0 cache size
*
* Both adoptions can be deactivated by setting `downlevelCaches` to
* `false`.
*
* Cache values are generally not copied along regardless of the
* `downlevelCaches` setting.
*/
shallowCopy(): DefaultStateManager;
shallowCopy(downlevelCaches?: boolean): DefaultStateManager;
/**

@@ -308,0 +341,0 @@ * Clears all underlying caches

@@ -56,7 +56,7 @@ "use strict";

this._storageTries = {};
this._codeCache = {};
this.originalStorageCache = new originalStorageCache_js_1.OriginalStorageCache(this.getContractStorage.bind(this));
this._prefixCodeHashes = opts.prefixCodeHashes ?? true;
this._prefixStorageTrieKeys = opts.prefixStorageTrieKeys ?? false;
this._accountCacheSettings = {
deactivate: opts.accountCacheOpts?.deactivate ?? false,
deactivate: (opts.accountCacheOpts?.deactivate === true || opts.accountCacheOpts?.size === 0) ?? false,
type: opts.accountCacheOpts?.type ?? index_js_1.CacheType.ORDERED_MAP,

@@ -72,3 +72,3 @@ size: opts.accountCacheOpts?.size ?? 100000,

this._storageCacheSettings = {
deactivate: opts.storageCacheOpts?.deactivate ?? false,
deactivate: (opts.storageCacheOpts?.deactivate === true || opts.storageCacheOpts?.size === 0) ?? false,
type: opts.storageCacheOpts?.type ?? index_js_1.CacheType.ORDERED_MAP,

@@ -83,2 +83,13 @@ size: opts.storageCacheOpts?.size ?? 20000,

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

@@ -159,2 +170,3 @@ /**

}
this._codeCache?.del(address);
if (this._accountCacheSettings.deactivate) {

@@ -177,2 +189,3 @@ await this._trie.del(address.bytes);

async putContractCode(address, value) {
this._codeCache?.put(address, value);
const codeHash = (0, keccak_js_1.keccak256)(value);

@@ -182,6 +195,2 @@ if ((0, util_1.equalsBytes)(codeHash, util_1.KECCAK256_NULL)) {

}
const key = this._prefixCodeHashes ? (0, util_1.concatBytes)(exports.CODEHASH_PREFIX, codeHash) : codeHash;
await this._trie.database().put(key, value);
const keyHex = (0, util_1.bytesToUnprefixedHex)(key);
this._codeCache[keyHex] = value;
if (this.DEBUG) {

@@ -202,2 +211,8 @@ this._debug(`Update codeHash (-> ${(0, util_1.short)(codeHash)}) for account ${address}`);

async getContractCode(address) {
if (!this._codeCacheSettings.deactivate) {
const elem = this._codeCache?.get(address);
if (elem !== undefined) {
return elem.code ?? new Uint8Array(0);
}
}
const account = await this.getAccount(address);

@@ -213,11 +228,7 @@ if (!account) {

: account.codeHash;
const keyHex = (0, util_1.bytesToUnprefixedHex)(key);
if (keyHex in this._codeCache) {
return this._codeCache[keyHex];
const code = (await this._trie.database().get(key)) ?? new Uint8Array(0);
if (!this._codeCacheSettings.deactivate) {
this._codeCache.put(address, code);
}
else {
const code = (await this._trie.database().get(key)) ?? new Uint8Array(0);
this._codeCache[keyHex] = code;
return code;
}
return code;
}

@@ -229,12 +240,20 @@ /**

*/
async _getStorageTrie(address, account) {
// from storage cache
const addressHex = (0, util_1.bytesToUnprefixedHex)(address.bytes);
const storageTrie = this._storageTries[addressHex];
// TODO PR: have a better interface for hashed address pull?
_getStorageTrie(addressOrHash, account) {
// use hashed key for lookup from storage cache
const addressHex = (0, util_1.bytesToUnprefixedHex)(addressOrHash instanceof util_1.Address ? (0, keccak_js_1.keccak256)(addressOrHash.bytes) : addressOrHash);
let storageTrie = this._storageTries[addressHex];
if (storageTrie === undefined) {
const storageTrie = this._trie.shallowCopy(false);
storageTrie.root(account.storageRoot);
const keyPrefix = this._prefixStorageTrieKeys
? (addressOrHash instanceof util_1.Address ? (0, keccak_js_1.keccak256)(addressOrHash.bytes) : addressOrHash).slice(0, 7)
: undefined;
storageTrie = this._trie.shallowCopy(false, { keyPrefix });
if (account !== undefined) {
storageTrie.root(account.storageRoot);
}
else {
storageTrie.root(storageTrie.EMPTY_TRIE_ROOT);
}
storageTrie.flushCheckpoints();
this._storageTries[addressHex] = storageTrie;
return storageTrie;
}

@@ -244,2 +263,18 @@ return storageTrie;

/**
* Gets the storage trie for an account from the storage
* cache or does a lookup.
* @private
*/
_getAccountTrie() {
return this._trie;
}
/**
* Gets the storage trie for an account from the storage
* cache or does a lookup.
* @private
*/
_getCodeDB() {
return this._trie.database();
}
/**
* Gets the storage value associated with the provided `address` and `key`. This method returns

@@ -268,3 +303,3 @@ * the shortest representation of the stored value.

}
const trie = await this._getStorageTrie(address, account);
const trie = this._getStorageTrie(address, account);
const value = await trie.get(key);

@@ -286,3 +321,3 @@ if (!this._storageCacheSettings.deactivate) {

return new Promise(async (resolve) => {
const storageTrie = await this._getStorageTrie(address, account);
const storageTrie = this._getStorageTrie(address, account);
modifyTrie(storageTrie, async () => {

@@ -372,2 +407,3 @@ // update storage cache

this._accountCache?.checkpoint();
this._codeCache?.checkpoint();
this._checkpointCount++;

@@ -384,2 +420,3 @@ }

this._accountCache?.commit();
this._codeCache?.commit();
this._checkpointCount--;

@@ -403,4 +440,4 @@ if (this._checkpointCount === 0) {

this._accountCache?.revert();
this._codeCache?.revert();
this._storageTries = {};
this._codeCache = {};
this._checkpointCount--;

@@ -416,2 +453,21 @@ if (this._checkpointCount === 0) {

async flush() {
if (!this._codeCacheSettings.deactivate) {
const items = this._codeCache.flush();
for (const item of items) {
const addr = util_1.Address.fromString(`0x${item[0]}`);
const code = item[1].code;
if (code === undefined) {
continue;
}
// update code in database
const codeHash = (0, keccak_js_1.keccak256)(code);
const key = this._prefixCodeHashes ? (0, util_1.concatBytes)(exports.CODEHASH_PREFIX, codeHash) : codeHash;
await this._getCodeDB().put(key, code);
// update code root of associated account
if ((await this.getAccount(addr)) === undefined) {
await this.putAccount(addr, new util_1.Account());
}
await this.modifyAccountFields(addr, { codeHash });
}
}
if (!this._storageCacheSettings.deactivate) {

@@ -459,5 +515,5 @@ const items = this._storageCache.flush();

address: address.toString(),
balance: '0x',
balance: '0x0',
codeHash: util_1.KECCAK256_NULL_S,
nonce: '0x',
nonce: '0x0',
storageHash: util_1.KECCAK256_RLP_S,

@@ -471,3 +527,3 @@ accountProof: (await this._trie.createProof(address.bytes)).map((p) => (0, util_1.bytesToHex)(p)),

const storageProof = [];
const storageTrie = await this._getStorageTrie(address, account);
const storageTrie = this._getStorageTrie(address, account);
for (const storageKey of storageSlots) {

@@ -588,4 +644,6 @@ const proof = (await storageTrie.createProof(storageKey)).map((p) => (0, util_1.bytesToHex)(p));

}
if (this._codeCache !== undefined && clearCache) {
this._codeCache.clear();
}
this._storageTries = {};
this._codeCache = {};
}

@@ -605,15 +663,13 @@ /**

}
const trie = this._getStorageTrie(address, account);
return new Promise((resolve, reject) => {
this._getStorageTrie(address, account)
.then((trie) => {
const storage = {};
const stream = trie.createReadStream();
stream.on('data', (val) => {
storage[(0, util_1.bytesToHex)(val.key)] = (0, util_1.bytesToHex)(val.value);
});
stream.on('end', () => {
resolve(storage);
});
})
.catch((e) => {
const storage = {};
const stream = trie.createReadStream();
stream.on('data', (val) => {
storage[(0, util_1.bytesToHex)(val.key)] = (0, util_1.bytesToHex)(val.value);
});
stream.on('end', () => {
resolve(storage);
});
stream.on('error', (e) => {
reject(e);

@@ -641,41 +697,37 @@ });

}
const trie = this._getStorageTrie(address, account);
return new Promise((resolve, reject) => {
this._getStorageTrie(address, account)
.then((trie) => {
let inRange = false;
let i = 0;
/** Object conforming to {@link StorageRange.storage}. */
const storageMap = {};
const stream = trie.createReadStream();
stream.on('data', (val) => {
if (!inRange) {
// Check if the key is already in the correct range.
if ((0, util_1.bytesToBigInt)(val.key) >= startKey) {
inRange = true;
}
else {
return;
}
let inRange = false;
let i = 0;
/** Object conforming to {@link StorageRange.storage}. */
const storageMap = {};
const stream = trie.createReadStream();
stream.on('data', (val) => {
if (!inRange) {
// Check if the key is already in the correct range.
if ((0, util_1.bytesToBigInt)(val.key) >= startKey) {
inRange = true;
}
if (i < limit) {
storageMap[(0, util_1.bytesToHex)(val.key)] = { key: null, value: (0, util_1.bytesToHex)(val.value) };
i++;
else {
return;
}
else if (i === limit) {
resolve({
storage: storageMap,
nextKey: (0, util_1.bytesToHex)(val.key),
});
}
});
stream.on('end', () => {
}
if (i < limit) {
storageMap[(0, util_1.bytesToHex)(val.key)] = { key: null, value: (0, util_1.bytesToHex)(val.value) };
i++;
}
else if (i === limit) {
resolve({
storage: storageMap,
nextKey: null,
nextKey: (0, util_1.bytesToHex)(val.key),
});
}
});
stream.on('end', () => {
resolve({
storage: storageMap,
nextKey: null,
});
})
.catch((e) => {
reject(e);
});
stream.on('error', (e) => reject(e));
});

@@ -732,3 +784,6 @@ }

*
* Note on caches:
* Caches are downleveled (so: adopted for short-term usage)
* by default.
*
* This means in particular:
* 1. For caches instantiated as an LRU cache type

@@ -739,20 +794,37 @@ * the copy() method will instantiate with an ORDERED_MAP cache

* a large overhead here.
* 2. Cache values are generally not copied along
* 2. The underlying trie object is initialized with 0 cache size
*
* Both adoptions can be deactivated by setting `downlevelCaches` to
* `false`.
*
* Cache values are generally not copied along regardless of the
* `downlevelCaches` setting.
*/
shallowCopy() {
const trie = this._trie.shallowCopy(false);
shallowCopy(downlevelCaches = true) {
const common = this.common.copy();
common.setHardfork(this.common.hardfork());
const cacheSize = !downlevelCaches ? this._trie['_opts']['cacheSize'] : 0;
const trie = this._trie.shallowCopy(false, { cacheSize });
const prefixCodeHashes = this._prefixCodeHashes;
const prefixStorageTrieKeys = this._prefixStorageTrieKeys;
let accountCacheOpts = { ...this._accountCacheSettings };
if (!this._accountCacheSettings.deactivate) {
if (downlevelCaches && !this._accountCacheSettings.deactivate) {
accountCacheOpts = { ...accountCacheOpts, type: index_js_1.CacheType.ORDERED_MAP };
}
let storageCacheOpts = { ...this._storageCacheSettings };
if (!this._storageCacheSettings.deactivate) {
if (downlevelCaches && !this._storageCacheSettings.deactivate) {
storageCacheOpts = { ...storageCacheOpts, type: index_js_1.CacheType.ORDERED_MAP };
}
let codeCacheOpts = { ...this._codeCacheSettings };
if (!this._codeCacheSettings.deactivate) {
codeCacheOpts = { ...codeCacheOpts, type: index_js_1.CacheType.ORDERED_MAP };
}
return new DefaultStateManager({
common,
trie,
prefixStorageTrieKeys,
prefixCodeHashes,
accountCacheOpts,
storageCacheOpts,
codeCacheOpts,
});

@@ -766,2 +838,3 @@ }

this._storageCache?.clear();
this._codeCache?.clear();
}

@@ -768,0 +841,0 @@ }

@@ -34,4 +34,4 @@ import { bytesToUnprefixedHex } from '@ethereumjs/util';

_saveCachePreState(cacheKeyHex) {
const it = this._diffCache[this._checkpoints].get(cacheKeyHex);
if (it === undefined) {
const diffMap = this._diffCache[this._checkpoints];
if (!diffMap.has(cacheKeyHex)) {
let oldElem;

@@ -44,3 +44,3 @@ if (this._lruCache) {

}
this._diffCache[this._checkpoints].set(cacheKeyHex, oldElem);
diffMap.set(cacheKeyHex, oldElem);
}

@@ -47,0 +47,0 @@ }

export * from './account.js';
export * from './code.js';
export * from './storage.js';
export * from './types.js';
//# sourceMappingURL=index.d.ts.map
export * from './account.js';
export * from './code.js';
export * from './storage.js';
export * from './types.js';
//# sourceMappingURL=index.js.map

@@ -93,4 +93,10 @@ import { OrderedMap } from 'js-sdsl';

clear(): void;
/**
* Dumps the RLP-encoded storage values for an `account` specified by `address`.
* @param address - The address of the `account` to return storage for
* @returns {StorageCacheMap | undefined} - The storage values for the `account` or undefined if the `account` is not in the cache
*/
dump(address: Address): StorageCacheMap | undefined;
}
export {};
//# sourceMappingURL=storage.d.ts.map

@@ -37,9 +37,3 @@ import { bytesToUnprefixedHex, hexToBytes } from '@ethereumjs/util';

const addressStoragePreState = this._diffCache[this._checkpoints].get(addressHex);
let diffStorageMap;
if (addressStoragePreState === undefined) {
diffStorageMap = new Map();
}
else {
diffStorageMap = addressStoragePreState;
}
const diffStorageMap = addressStoragePreState ?? new Map();
if (!diffStorageMap.has(keyHex)) {

@@ -324,3 +318,18 @@ let oldStorageMap;

}
/**
* Dumps the RLP-encoded storage values for an `account` specified by `address`.
* @param address - The address of the `account` to return storage for
* @returns {StorageCacheMap | undefined} - The storage values for the `account` or undefined if the `account` is not in the cache
*/
dump(address) {
let storageMap;
if (this._lruCache) {
storageMap = this._lruCache.get(bytesToUnprefixedHex(address.bytes));
}
else {
storageMap = this._orderedMapCache?.getElementByKey(bytesToUnprefixedHex(address.bytes));
}
return storageMap;
}
}
//# sourceMappingURL=storage.js.map

@@ -164,3 +164,3 @@ import { Trie } from '@ethereumjs/trie';

dumpStorage(address) {
const storageMap = this._storageCache._lruCache?.get(address.toString());
const storageMap = this._storageCache.dump(address);
const dump = {};

@@ -167,0 +167,0 @@ if (storageMap !== undefined) {

import { Common } from '@ethereumjs/common';
import { Trie } from '@ethereumjs/trie';
import { Account, Address } from '@ethereumjs/util';
import { AccountCache, CacheType, StorageCache } from './cache/index.js';
import { AccountCache, CacheType, CodeCache, StorageCache } from './cache/index.js';
import { OriginalStorageCache } from './cache/originalStorageCache.js';
import type { AccountFields, EVMStateManagerInterface, StorageDump } from '@ethereumjs/common';
import type { StorageRange } from '@ethereumjs/common/src';
import type { PrefixedHexString } from '@ethereumjs/util';
import type { DB, PrefixedHexString } from '@ethereumjs/util';
import type { Debugger } from 'debug';

@@ -49,3 +49,3 @@ export declare type StorageProof = {

*
* Default: 100000 (account cache) / 20000 (storage cache)
* Default: 100000 (account cache) / 20000 (storage cache) / 20000 (code cache)
*

@@ -88,4 +88,16 @@ * Note: the cache/trie interplay mechanism is designed in a way that

prefixCodeHashes?: boolean;
/**
* Option to prefix the keys for the storage tries with the first 7 bytes from the
* associated account address. Activating this option gives a noticeable performance
* boost for storage DB reads when operating on larger tries.
*
* Note: Activating/deactivating this option causes continued state reads to be
* incompatible with existing databases.
*
* Default: false (for backwards compatibility reasons)
*/
prefixStorageTrieKeys?: boolean;
accountCacheOpts?: CacheOptions;
storageCacheOpts?: CacheOptions;
codeCacheOpts?: CacheOptions;
/**

@@ -110,2 +122,3 @@ * The common to use

protected _storageCache?: StorageCache;
protected _codeCache?: CodeCache;
originalStorageCache: OriginalStorageCache;

@@ -116,8 +129,7 @@ protected _trie: Trie;

};
protected _codeCache: {
[key: string]: Uint8Array;
};
protected readonly _prefixCodeHashes: boolean;
protected readonly _prefixStorageTrieKeys: boolean;
protected readonly _accountCacheSettings: CacheSettings;
protected readonly _storageCacheSettings: CacheSettings;
protected readonly _codeCacheSettings: CacheSettings;
readonly common: Common;

@@ -182,4 +194,16 @@ protected _checkpointCount: number;

*/
protected _getStorageTrie(address: Address, account: Account): Promise<Trie>;
protected _getStorageTrie(addressOrHash: Address | Uint8Array, account?: Account): Trie;
/**
* Gets the storage trie for an account from the storage
* cache or does a lookup.
* @private
*/
protected _getAccountTrie(): Trie;
/**
* Gets the storage trie for an account from the storage
* cache or does a lookup.
* @private
*/
protected _getCodeDB(): DB;
/**
* Gets the storage value associated with the provided `address` and `key`. This method returns

@@ -296,3 +320,6 @@ * the shortest representation of the stored value.

*
* Note on caches:
* Caches are downleveled (so: adopted for short-term usage)
* by default.
*
* This means in particular:
* 1. For caches instantiated as an LRU cache type

@@ -303,5 +330,11 @@ * the copy() method will instantiate with an ORDERED_MAP cache

* a large overhead here.
* 2. Cache values are generally not copied along
* 2. The underlying trie object is initialized with 0 cache size
*
* Both adoptions can be deactivated by setting `downlevelCaches` to
* `false`.
*
* Cache values are generally not copied along regardless of the
* `downlevelCaches` setting.
*/
shallowCopy(): DefaultStateManager;
shallowCopy(downlevelCaches?: boolean): DefaultStateManager;
/**

@@ -308,0 +341,0 @@ * Clears all underlying caches

@@ -7,3 +7,3 @@ import { Chain, Common } from '@ethereumjs/common';

import { keccak256 } from 'ethereum-cryptography/keccak.js';
import { AccountCache, CacheType, StorageCache } from './cache/index.js';
import { AccountCache, CacheType, CodeCache, StorageCache } from './cache/index.js';
import { OriginalStorageCache } from './cache/originalStorageCache.js';

@@ -54,7 +54,7 @@ const { debug: createDebugLogger } = debugDefault;

this._storageTries = {};
this._codeCache = {};
this.originalStorageCache = new OriginalStorageCache(this.getContractStorage.bind(this));
this._prefixCodeHashes = opts.prefixCodeHashes ?? true;
this._prefixStorageTrieKeys = opts.prefixStorageTrieKeys ?? false;
this._accountCacheSettings = {
deactivate: opts.accountCacheOpts?.deactivate ?? false,
deactivate: (opts.accountCacheOpts?.deactivate === true || opts.accountCacheOpts?.size === 0) ?? false,
type: opts.accountCacheOpts?.type ?? CacheType.ORDERED_MAP,

@@ -70,3 +70,3 @@ size: opts.accountCacheOpts?.size ?? 100000,

this._storageCacheSettings = {
deactivate: opts.storageCacheOpts?.deactivate ?? false,
deactivate: (opts.storageCacheOpts?.deactivate === true || opts.storageCacheOpts?.size === 0) ?? false,
type: opts.storageCacheOpts?.type ?? CacheType.ORDERED_MAP,

@@ -81,2 +81,13 @@ size: opts.storageCacheOpts?.size ?? 20000,

}
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,
});
}
}

@@ -157,2 +168,3 @@ /**

}
this._codeCache?.del(address);
if (this._accountCacheSettings.deactivate) {

@@ -175,2 +187,3 @@ await this._trie.del(address.bytes);

async putContractCode(address, value) {
this._codeCache?.put(address, value);
const codeHash = keccak256(value);

@@ -180,6 +193,2 @@ if (equalsBytes(codeHash, KECCAK256_NULL)) {

}
const key = this._prefixCodeHashes ? concatBytes(CODEHASH_PREFIX, codeHash) : codeHash;
await this._trie.database().put(key, value);
const keyHex = bytesToUnprefixedHex(key);
this._codeCache[keyHex] = value;
if (this.DEBUG) {

@@ -200,2 +209,8 @@ this._debug(`Update codeHash (-> ${short(codeHash)}) for account ${address}`);

async getContractCode(address) {
if (!this._codeCacheSettings.deactivate) {
const elem = this._codeCache?.get(address);
if (elem !== undefined) {
return elem.code ?? new Uint8Array(0);
}
}
const account = await this.getAccount(address);

@@ -211,11 +226,7 @@ if (!account) {

: account.codeHash;
const keyHex = bytesToUnprefixedHex(key);
if (keyHex in this._codeCache) {
return this._codeCache[keyHex];
const code = (await this._trie.database().get(key)) ?? new Uint8Array(0);
if (!this._codeCacheSettings.deactivate) {
this._codeCache.put(address, code);
}
else {
const code = (await this._trie.database().get(key)) ?? new Uint8Array(0);
this._codeCache[keyHex] = code;
return code;
}
return code;
}

@@ -227,12 +238,20 @@ /**

*/
async _getStorageTrie(address, account) {
// from storage cache
const addressHex = bytesToUnprefixedHex(address.bytes);
const storageTrie = this._storageTries[addressHex];
// TODO PR: have a better interface for hashed address pull?
_getStorageTrie(addressOrHash, account) {
// use hashed key for lookup from storage cache
const addressHex = bytesToUnprefixedHex(addressOrHash instanceof Address ? keccak256(addressOrHash.bytes) : addressOrHash);
let storageTrie = this._storageTries[addressHex];
if (storageTrie === undefined) {
const storageTrie = this._trie.shallowCopy(false);
storageTrie.root(account.storageRoot);
const keyPrefix = this._prefixStorageTrieKeys
? (addressOrHash instanceof Address ? keccak256(addressOrHash.bytes) : addressOrHash).slice(0, 7)
: undefined;
storageTrie = this._trie.shallowCopy(false, { keyPrefix });
if (account !== undefined) {
storageTrie.root(account.storageRoot);
}
else {
storageTrie.root(storageTrie.EMPTY_TRIE_ROOT);
}
storageTrie.flushCheckpoints();
this._storageTries[addressHex] = storageTrie;
return storageTrie;
}

@@ -242,2 +261,18 @@ return storageTrie;

/**
* Gets the storage trie for an account from the storage
* cache or does a lookup.
* @private
*/
_getAccountTrie() {
return this._trie;
}
/**
* Gets the storage trie for an account from the storage
* cache or does a lookup.
* @private
*/
_getCodeDB() {
return this._trie.database();
}
/**
* Gets the storage value associated with the provided `address` and `key`. This method returns

@@ -266,3 +301,3 @@ * the shortest representation of the stored value.

}
const trie = await this._getStorageTrie(address, account);
const trie = this._getStorageTrie(address, account);
const value = await trie.get(key);

@@ -284,3 +319,3 @@ if (!this._storageCacheSettings.deactivate) {

return new Promise(async (resolve) => {
const storageTrie = await this._getStorageTrie(address, account);
const storageTrie = this._getStorageTrie(address, account);
modifyTrie(storageTrie, async () => {

@@ -370,2 +405,3 @@ // update storage cache

this._accountCache?.checkpoint();
this._codeCache?.checkpoint();
this._checkpointCount++;

@@ -382,2 +418,3 @@ }

this._accountCache?.commit();
this._codeCache?.commit();
this._checkpointCount--;

@@ -401,4 +438,4 @@ if (this._checkpointCount === 0) {

this._accountCache?.revert();
this._codeCache?.revert();
this._storageTries = {};
this._codeCache = {};
this._checkpointCount--;

@@ -414,2 +451,21 @@ if (this._checkpointCount === 0) {

async flush() {
if (!this._codeCacheSettings.deactivate) {
const items = this._codeCache.flush();
for (const item of items) {
const addr = Address.fromString(`0x${item[0]}`);
const code = item[1].code;
if (code === undefined) {
continue;
}
// update code in database
const codeHash = keccak256(code);
const key = this._prefixCodeHashes ? concatBytes(CODEHASH_PREFIX, codeHash) : codeHash;
await this._getCodeDB().put(key, code);
// update code root of associated account
if ((await this.getAccount(addr)) === undefined) {
await this.putAccount(addr, new Account());
}
await this.modifyAccountFields(addr, { codeHash });
}
}
if (!this._storageCacheSettings.deactivate) {

@@ -457,5 +513,5 @@ const items = this._storageCache.flush();

address: address.toString(),
balance: '0x',
balance: '0x0',
codeHash: KECCAK256_NULL_S,
nonce: '0x',
nonce: '0x0',
storageHash: KECCAK256_RLP_S,

@@ -469,3 +525,3 @@ accountProof: (await this._trie.createProof(address.bytes)).map((p) => bytesToHex(p)),

const storageProof = [];
const storageTrie = await this._getStorageTrie(address, account);
const storageTrie = this._getStorageTrie(address, account);
for (const storageKey of storageSlots) {

@@ -586,4 +642,6 @@ const proof = (await storageTrie.createProof(storageKey)).map((p) => bytesToHex(p));

}
if (this._codeCache !== undefined && clearCache) {
this._codeCache.clear();
}
this._storageTries = {};
this._codeCache = {};
}

@@ -603,15 +661,13 @@ /**

}
const trie = this._getStorageTrie(address, account);
return new Promise((resolve, reject) => {
this._getStorageTrie(address, account)
.then((trie) => {
const storage = {};
const stream = trie.createReadStream();
stream.on('data', (val) => {
storage[bytesToHex(val.key)] = bytesToHex(val.value);
});
stream.on('end', () => {
resolve(storage);
});
})
.catch((e) => {
const storage = {};
const stream = trie.createReadStream();
stream.on('data', (val) => {
storage[bytesToHex(val.key)] = bytesToHex(val.value);
});
stream.on('end', () => {
resolve(storage);
});
stream.on('error', (e) => {
reject(e);

@@ -639,41 +695,37 @@ });

}
const trie = this._getStorageTrie(address, account);
return new Promise((resolve, reject) => {
this._getStorageTrie(address, account)
.then((trie) => {
let inRange = false;
let i = 0;
/** Object conforming to {@link StorageRange.storage}. */
const storageMap = {};
const stream = trie.createReadStream();
stream.on('data', (val) => {
if (!inRange) {
// Check if the key is already in the correct range.
if (bytesToBigInt(val.key) >= startKey) {
inRange = true;
}
else {
return;
}
let inRange = false;
let i = 0;
/** Object conforming to {@link StorageRange.storage}. */
const storageMap = {};
const stream = trie.createReadStream();
stream.on('data', (val) => {
if (!inRange) {
// Check if the key is already in the correct range.
if (bytesToBigInt(val.key) >= startKey) {
inRange = true;
}
if (i < limit) {
storageMap[bytesToHex(val.key)] = { key: null, value: bytesToHex(val.value) };
i++;
else {
return;
}
else if (i === limit) {
resolve({
storage: storageMap,
nextKey: bytesToHex(val.key),
});
}
});
stream.on('end', () => {
}
if (i < limit) {
storageMap[bytesToHex(val.key)] = { key: null, value: bytesToHex(val.value) };
i++;
}
else if (i === limit) {
resolve({
storage: storageMap,
nextKey: null,
nextKey: bytesToHex(val.key),
});
}
});
stream.on('end', () => {
resolve({
storage: storageMap,
nextKey: null,
});
})
.catch((e) => {
reject(e);
});
stream.on('error', (e) => reject(e));
});

@@ -730,3 +782,6 @@ }

*
* Note on caches:
* Caches are downleveled (so: adopted for short-term usage)
* by default.
*
* This means in particular:
* 1. For caches instantiated as an LRU cache type

@@ -737,20 +792,37 @@ * the copy() method will instantiate with an ORDERED_MAP cache

* a large overhead here.
* 2. Cache values are generally not copied along
* 2. The underlying trie object is initialized with 0 cache size
*
* Both adoptions can be deactivated by setting `downlevelCaches` to
* `false`.
*
* Cache values are generally not copied along regardless of the
* `downlevelCaches` setting.
*/
shallowCopy() {
const trie = this._trie.shallowCopy(false);
shallowCopy(downlevelCaches = true) {
const common = this.common.copy();
common.setHardfork(this.common.hardfork());
const cacheSize = !downlevelCaches ? this._trie['_opts']['cacheSize'] : 0;
const trie = this._trie.shallowCopy(false, { cacheSize });
const prefixCodeHashes = this._prefixCodeHashes;
const prefixStorageTrieKeys = this._prefixStorageTrieKeys;
let accountCacheOpts = { ...this._accountCacheSettings };
if (!this._accountCacheSettings.deactivate) {
if (downlevelCaches && !this._accountCacheSettings.deactivate) {
accountCacheOpts = { ...accountCacheOpts, type: CacheType.ORDERED_MAP };
}
let storageCacheOpts = { ...this._storageCacheSettings };
if (!this._storageCacheSettings.deactivate) {
if (downlevelCaches && !this._storageCacheSettings.deactivate) {
storageCacheOpts = { ...storageCacheOpts, type: CacheType.ORDERED_MAP };
}
let codeCacheOpts = { ...this._codeCacheSettings };
if (!this._codeCacheSettings.deactivate) {
codeCacheOpts = { ...codeCacheOpts, type: CacheType.ORDERED_MAP };
}
return new DefaultStateManager({
common,
trie,
prefixStorageTrieKeys,
prefixCodeHashes,
accountCacheOpts,
storageCacheOpts,
codeCacheOpts,
});

@@ -764,4 +836,5 @@ }

this._storageCache?.clear();
this._codeCache?.clear();
}
}
//# sourceMappingURL=stateManager.js.map
{
"name": "@ethereumjs/statemanager",
"version": "2.0.0",
"version": "2.1.0",
"description": "An Ethereum statemanager implementation",

@@ -38,3 +38,3 @@ "keywords": [

"clean": "../../config/cli/clean-package.sh",
"coverage": "npx vitest run --coverage.enabled --coverage.reporter=lcov",
"coverage": "DEBUG=ethjs npx vitest run --coverage.enabled --coverage.reporter=lcov",
"docs:build": "typedoc --options typedoc.cjs",

@@ -52,4 +52,6 @@ "examples": "ts-node ../../scripts/examples-runner.ts -- statemanager",

"dependencies": {
"@ethereumjs/common": "^4.0.0",
"@ethereumjs/rlp": "^5.0.0",
"@ethereumjs/common": "^4.1.0",
"@ethereumjs/rlp": "^5.0.1",
"@ethereumjs/trie": "^6.0.1",
"@ethereumjs/util": "^9.0.1",
"debug": "^4.3.3",

@@ -62,9 +64,6 @@ "ethereum-cryptography": "^2.1.2",

"devDependencies": {
"@ethereumjs/block": "^5.0.0",
"@ethereumjs/genesis": "^0.1.0",
"@ethereumjs/trie": "^6.0.0",
"@ethereumjs/util": "^9.0.0",
"debug": "^4.3.3",
"ethereum-cryptography": "^2.1.2"
"@ethereumjs/block": "^5.0.1",
"@ethereumjs/genesis": "^0.2.0",
"@types/debug": "^4.1.9"
}
}

@@ -48,5 +48,5 @@ # @ethereumjs/statemanager

### Account and Storage Caches
### Account, Storage and Code Caches
Starting with the v2 release the StateManager comes with a significantly more elaborate caching mechanism for account and storage caches.
Starting with the v2 release and complemented by the v2.1 release the StateManager comes with a significantly more elaborate caching mechanism for account, storage and code caches.

@@ -53,0 +53,0 @@ There are now two cache options available: an unbounded cache (`CacheType.ORDERED_MAP`) for short-lived usage scenarios (this one is the default cache) and a fixed-size cache (`CacheType.LRU`) for a long-lived large cache scenario.

@@ -52,4 +52,4 @@ import { bytesToUnprefixedHex } from '@ethereumjs/util'

_saveCachePreState(cacheKeyHex: string) {
const it = this._diffCache[this._checkpoints].get(cacheKeyHex)
if (it === undefined) {
const diffMap = this._diffCache[this._checkpoints]
if (!diffMap.has(cacheKeyHex)) {
let oldElem: AccountCacheElement | undefined

@@ -61,3 +61,3 @@ if (this._lruCache) {

}
this._diffCache[this._checkpoints].set(cacheKeyHex, oldElem)
diffMap.set(cacheKeyHex, oldElem)
}

@@ -64,0 +64,0 @@ }

export * from './account.js'
export * from './code.js'
export * from './storage.js'
export * from './types.js'

@@ -56,8 +56,3 @@ import { bytesToUnprefixedHex, hexToBytes } from '@ethereumjs/util'

const addressStoragePreState = this._diffCache[this._checkpoints].get(addressHex)
let diffStorageMap: DiffStorageCacheMap
if (addressStoragePreState === undefined) {
diffStorageMap = new Map()
} else {
diffStorageMap = addressStoragePreState
}
const diffStorageMap: DiffStorageCacheMap = addressStoragePreState ?? new Map()

@@ -358,2 +353,17 @@ if (!diffStorageMap.has(keyHex)) {

}
/**
* Dumps the RLP-encoded storage values for an `account` specified by `address`.
* @param address - The address of the `account` to return storage for
* @returns {StorageCacheMap | undefined} - The storage values for the `account` or undefined if the `account` is not in the cache
*/
dump(address: Address): StorageCacheMap | undefined {
let storageMap
if (this._lruCache) {
storageMap = this._lruCache!.get(bytesToUnprefixedHex(address.bytes))
} else {
storageMap = this._orderedMapCache?.getElementByKey(bytesToUnprefixedHex(address.bytes))
}
return storageMap
}
}

@@ -185,3 +185,3 @@ import { Trie } from '@ethereumjs/trie'

dumpStorage(address: Address): Promise<StorageDump> {
const storageMap = this._storageCache._lruCache?.get(address.toString())
const storageMap = this._storageCache.dump(address)
const dump: StorageDump = {}

@@ -188,0 +188,0 @@ if (storageMap !== undefined) {

@@ -28,3 +28,3 @@ import { Chain, Common } from '@ethereumjs/common'

import { AccountCache, CacheType, StorageCache } from './cache/index.js'
import { AccountCache, CacheType, CodeCache, StorageCache } from './cache/index.js'
import { OriginalStorageCache } from './cache/originalStorageCache.js'

@@ -34,3 +34,3 @@

import type { StorageRange } from '@ethereumjs/common/src'
import type { PrefixedHexString } from '@ethereumjs/util'
import type { DB, PrefixedHexString } from '@ethereumjs/util'
import type { Debugger } from 'debug'

@@ -82,3 +82,3 @@ const { debug: createDebugLogger } = debugDefault

*
* Default: 100000 (account cache) / 20000 (storage cache)
* Default: 100000 (account cache) / 20000 (storage cache) / 20000 (code cache)
*

@@ -125,2 +125,14 @@ * Note: the cache/trie interplay mechanism is designed in a way that

/**
* Option to prefix the keys for the storage tries with the first 7 bytes from the
* associated account address. Activating this option gives a noticeable performance
* boost for storage DB reads when operating on larger tries.
*
* Note: Activating/deactivating this option causes continued state reads to be
* incompatible with existing databases.
*
* Default: false (for backwards compatibility reasons)
*/
prefixStorageTrieKeys?: boolean
accountCacheOpts?: CacheOptions

@@ -130,2 +142,4 @@

codeCacheOpts?: CacheOptions
/**

@@ -151,2 +165,3 @@ * The common to use

protected _storageCache?: StorageCache
protected _codeCache?: CodeCache

@@ -157,7 +172,8 @@ originalStorageCache: OriginalStorageCache

protected _storageTries: { [key: string]: Trie }
protected _codeCache: { [key: string]: Uint8Array }
protected readonly _prefixCodeHashes: boolean
protected readonly _prefixStorageTrieKeys: boolean
protected readonly _accountCacheSettings: CacheSettings
protected readonly _storageCacheSettings: CacheSettings
protected readonly _codeCacheSettings: CacheSettings

@@ -199,3 +215,2 @@ public readonly common: Common

this._storageTries = {}
this._codeCache = {}

@@ -205,4 +220,6 @@ this.originalStorageCache = new OriginalStorageCache(this.getContractStorage.bind(this))

this._prefixCodeHashes = opts.prefixCodeHashes ?? true
this._prefixStorageTrieKeys = opts.prefixStorageTrieKeys ?? false
this._accountCacheSettings = {
deactivate: opts.accountCacheOpts?.deactivate ?? false,
deactivate:
(opts.accountCacheOpts?.deactivate === true || opts.accountCacheOpts?.size === 0) ?? false,
type: opts.accountCacheOpts?.type ?? CacheType.ORDERED_MAP,

@@ -220,3 +237,4 @@ size: opts.accountCacheOpts?.size ?? 100000,

this._storageCacheSettings = {
deactivate: opts.storageCacheOpts?.deactivate ?? false,
deactivate:
(opts.storageCacheOpts?.deactivate === true || opts.storageCacheOpts?.size === 0) ?? false,
type: opts.storageCacheOpts?.type ?? CacheType.ORDERED_MAP,

@@ -232,2 +250,16 @@ size: opts.storageCacheOpts?.size ?? 20000,

}
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,
})
}
}

@@ -316,2 +348,5 @@

}
this._codeCache?.del(address)
if (this._accountCacheSettings.deactivate) {

@@ -334,4 +369,4 @@ await this._trie.del(address.bytes)

async putContractCode(address: Address, value: Uint8Array): Promise<void> {
this._codeCache?.put(address, value)
const codeHash = keccak256(value)
if (equalsBytes(codeHash, KECCAK256_NULL)) {

@@ -341,11 +376,6 @@ return

const key = this._prefixCodeHashes ? concatBytes(CODEHASH_PREFIX, codeHash) : codeHash
await this._trie.database().put(key, value)
const keyHex = bytesToUnprefixedHex(key)
this._codeCache[keyHex] = value
if (this.DEBUG) {
this._debug(`Update codeHash (-> ${short(codeHash)}) for account ${address}`)
}
if ((await this.getAccount(address)) === undefined) {

@@ -364,2 +394,8 @@ await this.putAccount(address, new Account())

async getContractCode(address: Address): Promise<Uint8Array> {
if (!this._codeCacheSettings.deactivate) {
const elem = this._codeCache?.get(address)
if (elem !== undefined) {
return elem.code ?? new Uint8Array(0)
}
}
const account = await this.getAccount(address)

@@ -375,11 +411,8 @@ if (!account) {

: account.codeHash
const code = (await this._trie.database().get(key)) ?? new Uint8Array(0)
const keyHex = bytesToUnprefixedHex(key)
if (keyHex in this._codeCache) {
return this._codeCache[keyHex]
} else {
const code = (await this._trie.database().get(key)) ?? new Uint8Array(0)
this._codeCache[keyHex] = code
return code
if (!this._codeCacheSettings.deactivate) {
this._codeCache!.put(address, code)
}
return code
}

@@ -392,12 +425,24 @@

*/
protected async _getStorageTrie(address: Address, account: Account): Promise<Trie> {
// from storage cache
const addressHex = bytesToUnprefixedHex(address.bytes)
const storageTrie = this._storageTries[addressHex]
// TODO PR: have a better interface for hashed address pull?
protected _getStorageTrie(addressOrHash: Address | Uint8Array, account?: Account): Trie {
// use hashed key for lookup from storage cache
const addressHex = bytesToUnprefixedHex(
addressOrHash instanceof Address ? keccak256(addressOrHash.bytes) : addressOrHash
)
let storageTrie = this._storageTries[addressHex]
if (storageTrie === undefined) {
const storageTrie = this._trie.shallowCopy(false)
storageTrie.root(account.storageRoot)
const keyPrefix = this._prefixStorageTrieKeys
? (addressOrHash instanceof Address ? keccak256(addressOrHash.bytes) : addressOrHash).slice(
0,
7
)
: undefined
storageTrie = this._trie.shallowCopy(false, { keyPrefix })
if (account !== undefined) {
storageTrie.root(account.storageRoot)
} else {
storageTrie.root(storageTrie.EMPTY_TRIE_ROOT)
}
storageTrie.flushCheckpoints()
this._storageTries[addressHex] = storageTrie
return storageTrie
}

@@ -408,2 +453,20 @@ return storageTrie

/**
* Gets the storage trie for an account from the storage
* cache or does a lookup.
* @private
*/
protected _getAccountTrie(): Trie {
return this._trie
}
/**
* Gets the storage trie for an account from the storage
* cache or does a lookup.
* @private
*/
protected _getCodeDB(): DB {
return this._trie.database()
}
/**
* Gets the storage value associated with the provided `address` and `key`. This method returns

@@ -433,3 +496,3 @@ * the shortest representation of the stored value.

}
const trie = await this._getStorageTrie(address, account)
const trie = this._getStorageTrie(address, account)
const value = await trie.get(key)

@@ -456,3 +519,3 @@ if (!this._storageCacheSettings.deactivate) {

return new Promise(async (resolve) => {
const storageTrie = await this._getStorageTrie(address, account)
const storageTrie = this._getStorageTrie(address, account)

@@ -554,2 +617,3 @@ modifyTrie(storageTrie, async () => {

this._accountCache?.checkpoint()
this._codeCache?.checkpoint()
this._checkpointCount++

@@ -567,2 +631,3 @@ }

this._accountCache?.commit()
this._codeCache?.commit()
this._checkpointCount--

@@ -589,4 +654,5 @@

this._accountCache?.revert()
this._codeCache?.revert()
this._storageTries = {}
this._codeCache = {}

@@ -605,2 +671,24 @@ this._checkpointCount--

async flush(): Promise<void> {
if (!this._codeCacheSettings.deactivate) {
const items = this._codeCache!.flush()
for (const item of items) {
const addr = Address.fromString(`0x${item[0]}`)
const code = item[1].code
if (code === undefined) {
continue
}
// update code in database
const codeHash = keccak256(code)
const key = this._prefixCodeHashes ? concatBytes(CODEHASH_PREFIX, codeHash) : codeHash
await this._getCodeDB().put(key, code)
// update code root of associated account
if ((await this.getAccount(addr)) === undefined) {
await this.putAccount(addr, new Account())
}
await this.modifyAccountFields(addr, { codeHash })
}
}
if (!this._storageCacheSettings.deactivate) {

@@ -649,5 +737,5 @@ const items = this._storageCache!.flush()

address: address.toString(),
balance: '0x',
balance: '0x0',
codeHash: KECCAK256_NULL_S,
nonce: '0x',
nonce: '0x0',
storageHash: KECCAK256_RLP_S,

@@ -663,3 +751,3 @@ accountProof: (await this._trie.createProof(address.bytes)).map((p) => bytesToHex(p)),

const storageProof: StorageProof[] = []
const storageTrie = await this._getStorageTrie(address, account)
const storageTrie = this._getStorageTrie(address, account)

@@ -795,4 +883,6 @@ for (const storageKey of storageSlots) {

}
if (this._codeCache !== undefined && clearCache) {
this._codeCache!.clear()
}
this._storageTries = {}
this._codeCache = {}
}

@@ -813,19 +903,17 @@

}
const trie = this._getStorageTrie(address, account)
return new Promise((resolve, reject) => {
this._getStorageTrie(address, account)
.then((trie) => {
const storage: StorageDump = {}
const stream = trie.createReadStream()
const storage: StorageDump = {}
const stream = trie.createReadStream()
stream.on('data', (val: any) => {
storage[bytesToHex(val.key)] = bytesToHex(val.value)
})
stream.on('end', () => {
resolve(storage)
})
})
.catch((e) => {
reject(e)
})
stream.on('data', (val: any) => {
storage[bytesToHex(val.key)] = bytesToHex(val.value)
})
stream.on('end', () => {
resolve(storage)
})
stream.on('error', (e) => {
reject(e)
})
})

@@ -853,44 +941,40 @@ }

}
const trie = this._getStorageTrie(address, account)
return new Promise((resolve, reject) => {
this._getStorageTrie(address, account)
.then((trie) => {
let inRange = false
let i = 0
let inRange = false
let i = 0
/** Object conforming to {@link StorageRange.storage}. */
const storageMap: StorageRange['storage'] = {}
const stream = trie.createReadStream()
/** Object conforming to {@link StorageRange.storage}. */
const storageMap: StorageRange['storage'] = {}
const stream = trie.createReadStream()
stream.on('data', (val: any) => {
if (!inRange) {
// Check if the key is already in the correct range.
if (bytesToBigInt(val.key) >= startKey) {
inRange = true
} else {
return
}
}
stream.on('data', (val: any) => {
if (!inRange) {
// Check if the key is already in the correct range.
if (bytesToBigInt(val.key) >= startKey) {
inRange = true
} else {
return
}
}
if (i < limit) {
storageMap[bytesToHex(val.key)] = { key: null, value: bytesToHex(val.value) }
i++
} else if (i === limit) {
resolve({
storage: storageMap,
nextKey: bytesToHex(val.key),
})
}
if (i < limit) {
storageMap[bytesToHex(val.key)] = { key: null, value: bytesToHex(val.value) }
i++
} else if (i === limit) {
resolve({
storage: storageMap,
nextKey: bytesToHex(val.key),
})
}
})
stream.on('end', () => {
resolve({
storage: storageMap,
nextKey: null,
})
})
stream.on('end', () => {
resolve({
storage: storageMap,
nextKey: null,
})
.catch((e) => {
reject(e)
})
})
stream.on('error', (e) => reject(e))
})

@@ -949,3 +1033,6 @@ }

*
* Note on caches:
* Caches are downleveled (so: adopted for short-term usage)
* by default.
*
* This means in particular:
* 1. For caches instantiated as an LRU cache type

@@ -956,21 +1043,39 @@ * the copy() method will instantiate with an ORDERED_MAP cache

* a large overhead here.
* 2. Cache values are generally not copied along
* 2. The underlying trie object is initialized with 0 cache size
*
* Both adoptions can be deactivated by setting `downlevelCaches` to
* `false`.
*
* Cache values are generally not copied along regardless of the
* `downlevelCaches` setting.
*/
shallowCopy(): DefaultStateManager {
const trie = this._trie.shallowCopy(false)
shallowCopy(downlevelCaches = true): DefaultStateManager {
const common = this.common.copy()
common.setHardfork(this.common.hardfork())
const cacheSize = !downlevelCaches ? this._trie['_opts']['cacheSize'] : 0
const trie = this._trie.shallowCopy(false, { cacheSize })
const prefixCodeHashes = this._prefixCodeHashes
const prefixStorageTrieKeys = this._prefixStorageTrieKeys
let accountCacheOpts = { ...this._accountCacheSettings }
if (!this._accountCacheSettings.deactivate) {
if (downlevelCaches && !this._accountCacheSettings.deactivate) {
accountCacheOpts = { ...accountCacheOpts, type: CacheType.ORDERED_MAP }
}
let storageCacheOpts = { ...this._storageCacheSettings }
if (!this._storageCacheSettings.deactivate) {
if (downlevelCaches && !this._storageCacheSettings.deactivate) {
storageCacheOpts = { ...storageCacheOpts, type: CacheType.ORDERED_MAP }
}
let codeCacheOpts = { ...this._codeCacheSettings }
if (!this._codeCacheSettings.deactivate) {
codeCacheOpts = { ...codeCacheOpts, type: CacheType.ORDERED_MAP }
}
return new DefaultStateManager({
common,
trie,
prefixStorageTrieKeys,
prefixCodeHashes,
accountCacheOpts,
storageCacheOpts,
codeCacheOpts,
})

@@ -985,3 +1090,4 @@ }

this._storageCache?.clear()
this._codeCache?.clear()
}
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc