Skip to content

Commit

Permalink
Merge pull request #2227 from ethereumjs/big-messy-bunch
Browse files Browse the repository at this point in the history
Trie: Property Renaming & Visibility / Getter-Setter & Dependency Removals
  • Loading branch information
holgerd77 authored Aug 24, 2022
2 parents 7c0b0ad + 5eca0f0 commit 2e9e493
Show file tree
Hide file tree
Showing 49 changed files with 536 additions and 458 deletions.
16 changes: 2 additions & 14 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions packages/block/src/block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,10 +224,10 @@ export class Block {
return result
}

if (this.txTrie.root.equals(KECCAK256_RLP)) {
if (this.txTrie.root().equals(KECCAK256_RLP)) {
await this.genTxTrie()
}
result = this.txTrie.root.equals(this.header.transactionsTrie)
result = this.txTrie.root().equals(this.header.transactionsTrie)
return result
}

Expand Down
3 changes: 1 addition & 2 deletions packages/blockchain/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,7 @@
"ethereum-cryptography": "^1.1.2",
"level": "^8.0.0",
"lru-cache": "^5.1.1",
"memory-level": "^1.0.0",
"semaphore-async-await": "^1.5.1"
"memory-level": "^1.0.0"
},
"devDependencies": {
"@types/async": "^2.4.1",
Expand Down
2 changes: 1 addition & 1 deletion packages/blockchain/src/blockchain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import { Block, BlockHeader } from '@ethereumjs/block'
import { Chain, Common, ConsensusAlgorithm, ConsensusType, Hardfork } from '@ethereumjs/common'
import { isFalsy, isTruthy } from '@ethereumjs/util'
import { MemoryLevel } from 'memory-level'
import Semaphore from 'semaphore-async-await'

import { CasperConsensus, CliqueConsensus, EthashConsensus } from './consensus'
import { DBOp, DBSaveLookups, DBSetBlockOrHeader, DBSetHashToNumber, DBSetTD } from './db/helpers'
import { DBManager } from './db/manager'
import { DBTarget } from './db/operation'
import { genesisStateRoot } from './genesisStates'
import { Semaphore } from './semaphore'

import type { Consensus } from './consensus'
import type { GenesisState } from './genesisStates'
Expand Down
6 changes: 3 additions & 3 deletions packages/blockchain/src/genesisStates/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export interface GenesisState {
* Derives the stateRoot of the genesis block based on genesis allocations
*/
export async function genesisStateRoot(genesisState: GenesisState) {
const trie = new Trie({ useHashedKeys: true })
const trie = new Trie({ useKeyHashing: true })
for (const [key, value] of Object.entries(genesisState)) {
const address = isHexPrefixed(key) ? toBuffer(key) : Buffer.from(key, 'hex')
const account = new Account()
Expand All @@ -48,10 +48,10 @@ export async function genesisStateRoot(genesisState: GenesisState) {
)
await storageTrie.put(storageKey, storageVal)
}
account.storageRoot = storageTrie.root
account.storageRoot = storageTrie.root()
}
}
await trie.put(address, account.serialize())
}
return trie.root
return trie.root()
}
52 changes: 52 additions & 0 deletions packages/blockchain/src/semaphore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Based on https://github.com/jsoendermann/semaphore-async-await/blob/master/src/Semaphore.ts
export class Semaphore {
private permits: number
private promiseResolverQueue: Array<(v: boolean) => void> = []

/**
* Creates a semaphore.
* @param permits The number of permits, i.e. strands of execution being allowed
* to run in parallel.
* This number can be initialized with a negative integer.
*/
constructor(permits: number) {
this.permits = permits
}

/**
* Returns a promise used to wait for a permit to become available. This method should be awaited on.
* @returns A promise that gets resolved when execution is allowed to proceed.
*/
public async acquire(): Promise<boolean> {
if (this.permits > 0) {
this.permits -= 1
return Promise.resolve(true)
}

// If there is no permit available, we return a promise that resolves once the semaphore gets
// signaled enough times that permits is equal to one.
return new Promise<boolean>((resolver) => this.promiseResolverQueue.push(resolver))
}

/**
* Increases the number of permits by one. If there are other functions waiting, one of them will
* continue to execute in a future iteration of the event loop.
*/
public release(): void {
this.permits += 1

if (this.permits > 1 && this.promiseResolverQueue.length > 0) {
// eslint-disable-next-line no-console
console.warn('Semaphore.permits should never be > 0 when there is someone waiting.')
} else if (this.permits === 1 && this.promiseResolverQueue.length > 0) {
// If there is someone else waiting, immediately consume the permit that was released
// at the beginning of this function and let the waiting function resume.
this.permits -= 1

const nextResolver = this.promiseResolverQueue.shift()
if (nextResolver) {
nextResolver(true)
}
}
}
}
2 changes: 1 addition & 1 deletion packages/client/lib/execution/vmexecution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export class VMExecution extends Execution {
if (isFalsy(this.config.vm)) {
const trie = new Trie({
db: new LevelDB(this.stateDB),
useHashedKeys: true,
useKeyHashing: true,
})

const stateManager = new DefaultStateManager({
Expand Down
2 changes: 1 addition & 1 deletion packages/client/lib/rpc/modules/engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ const txsTrieRoot = async (txs: TypedTransaction[]) => {
for (const [i, tx] of txs.entries()) {
await trie.put(Buffer.from(RLP.encode(i)), tx.serialize())
}
return trie.root
return trie.root()
}

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/client/lib/util/debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const main = async () => {
.toString('hex')}', 'hex'), { common })
const stateDB = new Level('${execution.config.getDataDirectory(DataDirectory.State)}')
const trie = new Trie({ db: stateDB, useHashedKeys: true })
const trie = new Trie({ db: stateDB, useKeyHashing: true })
const stateManager = new DefaultStateManager({ trie, common })
// Ensure we run on the right root
stateManager.setStateRoot(Buffer.from('${(
Expand Down
25 changes: 13 additions & 12 deletions packages/statemanager/src/stateManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export class DefaultStateManager extends BaseStateManager implements StateManage
constructor(opts: DefaultStateManagerOpts = {}) {
super(opts)

this._trie = opts.trie ?? new Trie({ useHashedKeys: true })
this._trie = opts.trie ?? new Trie({ useKeyHashing: true })
this._storageTries = {}

this._prefixCodeHashes = opts.prefixCodeHashes ?? true
Expand Down Expand Up @@ -138,7 +138,8 @@ export class DefaultStateManager extends BaseStateManager implements StateManage
}

const key = this._prefixCodeHashes ? Buffer.concat([CODEHASH_PREFIX, codeHash]) : codeHash
await this._trie.db.put(key, value)
// @ts-expect-error
await this._trie._db.put(key, value)

if (this.DEBUG) {
this._debug(`Update codeHash (-> ${short(codeHash)}) for account ${address}`)
Expand All @@ -160,7 +161,8 @@ export class DefaultStateManager extends BaseStateManager implements StateManage
const key = this._prefixCodeHashes
? Buffer.concat([CODEHASH_PREFIX, account.codeHash])
: account.codeHash
const code = await this._trie.db.get(key)
// @ts-expect-error
const code = await this._trie._db.get(key)
return code ?? Buffer.alloc(0)
}

Expand All @@ -173,8 +175,8 @@ export class DefaultStateManager extends BaseStateManager implements StateManage
// from state trie
const account = await this.getAccount(address)
const storageTrie = this._trie.copy(false)
storageTrie.root = account.storageRoot
storageTrie.db.checkpoints = []
storageTrie.root(account.storageRoot)
storageTrie.flushCheckpoints()
return storageTrie
}

Expand Down Expand Up @@ -235,7 +237,7 @@ export class DefaultStateManager extends BaseStateManager implements StateManage

// update contract storageRoot
const contract = this._cache.get(address)
contract.storageRoot = storageTrie.root
contract.storageRoot = storageTrie.root()

await this.putAccount(address, contract)
resolve()
Expand Down Expand Up @@ -286,7 +288,7 @@ export class DefaultStateManager extends BaseStateManager implements StateManage
*/
async clearContractStorage(address: Address): Promise<void> {
await this._modifyContractStorage(address, (storageTrie, done) => {
storageTrie.root = storageTrie.EMPTY_TRIE_ROOT
storageTrie.root(storageTrie.EMPTY_TRIE_ROOT)
done()
})
}
Expand Down Expand Up @@ -374,7 +376,7 @@ export class DefaultStateManager extends BaseStateManager implements StateManage

// This returns the account if the proof is valid.
// Verify that it matches the reported account.
const value = await new Trie({ useHashedKeys: true }).verifyProof(rootHash, key, accountProof)
const value = await new Trie({ useKeyHashing: true }).verifyProof(rootHash, key, accountProof)

if (value === null) {
// Verify that the account is empty in the proof.
Expand Down Expand Up @@ -420,7 +422,7 @@ export class DefaultStateManager extends BaseStateManager implements StateManage
const storageProof = stProof.proof.map((value: PrefixedHexString) => toBuffer(value))
const storageValue = setLengthLeft(toBuffer(stProof.value), 32)
const storageKey = toBuffer(stProof.key)
const proofValue = await new Trie({ useHashedKeys: true }).verifyProof(
const proofValue = await new Trie({ useKeyHashing: true }).verifyProof(
storageRoot,
storageKey,
storageProof
Expand All @@ -444,8 +446,7 @@ export class DefaultStateManager extends BaseStateManager implements StateManage
*/
async getStateRoot(): Promise<Buffer> {
await this._cache.flush()
const stateRoot = this._trie.root
return stateRoot
return this._trie.root()
}

/**
Expand All @@ -465,7 +466,7 @@ export class DefaultStateManager extends BaseStateManager implements StateManage
}
}

this._trie.root = stateRoot
this._trie.root(stateRoot)
this._cache.clear()
this._storageTries = {}
}
Expand Down
6 changes: 3 additions & 3 deletions packages/statemanager/tests/cache.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import type { getCb, putCb } from '../src/cache'

tape('cache initialization', (t) => {
t.test('should initialize', async (st) => {
const trie = new Trie({ useHashedKeys: true })
const trie = new Trie({ useKeyHashing: true })
const getCb: getCb = async (address) => {
const innerTrie = trie
const rlp = await innerTrie.get(address.buf)
Expand All @@ -32,7 +32,7 @@ tape('cache initialization', (t) => {
})

tape('cache put and get account', (t) => {
const trie = new Trie({ useHashedKeys: true })
const trie = new Trie({ useKeyHashing: true })
const getCb: getCb = async (address) => {
const innerTrie = trie
const rlp = await innerTrie.get(address.buf)
Expand Down Expand Up @@ -103,7 +103,7 @@ tape('cache put and get account', (t) => {
})

tape('cache checkpointing', (t) => {
const trie = new Trie({ useHashedKeys: true })
const trie = new Trie({ useKeyHashing: true })
const getCb: getCb = async (address) => {
const innerTrie = trie
const rlp = await innerTrie.get(address.buf)
Expand Down
Loading

0 comments on commit 2e9e493

Please sign in to comment.