@ethereumjs/mpt
Version:
Implementation of the modified merkle patricia tree as specified in Ethereum's yellow paper.
53 lines (49 loc) • 1.82 kB
text/typescript
import { RLP } from '@ethereumjs/rlp'
import {
Account,
hexToBytes,
isHexString,
unpadBytes,
unprefixedHexToBytes,
} from '@ethereumjs/util'
import { keccak256 } from 'ethereum-cryptography/keccak.js'
import { MerklePatriciaTrie } from '../mpt.ts'
import type { AccountState, GenesisState } from '@ethereumjs/common'
/**
* Derives the stateRoot of the genesis block based on genesis allocations
*/
export async function genesisMPTStateRoot(genesisState: GenesisState) {
const trie = new MerklePatriciaTrie({ useKeyHashing: true })
for (const [key, value] of Object.entries(genesisState)) {
const address = isHexString(key) ? hexToBytes(key) : unprefixedHexToBytes(key)
const account = new Account()
if (typeof value === 'string') {
account.balance = BigInt(value)
} else {
const [balance, code, storage, nonce] = value as Partial<AccountState>
if (balance !== undefined) {
account.balance = BigInt(balance)
}
if (code !== undefined) {
const codeBytes = isHexString(code) ? hexToBytes(code) : unprefixedHexToBytes(code)
account.codeHash = keccak256(codeBytes)
}
if (storage !== undefined) {
const storageTrie = new MerklePatriciaTrie({ useKeyHashing: true })
for (const [k, val] of storage) {
const storageKey = isHexString(k) ? hexToBytes(k) : unprefixedHexToBytes(k)
const storageVal = RLP.encode(
unpadBytes(isHexString(val) ? hexToBytes(val) : unprefixedHexToBytes(val)),
)
await storageTrie.put(storageKey, storageVal)
}
account.storageRoot = storageTrie.root()
}
if (nonce !== undefined) {
account.nonce = BigInt(nonce)
}
}
await trie.put(address, account.serialize())
}
return trie.root()
}