From aac2bef7c6a9300bbfa4264b0cfdfd9603847a11 Mon Sep 17 00:00:00 2001 From: Gabriel Rocheleau Date: Wed, 6 Dec 2023 11:37:44 -0500 Subject: [PATCH] StateManager: stateless verkle state manager (#3139) Co-authored-by: harkamal --- package-lock.json | 9 + packages/block/src/block.ts | 96 ++- packages/block/src/from-beacon-payload.ts | 9 +- packages/block/src/header.ts | 10 +- packages/block/src/types.ts | 59 ++ .../block/test/from-beacon-payload.spec.ts | 23 + packages/block/test/mergeBlock.spec.ts | 2 +- .../test/testdata/payload-kaustinen.json | 284 +++++++ .../test/testdata/testnetVerkleKaustinen.json | 76 ++ packages/blockchain/src/blockchain.ts | 52 +- packages/blockchain/src/db/helpers.ts | 3 +- packages/blockchain/src/db/manager.ts | 4 +- packages/blockchain/test/util.ts | 2 +- packages/client/bin/cli.ts | 39 +- packages/client/package.json | 1 + packages/client/src/blockchain/chain.ts | 9 +- packages/client/src/client.ts | 6 + packages/client/src/config.ts | 6 + packages/client/src/execution/vmexecution.ts | 342 ++++++-- packages/client/src/types.ts | 4 + .../client/test/rpc/engine/kaustinen2.spec.ts | 115 +++ packages/client/test/rpc/helpers.ts | 14 +- .../test/testdata/blocks/kaustinen2.json | 788 ++++++++++++++++++ .../testdata/geth-genesis/kaustinen2.json | 86 ++ packages/common/src/chains.ts | 82 ++ packages/common/src/eips.ts | 16 + packages/common/src/enums.ts | 7 + packages/common/src/hardforks.ts | 8 + packages/common/src/utils.ts | 18 +- packages/evm/src/evm.ts | 3 +- .../genesis/src/genesisStates/kaustinen.ts | 0 packages/genesis/test/index.spec.ts | 7 +- packages/statemanager/package.json | 8 + packages/statemanager/src/index.ts | 1 + .../src/statelessVerkleStateManager.ts | 645 ++++++++++++++ .../test/statelessVerkleStateManager.spec.ts | 46 + .../test/testdata/testnetVerkleKaustinen.json | 76 ++ .../test/testdata/verkleKaustinenBlock.json | 647 ++++++++++++++ packages/statemanager/tsconfig.prod.cjs.json | 3 +- packages/statemanager/tsconfig.prod.esm.json | 3 +- .../statemanager/vitest.config.browser.ts | 2 + packages/util/src/bytes.ts | 11 +- packages/verkle/src/util/crypto.ts | 33 +- packages/verkle/src/verkleTree.ts | 13 +- packages/verkle/test/crypto.spec.ts | 20 + .../test/{node => }/internalNode.spec.ts | 8 +- .../verkle/test/{node => }/leafNode.spec.ts | 6 +- packages/vm/src/runBlock.ts | 31 +- packages/vm/test/api/types.spec.ts | 5 +- 49 files changed, 3583 insertions(+), 155 deletions(-) create mode 100644 packages/block/test/testdata/payload-kaustinen.json create mode 100644 packages/block/test/testdata/testnetVerkleKaustinen.json create mode 100644 packages/client/test/rpc/engine/kaustinen2.spec.ts create mode 100644 packages/client/test/testdata/blocks/kaustinen2.json create mode 100644 packages/client/test/testdata/geth-genesis/kaustinen2.json create mode 100644 packages/genesis/src/genesisStates/kaustinen.ts create mode 100644 packages/statemanager/src/statelessVerkleStateManager.ts create mode 100644 packages/statemanager/test/statelessVerkleStateManager.spec.ts create mode 100644 packages/statemanager/test/testdata/testnetVerkleKaustinen.json create mode 100644 packages/statemanager/test/testdata/verkleKaustinenBlock.json create mode 100644 packages/verkle/test/crypto.spec.ts rename packages/verkle/test/{node => }/internalNode.spec.ts (87%) rename packages/verkle/test/{node => }/leafNode.spec.ts (89%) diff --git a/package-lock.json b/package-lock.json index f461f9cccd..70d273b47f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15759,6 +15759,7 @@ "@ethereumjs/trie": "6.0.1", "@ethereumjs/tx": "5.1.0", "@ethereumjs/util": "9.0.1", + "@ethereumjs/verkle": "^0.0.1", "@ethereumjs/vm": "7.1.0", "abstract-level": "^1.0.3", "body-parser": "^1.19.2", @@ -16078,6 +16079,14 @@ "@ethereumjs/block": "^5.0.1", "@ethereumjs/genesis": "^0.2.0", "@types/debug": "^4.1.9" + }, + "peerDependencies": { + "@ethereumjs/verkle": "^0.0.1" + }, + "peerDependenciesMeta": { + "@ethereumjs/verkle": { + "optional": true + } } }, "packages/statemanager/node_modules/lru-cache": { diff --git a/packages/block/src/block.ts b/packages/block/src/block.ts index 507eb99d51..4fe44a6d0a 100644 --- a/packages/block/src/block.ts +++ b/packages/block/src/block.ts @@ -8,6 +8,7 @@ import { Withdrawal, bigIntToHex, bytesToHex, + bytesToUtf8, equalsBytes, fetchFromProvider, getProvider, @@ -30,6 +31,7 @@ import type { HeaderData, JsonBlock, JsonRpcBlock, + VerkleExecutionWitness, } from './types.js' import type { Common } from '@ethereumjs/common' import type { @@ -50,6 +52,13 @@ export class Block { public readonly withdrawals?: Withdrawal[] public readonly common: Common + /** + * EIP-6800: Verkle Proof Data (experimental) + * null implies that the non default executionWitness might exist but not available + * and will not lead to execution of the block via vm with verkle stateless manager + */ + public readonly executionWitness?: VerkleExecutionWitness | null + private cache: { txTrieRoot?: Uint8Array } = {} @@ -92,6 +101,7 @@ export class Block { transactions: txsData, uncleHeaders: uhsData, withdrawals: withdrawalsData, + executionWitness: executionWitnessData, } = blockData const header = BlockHeader.fromHeaderData(headerData, opts) @@ -125,8 +135,11 @@ export class Block { } const withdrawals = withdrawalsData?.map(Withdrawal.fromWithdrawalData) + // The witness data is planned to come in rlp serialized bytes so leave this + // stub till that time + const executionWitness = executionWitnessData - return new Block(header, transactions, uncleHeaders, withdrawals, opts) + return new Block(header, transactions, uncleHeaders, withdrawals, opts, executionWitness) } /** @@ -152,18 +165,18 @@ export class Block { * @param opts */ public static fromValuesArray(values: BlockBytes, opts?: BlockOptions) { - if (values.length > 4) { - throw new Error('invalid block. More values than expected were received') + if (values.length > 5) { + throw new Error(`invalid block. More values=${values.length} than expected were received`) } // First try to load header so that we can use its common (in case of setHardfork being activated) // to correctly make checks on the hardforks - const [headerData, txsData, uhsData, withdrawalBytes] = values + const [headerData, txsData, uhsData, withdrawalBytes, executionWitnessBytes] = values const header = BlockHeader.fromValuesArray(headerData, opts) if ( header.common.isActivatedEIP(4895) && - (values[3] === undefined || !Array.isArray(values[3])) + (withdrawalBytes === undefined || !Array.isArray(withdrawalBytes)) ) { throw new Error( 'Invalid serialized block input: EIP-4895 is active, and no withdrawals were provided as array' @@ -208,7 +221,18 @@ export class Block { })) ?.map(Withdrawal.fromWithdrawalData) - return new Block(header, transactions, uncleHeaders, withdrawals, opts) + // executionWitness are not part of the EL fetched blocks via eth_ bodies method + // they are currently only available via the engine api constructed blocks + let executionWitness + if (header.common.isActivatedEIP(6800) && executionWitnessBytes !== undefined) { + executionWitness = JSON.parse(bytesToUtf8(RLP.decode(executionWitnessBytes) as Uint8Array)) + } else { + // don't assign default witness if eip 6800 is implemented as it leads to incorrect + // assumptions while executing the block. if not present in input implies its unavailable + executionWitness = null + } + + return new Block(header, transactions, uncleHeaders, withdrawals, opts, executionWitness) } /** @@ -300,6 +324,7 @@ export class Block { feeRecipient: coinbase, transactions, withdrawals: withdrawalsData, + executionWitness, } = payload const txs = [] @@ -331,7 +356,16 @@ export class Block { } // we are not setting setHardfork as common is already set to the correct hf - const block = Block.fromBlockData({ header, transactions: txs, withdrawals }, options) + const block = Block.fromBlockData( + { header, transactions: txs, withdrawals, executionWitness }, + options + ) + if ( + block.common.isActivatedEIP(6800) && + (executionWitness === undefined || executionWitness === null) + ) { + throw Error('Missing executionWitness for EIP-6800 activated executionPayload') + } // Verify blockHash matches payload if (!equalsBytes(block.hash(), hexToBytes(payload.blockHash))) { const validationError = `Invalid blockHash, expected: ${ @@ -366,13 +400,34 @@ export class Block { transactions: TypedTransaction[] = [], uncleHeaders: BlockHeader[] = [], withdrawals?: Withdrawal[], - opts: BlockOptions = {} + opts: BlockOptions = {}, + executionWitness?: VerkleExecutionWitness | null ) { this.header = header ?? BlockHeader.fromHeaderData({}, opts) this.common = this.header.common this.transactions = transactions this.withdrawals = withdrawals ?? (this.common.isActivatedEIP(4895) ? [] : undefined) + this.executionWitness = executionWitness + // null indicates an intentional absence of value or unavailability + // undefined indicates that the executionWitness should be initialized with the default state + if (this.common.isActivatedEIP(6800) && this.executionWitness === undefined) { + this.executionWitness = { + stateDiff: [], + verkleProof: { + commitmentsByPath: [], + d: '0x', + depthExtensionPresent: '0x', + ipaProof: { + cl: [], + cr: [], + finalEvaluation: '0x', + }, + otherStems: [], + }, + } + } + this.uncleHeaders = uncleHeaders if (uncleHeaders.length > 0) { this.validateUncles() @@ -394,6 +449,14 @@ export class Block { throw new Error('Cannot have a withdrawals field if EIP 4895 is not active') } + if ( + !this.common.isActivatedEIP(6800) && + executionWitness !== undefined && + executionWitness !== null + ) { + throw new Error(`Cannot have executionWitness field if EIP 6800 is not active `) + } + const freeze = opts?.freeze ?? true if (freeze) { Object.freeze(this) @@ -401,7 +464,7 @@ export class Block { } /** - * Returns a Array of the raw Bytes Arays of this block, in order. + * Returns a Array of the raw Bytes Arrays of this block, in order. */ raw(): BlockBytes { const bytesArray = [ @@ -415,6 +478,10 @@ export class Block { if (withdrawalsRaw) { bytesArray.push(withdrawalsRaw) } + if (this.executionWitness !== undefined && this.executionWitness !== null) { + const executionWitnessBytes = RLP.encode(JSON.stringify(this.executionWitness)) + bytesArray.push(executionWitnessBytes as any) + } return bytesArray } @@ -559,6 +626,17 @@ export class Block { const msg = this._errorMsg('invalid withdrawals trie') throw new Error(msg) } + + // Validation for Verkle blocks + // Unnecessary in this implementation since we're providing defaults if those fields are undefined + if (this.common.isActivatedEIP(6800)) { + if (this.executionWitness === undefined) { + throw new Error(`Invalid block: missing executionWitness`) + } + if (this.executionWitness === null) { + throw new Error(`Invalid block: ethereumjs stateless client needs executionWitness`) + } + } } /** diff --git a/packages/block/src/from-beacon-payload.ts b/packages/block/src/from-beacon-payload.ts index 59baac22e5..79aafd1bf2 100644 --- a/packages/block/src/from-beacon-payload.ts +++ b/packages/block/src/from-beacon-payload.ts @@ -1,6 +1,6 @@ import { bigIntToHex } from '@ethereumjs/util' -import type { ExecutionPayload } from './types.js' +import type { ExecutionPayload, VerkleExecutionWitness } from './types.js' type BeaconWithdrawal = { index: string @@ -30,6 +30,8 @@ export type BeaconPayloadJson = { blob_gas_used?: string excess_blob_gas?: string parent_beacon_block_root?: string + // the casing of VerkleExecutionWitness remains same camel case for now + execution_witness?: VerkleExecutionWitness } /** @@ -72,6 +74,11 @@ export function executionPayloadFromBeaconPayload(payload: BeaconPayloadJson): E if (payload.parent_beacon_block_root !== undefined && payload.parent_beacon_block_root !== null) { executionPayload.parentBeaconBlockRoot = payload.parent_beacon_block_root } + if (payload.execution_witness !== undefined && payload.execution_witness !== null) { + // the casing structure in payload is already camel case, might be updated in + // kaustinen relaunch + executionPayload.executionWitness = payload.execution_witness + } return executionPayload } diff --git a/packages/block/src/header.ts b/packages/block/src/header.ts index 3a82236c04..1b2cece6dc 100644 --- a/packages/block/src/header.ts +++ b/packages/block/src/header.ts @@ -28,7 +28,7 @@ import { keccak256 } from 'ethereum-cryptography/keccak.js' import { CLIQUE_EXTRA_SEAL, CLIQUE_EXTRA_VANITY } from './clique.js' import { fakeExponential, valuesArrayToHeaderData } from './helpers.js' -import type { BlockHeaderBytes, BlockOptions, HeaderData, JsonHeader } from './types.js' +import type { BlockHeaderBytes, BlockOptions, HeaderData, JsonHeader } from './types' import type { CliqueConfig } from '@ethereumjs/common' import type { BigIntLike } from '@ethereumjs/util' @@ -647,6 +647,14 @@ export class BlockHeader { if (this.common.isActivatedEIP(4895) === true) { rawItems.push(this.withdrawalsRoot!) } + + // in kaunstinen 2 verkle is scheduled after withdrawals, will eventually be post deneb hopefully + if (this.common.isActivatedEIP(6800) === true) { + // execution witness is not mandatory part of the the block so nothing to push here + // but keep this comment segment for clarity regarding the same and move it according as per the + // HF sequence eventually planned + } + if (this.common.isActivatedEIP(4844) === true) { rawItems.push(bigIntToUnpaddedBytes(this.blobGasUsed!)) rawItems.push(bigIntToUnpaddedBytes(this.excessBlobGas!)) diff --git a/packages/block/src/types.ts b/packages/block/src/types.ts index be47d9e81a..f871b9609d 100644 --- a/packages/block/src/types.ts +++ b/packages/block/src/types.ts @@ -71,6 +71,45 @@ export interface BlockOptions { skipConsensusFormatValidation?: boolean } +export interface VerkleProof { + commitmentsByPath: PrefixedHexString[] + d: PrefixedHexString + depthExtensionPresent: PrefixedHexString + ipaProof: { + cl: PrefixedHexString[] + cr: PrefixedHexString[] + finalEvaluation: PrefixedHexString + } + otherStems: PrefixedHexString[] +} + +export interface VerkleStateDiff { + stem: PrefixedHexString + suffixDiffs: { + currentValue: PrefixedHexString | null + newValue: PrefixedHexString | null + suffix: number + }[] +} + +/** + * Experimental, object format could eventual change. + * An object that provides the state and proof necessary for verkle stateless execution + * */ +export interface VerkleExecutionWitness { + /** + * An array of state diffs. + * Each item corresponding to state accesses or state modifications of the block. + * In the current design, it also contains the resulting state of the block execution (post-state). + */ + stateDiff: VerkleStateDiff[] + /** + * The verkle proof for the block. + * Proves that the provided stateDiff belongs to the canonical verkle tree. + */ + verkleProof: VerkleProof +} + /** * A block header's data. */ @@ -108,13 +147,29 @@ export interface BlockData { transactions?: Array uncleHeaders?: Array withdrawals?: Array + /** + * EIP-6800: Verkle Proof Data (experimental) + */ + executionWitness?: VerkleExecutionWitness | null } export type WithdrawalsBytes = WithdrawalBytes[] +export type ExecutionWitnessBytes = Uint8Array export type BlockBytes = | [BlockHeaderBytes, TransactionsBytes, UncleHeadersBytes] | [BlockHeaderBytes, TransactionsBytes, UncleHeadersBytes, WithdrawalsBytes] + | [ + BlockHeaderBytes, + TransactionsBytes, + UncleHeadersBytes, + WithdrawalsBytes, + ExecutionWitnessBytes + ] + +/** + * BlockHeaderBuffer is a Buffer array, except for the Verkle PreState which is an array of prestate arrays. + */ export type BlockHeaderBytes = Uint8Array[] export type BlockBodyBytes = [TransactionsBytes, UncleHeadersBytes, WithdrawalsBytes?] /** @@ -134,6 +189,7 @@ export interface JsonBlock { transactions?: JsonTx[] uncleHeaders?: JsonHeader[] withdrawals?: JsonRpcWithdrawal[] + executionWitness?: VerkleExecutionWitness | null } /** @@ -192,6 +248,7 @@ export interface JsonRpcBlock { blobGasUsed?: string // If EIP-4844 is enabled for this block, returns the blob gas used for the block excessBlobGas?: string // If EIP-4844 is enabled for this block, returns the excess blob gas for the block parentBeaconBlockRoot?: string // If EIP-4788 is enabled for this block, returns parent beacon block root + executionWitness?: VerkleExecutionWitness | null // If Verkle is enabled for this block } // Note: all these strings are 0x-prefixed @@ -222,4 +279,6 @@ export type ExecutionPayload = { blobGasUsed?: PrefixedHexString // QUANTITY, 64 Bits excessBlobGas?: PrefixedHexString // QUANTITY, 64 Bits parentBeaconBlockRoot?: PrefixedHexString // QUANTITY, 64 Bits + // VerkleExecutionWitness is already a hex serialized object + executionWitness?: VerkleExecutionWitness | null // QUANTITY, 64 Bits, null imples not available } diff --git a/packages/block/test/from-beacon-payload.spec.ts b/packages/block/test/from-beacon-payload.spec.ts index eacbd3e6c0..6d2725f057 100644 --- a/packages/block/test/from-beacon-payload.spec.ts +++ b/packages/block/test/from-beacon-payload.spec.ts @@ -4,8 +4,10 @@ import { assert, describe, it } from 'vitest' import * as shardingJson from '../../client/test/sim/configs/4844-devnet.json' import { Block, BlockHeader } from '../src/index.js' +import * as payloadKaustinen from './testdata/payload-kaustinen.json' import * as payload87335 from './testdata/payload-slot-87335.json' import * as payload87475 from './testdata/payload-slot-87475.json' +import * as testnetVerkleKaustinen from './testdata/testnetVerkleKaustinen.json' describe('[fromExecutionPayloadJson]: 4844 devnet 5', () => { const network = 'sharding' @@ -65,3 +67,24 @@ describe('[fromExecutionPayloadJson]: 4844 devnet 5', () => { } }) }) + +describe('[fromExecutionPayloadJson]: kaustinen', () => { + const network = 'kaustinen' + + // safely change chainId without modifying undelying json + const common = Common.fromGethGenesis(testnetVerkleKaustinen, { + chain: network, + eips: [6800], + }) + it('reconstruct kaustinen block', async () => { + assert.ok(common.isActivatedEIP(6800), 'verkle eip should be activated') + const block = await Block.fromBeaconPayloadJson(payloadKaustinen, { common }) + // the witness object in payload has camel casing for now + // the current block hash doesn't include witness data so deep match is required + assert.deepEqual( + block.executionWitness, + payloadKaustinen.execution_witness, + 'execution witness should match' + ) + }) +}) diff --git a/packages/block/test/mergeBlock.spec.ts b/packages/block/test/mergeBlock.spec.ts index 46f0291be9..330e90624f 100644 --- a/packages/block/test/mergeBlock.spec.ts +++ b/packages/block/test/mergeBlock.spec.ts @@ -40,7 +40,7 @@ describe('[Header]: Casper PoS / The Merge Functionality', () => { const header = BlockHeader.fromHeaderData({}, { common }) validateMergeHeader(header) - const block = new Block(undefined, undefined, undefined, undefined, { common }) + const block = new Block(undefined, undefined, undefined, undefined, { common }, undefined) validateMergeHeader(block.header) }) diff --git a/packages/block/test/testdata/payload-kaustinen.json b/packages/block/test/testdata/payload-kaustinen.json new file mode 100644 index 0000000000..4fe30ca9f3 --- /dev/null +++ b/packages/block/test/testdata/payload-kaustinen.json @@ -0,0 +1,284 @@ +{ + "parent_hash": "0xa9aa24225f0e1eceb1d9b14e37141ea515d589fb7905e182d016ebf5ab97981c", + "fee_recipient": "0xf97e180c050e5ab072211ad2c213eb5aee4df134", + "state_root": "0x1d77ea5846adfadfac501d7f985ea7d2db3aef74ce3f766d9078af2b9c0528ee", + "receipts_root": "0xecb16c09246cc4470db4921cbe3d186bc48fcf3e7cfbf7226cfcff2b4422d382", + "logs_bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prev_randao": "0xc1f2942b8d8c293c49d8cbe721970184ce4c1e8570234e0f912875d24fa3a524", + "block_number": "918038", + "gas_limit": "30000000", + "gas_used": "471040", + "timestamp": "1691138544", + "extra_data": "0x", + "base_fee_per_gas": "8", + "block_hash": "0xa939663a615b9f29cffe76d5709060f43f183110cf73f794bcc64022d8d6bed6", + "transactions": [ + "0x02f8f283010f2c838362f9843b9b1360843b9b1368830186a094b02a2eda1b317fbd16760128836b0ac59b560e9d80b880600063d6d9dbe4557f039581aefb0dfb1042304e21548bff5d449b5d2e28141b454c1aab05bc57ae55608a527f9d4a12e96b388bb5cb8c5c52acc840a3d28d2caaf675ba5edf79020e7dcfca2e60aa52601960ca53608e60cb5360af60cc5360df60cd53609960ce53606e60cf5360b860d053606860d15360b360d253608760c001a073452abe6866ab6bee42f380a0c510b7619bb36a6b533e36fd57bca0397568d2a056db772085c65056976899bcade617ba562d771eb20b096b82bb6a7b79afe090", + "0x02f8de83010f2c838362fa843b9b1360843b9b1368830186a08080b88060006008552b7fbd4007152df829d6786aa444f4fa640071d3196a6745be98dd728d8995b088a360b6527f57d337dbbedca47e6fb6e4ac607cbd1a29ee3e6d3d4eeef8f697addedaa920f760d65260f860f65360ee60f753604f60f85360e360f953601e60fa53600160fb53603860fc53600360fd53603760fe5360e060ff53c001a0755ddee71ececa43b9bb6d39eb7d814e0822e668b5db94b03bcd7f6d82c01d75a011237be1f238cbf6534b5fef23e6b09aa30385f720a861ebf4bebe0223a5df90", + "0x01f8ed83010f2c838362fb843b9b1368830186a094b02a2eda1b317fbd16760128836b0ac59b560e9d80b880600060735560006042557f77461c032b86fc5f0d7312e7afdb16af1268e99db82ec481fa401a22c08f6f7760de527fe0ef974861eb2e42dbf43e15ec9e9c0553cf1974b946d33cb7690656ce0dd40860fe527f404edb8f7383dbfedab9b466e3ed93df9220a9f521fa2436bdc0d8d9ef1aa26b61011e527fc4073d38042eecfdc080a03dde8e30dc073b3d7f3ee8a9f3aabc6d0a6706967d8d1df4c836b22149005ee7a05b6e07377fcbd96f0207ff9d2bc5c5619efc033374a2cd5796274d9cd327de1e", + "0x01f8ed83010f2c838362fc843b9b1368830186a094a3931a3c9a3677f79d5f1dc186e5fa2ef12f57af80b880fe7f823c0b8bd1857ec29073a0823561f76389ba6b75ed91a760bafe1551473a07e16093527f96cfcba53c4e91cbd1f1141de5e3070c6e623e088ded912a112840bae35d55c160b3527f945efe8ca10edb763ddd5861751330b6f948d8bb96b6db0b0562cb26ddc6b3d260d3527f4bfdbea75372c60b86fc4024e7b07845fdb8c001a0334909b094640167287357423d188960b0e24051a21e301381602d9013a536ffa01bf1177e2d3c785a04d8130801ffc0d02a7b830dfca48c267bc20058957716c3", + "0xf8d6838362fd843b9b1368830186a08080b8807fbdb9eaab9bc0b7010b1a6e62f676331d920e713163bf919dfbdd010b38e841f9604e527fba24da5f669638e081e6e77ba073a6b2fa7761f5beeaad37d4f8f2d9fc1a4626606e527fd4f0fde0f302c32541f2a3614630cc10481107cf156a5258939d03e8361c1f32608e527f498144a87924f14bd358dd83d1dc42a5e218d683021e7b9f8b0c59ad2dce428b2b5652fae0405c8db137790eb686a5ecf829f17f9a8d09a0757c969093f7fbb72195d812e07596da72f6f73bd01276a6c46fdf4ec7c9d0ff", + "0x02f85d83010f2c838362fe843b9b1360843b9b1368830186a0808080c001a0cc61edd6ee856894324247da6fc8acf1b2c3b7043937edaf6166fe8dc7433ddca04b9d588266eb4d6a0a913228ecfe6a7bd199c98f6ef4d343654925e5b2715755", + "0x02f8de83010f2c838362ff843b9b1360843b9b1368830186a08080b880286c3d6000593e5960002080556000600a550e3d600060a155c87f0c944ac3b27a861a7b93357d4d055dfafafb1dac0de07352a34554a80c60ef4f609b527f9ca934f2df7633ece42d9cb60cecb700192415336deb081075a5929400ee540a60bb52606d60db53608f60dc5360d960dd53605f60de5360c760df53602460e053c001a0f3bb03fa14b857609c6113d1b688161de2ff31854f8baaf6a294e13f5ab7ba1da00b8b614fe9cc1f9de61992fdb3b88d3290127ff643de56be8a646c663092e04c", + "0x02f8f283010f2c83836300843b9b1360843b9b1368830186a094000000000000000000000000000000000000000080b8807f52c8c26cccf194c960c3260b1aef360e00d83aea5ad65e3abd6d8d7c6402b68060125260786032536002603353608c603453604a603553609360365360576037536037603853600c6039536049603a53606f603b53609e603c536078603d5360f3603e5360e4603f5360066040536044604153605c6042536025604353608fc080a05e8b04f7ab0cdb98fea2648c3a225019bab81dd3860ebb30b8135e5762d90e37a00b9bca6a74c855cb657aa94945bb343d6dbc0e2d91c96de567d4bec418af3234" + ], + "execution_witness": { + "stateDiff": [ + { + "stem": "0x3491066bb628fd5c1b42e985ae4f078f5c6b642855d5ea13404772dc6c0a0e", + "suffixDiffs": [ + { + "suffix": 0, + "currentValue": null + }, + { + "suffix": 1, + "currentValue": null + }, + { + "suffix": 2, + "currentValue": null + }, + { + "suffix": 3, + "currentValue": null + }, + { + "suffix": 4, + "currentValue": null + }, + { + "suffix": 128, + "currentValue": null + }, + { + "suffix": 129, + "currentValue": null + }, + { + "suffix": 130, + "currentValue": null + }, + { + "suffix": 131, + "currentValue": null + }, + { + "suffix": 132, + "currentValue": null + } + ] + }, + { + "stem": "0x3ab9560e345759eba8da17637b73ab58559e95f94da661ae6f1455b2118f12", + "suffixDiffs": [ + { + "suffix": 0, + "currentValue": null + }, + { + "suffix": 2, + "currentValue": null + }, + { + "suffix": 3, + "currentValue": null + }, + { + "suffix": 72, + "currentValue": null + } + ] + }, + { + "stem": "0xae1b106992d792cbeb5d96559894c2a8dda72c9414cfb3532325f4633047ae", + "suffixDiffs": [ + { + "suffix": 0, + "currentValue": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "suffix": 1, + "currentValue": "0x6204c313026a194b101500000000000000000000000000000000000000000000" + }, + { + "suffix": 2, + "currentValue": "0xf962830000000000000000000000000000000000000000000000000000000000" + }, + { + "suffix": 3, + "currentValue": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + }, + { + "suffix": 4, + "currentValue": null + } + ] + }, + { + "stem": "0xbf101a6e1c8e83c11bd203a582c7981b91097ec55cbd344ce09005c1f26d19", + "suffixDiffs": [ + { + "suffix": 0, + "currentValue": null + }, + { + "suffix": 1, + "currentValue": null + }, + { + "suffix": 2, + "currentValue": null + }, + { + "suffix": 3, + "currentValue": null + }, + { + "suffix": 4, + "currentValue": null + } + ] + }, + { + "stem": "0xbfc11c3b9f2d3f417a5d5d88e56b8910b6ee18c71906c823e5537669908096", + "suffixDiffs": [ + { + "suffix": 0, + "currentValue": null + }, + { + "suffix": 1, + "currentValue": null + }, + { + "suffix": 2, + "currentValue": null + }, + { + "suffix": 3, + "currentValue": null + }, + { + "suffix": 4, + "currentValue": null + } + ] + }, + { + "stem": "0xce920eb1d293b22fc4282b4c91ba676331ad8e37cefc6de8f35906cd28a3c1", + "suffixDiffs": [ + { + "suffix": 0, + "currentValue": null + }, + { + "suffix": 2, + "currentValue": null + }, + { + "suffix": 3, + "currentValue": null + } + ] + }, + { + "stem": "0xe85ebe6a0413fd209120932484714b50e41a71a49903dd9dd15eeff12a64d7", + "suffixDiffs": [ + { + "suffix": 0, + "currentValue": null + }, + { + "suffix": 1, + "currentValue": null + }, + { + "suffix": 2, + "currentValue": null + }, + { + "suffix": 3, + "currentValue": null + }, + { + "suffix": 4, + "currentValue": null + } + ] + }, + { + "stem": "0xee9707ef2846473a6fe4e10781a3b8b225ea950a7c89fb88f01c3544a41dfb", + "suffixDiffs": [ + { + "suffix": 0, + "currentValue": null + }, + { + "suffix": 1, + "currentValue": null + }, + { + "suffix": 2, + "currentValue": null + }, + { + "suffix": 3, + "currentValue": null + }, + { + "suffix": 4, + "currentValue": null + } + ] + } + ], + "verkleProof": { + "otherStems": [], + "depthExtensionPresent": "0x18181a1818181818", + "commitmentsByPath": [ + "0x3a36d7acfe3b4c140138f44044debc50d39c39fd096b627c518301b738999812", + "0x70eff38d6390a949f8ded2241c0ad5f1a6c49d2dbbc47680c1fe52f50b066e75", + "0x2c72c8f7689f8056a5f6970199a391e5cd28976fa429141ef4fd7c8e8612ebc8", + "0x638ed3f8d834a0e37af0a56b031e401be824d128fff6e3893a6d268140e69c70", + "0x4000491640f9aa3ccb0059e7d7c8dabe052a26f0d875a9d33e783000dab0d6fb", + "0x4f5d2a112a38bae60478bf8653d0ca82f03b7f93b5b92ffbcbcbfd9058c62478", + "0x52c3dfa246094f684342210437b63edbaae49b5759cf0e88aeda5b4d3f692369", + "0x219d77dd11a5f467a40f16a95eb3152e5476f0929035130bb0ec8df7047b9611", + "0x6380fd959fa633f3a8568cde2701d73c165c843401f1acb947450b1555eec7ae", + "0x3b46d5d08dd54bdeb7ebb2ee67db932c6c039f3fac9a244c52dfbb2858447853", + "0x0de57f3893bf8aebfa08c82c695fb199e34a35f1f48a493641c9bd215960b66c", + "0x3d34c9ce6a3dfd220a77e90d62f6d02437dffdffb7de0b17a4e8efa6544e46f8", + "0x20acf9fb1af8c8a1bbd7660137997fa40943e98ac5bd94e4b05cd4924612b4b4", + "0x0b103fbe3aa0d2d1112eb4ffe2e59c932f5bff69b2a5ed7292a0a521a461360e", + "0x22ac1b2c021bb5ee4de461009a5bd81a2599cb026ba07a7c13e2b741eb14012d", + "0x153b46b23b2574a89c91f9eac62f4571fbb5d65fb7ab5c2bd3a60f4c8b476b7d", + "0x11b44a8fbcc27cae910ef3891e7bd4e1c512743f9524b3daa12328c3bccf01e9" + ], + "d": "0x595bb8c5ec818d3bc5c817c99874213921f86bf8e4af3ef640ce41133838f21c", + "ipaProof": { + "cl": [ + "0x70b0e212aeab6a5017d546dc45dcb809a67afcb7eb7851e996d7dc4fa2af2b51", + "0x6c77c9cb617d6bd6dbbd33990b0d9f59321d6a3c506ec68e13b09f92adaf09b7", + "0x231a20b178b89640a8880bf7b0c7252d94a1290e6826f2b8e235c1ab9483a579", + "0x3f53e6c4e566fce4b4d19d5e58e3927e86faac42c251ea3547801f6e98085635", + "0x3f1f2976b8746df11ced0a6a133988a08335dda93e12ff25c773d28272e0fa50", + "0x14058989392e922c1d62dd71500ca577b073cee29f1b34b799214e9c06cf1130", + "0x0d4d9a91201c54e94d82f14d8dc99052ec6030d3dc928829f5868cedb4523615", + "0x2c203263f38552248e5991e7f3767e7c0f1d3b9b8b01f0118f0f4569cb0d31bf" + ], + "cr": [ + "0x5aade3c51031cb81b2fff65d4ef863e96a34deadc1a529c8bc903b03f0bf907a", + "0x4ed5890a9883d99eabde9e5a0d44f8434b8c4500c336cef047886aaa1f623daa", + "0x11aac55cf7185d8ac5cd302126e5ea5dec0e4f35e1bff2ce40bd9ad62f4cc7e5", + "0x102c71e8da4b95f9f1e96df42ad327685a515b2d522ed27087fad523ee037c55", + "0x0a8f28762fa56eee9eeb206906d402848759ebeee3ea6dcc742457cc5fd834f3", + "0x17874962f96112f136068f96b69dafa2f8a4e5c50e6b631d5754fbc02f6b4410", + "0x2e246ef6fe9b080de02ca4ef11c98fa1c6faf147d7bbdadb675b1ca637489848", + "0x2b6677d0e34b4e6255a3574006f5d84f1a69576181127fcf17fdda472172eb45" + ], + "finalEvaluation": "0x188bbcef27b263bcc823916f1466070488bf609ad2e9f7d8c0e9b28f9bfa14a2" + } + } + } +} diff --git a/packages/block/test/testdata/testnetVerkleKaustinen.json b/packages/block/test/testdata/testnetVerkleKaustinen.json new file mode 100644 index 0000000000..7000c1bb60 --- /dev/null +++ b/packages/block/test/testdata/testnetVerkleKaustinen.json @@ -0,0 +1,76 @@ +{ + "config": { + "chainId": 69420, + "homesteadBlock": 0, + "daoForkBlock": 0, + "daoForkSupport": false, + "eip150Block": 0, + "eip150Hash": "0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0", + "eip155Block": 0, + "eip158Block": 0, + "byzantiumBlock": 0, + "constantinopleBlock": 0, + "petersburgBlock": 0, + "istanbulBlock": 0, + "muirGlacierBlock": 0, + "berlinBlock": 0, + "londonBlock": 0, + "cancunBlock": 0, + "mergeNetsplitBlock": 0, + "terminalTotalDifficulty": 0, + "ethash": {} + }, + "nonce": "0x56", + "timestamp": "1679652600", + "extraData": "0x", + "gasLimit": "0x2fefd8", + "difficulty": "0x1", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase": "0x0000000000000000000000000000000000000000", + "alloc": { + "0xf97e180c050e5Ab072211Ad2C213Eb5AEE4DF134": { + "balance": "10000000000000000000000000" + }, + "0x4242424242424242424242424242424242424242": { + "balance": "0", + "code": "0x60806040526004361061003f5760003560e01c806301ffc9a71461004457806322895118146100a4578063621fd130146101ba578063c5f2892f14610244575b600080fd5b34801561005057600080fd5b506100906004803603602081101561006757600080fd5b50357fffffffff000000000000000000000000000000000000000000000000000000001661026b565b604080519115158252519081900360200190f35b6101b8600480360360808110156100ba57600080fd5b8101906020810181356401000000008111156100d557600080fd5b8201836020820111156100e757600080fd5b8035906020019184600183028401116401000000008311171561010957600080fd5b91939092909160208101903564010000000081111561012757600080fd5b82018360208201111561013957600080fd5b8035906020019184600183028401116401000000008311171561015b57600080fd5b91939092909160208101903564010000000081111561017957600080fd5b82018360208201111561018b57600080fd5b803590602001918460018302840111640100000000831117156101ad57600080fd5b919350915035610304565b005b3480156101c657600080fd5b506101cf6110b5565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102095781810151838201526020016101f1565b50505050905090810190601f1680156102365780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561025057600080fd5b506102596110c7565b60408051918252519081900360200190f35b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a70000000000000000000000000000000000000000000000000000000014806102fe57507fffffffff0000000000000000000000000000000000000000000000000000000082167f8564090700000000000000000000000000000000000000000000000000000000145b92915050565b6030861461035d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806118056026913960400191505060405180910390fd5b602084146103b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603681526020018061179c6036913960400191505060405180910390fd5b6060821461040f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260298152602001806118786029913960400191505060405180910390fd5b670de0b6b3a7640000341015610470576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806118526026913960400191505060405180910390fd5b633b9aca003406156104cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260338152602001806117d26033913960400191505060405180910390fd5b633b9aca00340467ffffffffffffffff811115610535576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061182b6027913960400191505060405180910390fd5b6060610540826114ba565b90507f649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c589898989858a8a6105756020546114ba565b6040805160a0808252810189905290819060208201908201606083016080840160c085018e8e80828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690910187810386528c815260200190508c8c808284376000838201819052601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690920188810386528c5181528c51602091820193918e019250908190849084905b83811015610648578181015183820152602001610630565b50505050905090810190601f1680156106755780820380516001836020036101000a031916815260200191505b5086810383528881526020018989808284376000838201819052601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018881038452895181528951602091820193918b019250908190849084905b838110156106ef5781810151838201526020016106d7565b50505050905090810190601f16801561071c5780820380516001836020036101000a031916815260200191505b509d505050505050505050505050505060405180910390a1600060028a8a600060801b604051602001808484808284377fffffffffffffffffffffffffffffffff0000000000000000000000000000000090941691909301908152604080517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0818403018152601090920190819052815191955093508392506020850191508083835b602083106107fc57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016107bf565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610859573d6000803e3d6000fd5b5050506040513d602081101561086e57600080fd5b5051905060006002806108846040848a8c6116fe565b6040516020018083838082843780830192505050925050506040516020818303038152906040526040518082805190602001908083835b602083106108f857805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016108bb565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610955573d6000803e3d6000fd5b5050506040513d602081101561096a57600080fd5b5051600261097b896040818d6116fe565b60405160009060200180848480828437919091019283525050604080518083038152602092830191829052805190945090925082918401908083835b602083106109f457805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016109b7565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610a51573d6000803e3d6000fd5b5050506040513d6020811015610a6657600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b60208310610ada57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610a9d565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610b37573d6000803e3d6000fd5b5050506040513d6020811015610b4c57600080fd5b50516040805160208101858152929350600092600292839287928f928f92018383808284378083019250505093505050506040516020818303038152906040526040518082805190602001908083835b60208310610bd957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610b9c565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610c36573d6000803e3d6000fd5b5050506040513d6020811015610c4b57600080fd5b50516040518651600291889160009188916020918201918291908601908083835b60208310610ca957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610c6c565b6001836020036101000a0380198251168184511680821785525050505050509050018367ffffffffffffffff191667ffffffffffffffff1916815260180182815260200193505050506040516020818303038152906040526040518082805190602001908083835b60208310610d4e57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610d11565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610dab573d6000803e3d6000fd5b5050506040513d6020811015610dc057600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b60208310610e3457805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610df7565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610e91573d6000803e3d6000fd5b5050506040513d6020811015610ea657600080fd5b50519050858114610f02576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260548152602001806117486054913960600191505060405180910390fd5b60205463ffffffff11610f60576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806117276021913960400191505060405180910390fd5b602080546001019081905560005b60208110156110a9578160011660011415610fa0578260008260208110610f9157fe5b0155506110ac95505050505050565b600260008260208110610faf57fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061102557805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610fe8565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015611082573d6000803e3d6000fd5b5050506040513d602081101561109757600080fd5b50519250600282049150600101610f6e565b50fe5b50505050505050565b60606110c26020546114ba565b905090565b6020546000908190815b60208110156112f05781600116600114156111e6576002600082602081106110f557fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061116b57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161112e565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa1580156111c8573d6000803e3d6000fd5b5050506040513d60208110156111dd57600080fd5b505192506112e2565b600283602183602081106111f657fe5b015460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061126b57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161122e565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa1580156112c8573d6000803e3d6000fd5b5050506040513d60208110156112dd57600080fd5b505192505b6002820491506001016110d1565b506002826112ff6020546114ba565b600060401b6040516020018084815260200183805190602001908083835b6020831061135a57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161131d565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790527fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000095909516920191825250604080518083037ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8018152601890920190819052815191955093508392850191508083835b6020831061143f57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101611402565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa15801561149c573d6000803e3d6000fd5b5050506040513d60208110156114b157600080fd5b50519250505090565b60408051600880825281830190925260609160208201818036833701905050905060c082901b8060071a60f81b826000815181106114f457fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060061a60f81b8260018151811061153757fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060051a60f81b8260028151811061157a57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060041a60f81b826003815181106115bd57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060031a60f81b8260048151811061160057fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060021a60f81b8260058151811061164357fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060011a60f81b8260068151811061168657fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060001a60f81b826007815181106116c957fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535050919050565b6000808585111561170d578182fd5b83861115611719578182fd5b505082019391909203915056fe4465706f736974436f6e74726163743a206d65726b6c6520747265652066756c6c4465706f736974436f6e74726163743a207265636f6e7374727563746564204465706f7369744461746120646f6573206e6f74206d6174636820737570706c696564206465706f7369745f646174615f726f6f744465706f736974436f6e74726163743a20696e76616c6964207769746864726177616c5f63726564656e7469616c73206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c7565206e6f74206d756c7469706c65206f6620677765694465706f736974436f6e74726163743a20696e76616c6964207075626b6579206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f20686967684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f206c6f774465706f736974436f6e74726163743a20696e76616c6964207369676e6174757265206c656e677468a26469706673582212201dd26f37a621703009abf16e77e69c93dc50c79db7f6cc37543e3e0e3decdc9764736f6c634300060b0033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000022": "0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b", + "0x0000000000000000000000000000000000000000000000000000000000000023": "0xdb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71", + "0x0000000000000000000000000000000000000000000000000000000000000024": "0xc78009fdf07fc56a11f122370658a353aaa542ed63e44c4bc15ff4cd105ab33c", + "0x0000000000000000000000000000000000000000000000000000000000000025": "0x536d98837f2dd165a55d5eeae91485954472d56f246df256bf3cae19352a123c", + "0x0000000000000000000000000000000000000000000000000000000000000026": "0x9efde052aa15429fae05bad4d0b1d7c64da64d03d7a1854a588c2cb8430c0d30", + "0x0000000000000000000000000000000000000000000000000000000000000027": "0xd88ddfeed400a8755596b21942c1497e114c302e6118290f91e6772976041fa1", + "0x0000000000000000000000000000000000000000000000000000000000000028": "0x87eb0ddba57e35f6d286673802a4af5975e22506c7cf4c64bb6be5ee11527f2c", + "0x0000000000000000000000000000000000000000000000000000000000000029": "0x26846476fd5fc54a5d43385167c95144f2643f533cc85bb9d16b782f8d7db193", + "0x000000000000000000000000000000000000000000000000000000000000002a": "0x506d86582d252405b840018792cad2bf1259f1ef5aa5f887e13cb2f0094f51e1", + "0x000000000000000000000000000000000000000000000000000000000000002b": "0xffff0ad7e659772f9534c195c815efc4014ef1e1daed4404c06385d11192e92b", + "0x000000000000000000000000000000000000000000000000000000000000002c": "0x6cf04127db05441cd833107a52be852868890e4317e6a02ab47683aa75964220", + "0x000000000000000000000000000000000000000000000000000000000000002d": "0xb7d05f875f140027ef5118a2247bbb84ce8f2f0f1123623085daf7960c329f5f", + "0x000000000000000000000000000000000000000000000000000000000000002e": "0xdf6af5f5bbdb6be9ef8aa618e4bf8073960867171e29676f8b284dea6a08a85e", + "0x000000000000000000000000000000000000000000000000000000000000002f": "0xb58d900f5e182e3c50ef74969ea16c7726c549757cc23523c369587da7293784", + "0x0000000000000000000000000000000000000000000000000000000000000030": "0xd49a7502ffcfb0340b1d7885688500ca308161a7f96b62df9d083b71fcc8f2bb", + "0x0000000000000000000000000000000000000000000000000000000000000031": "0x8fe6b1689256c0d385f42f5bbe2027a22c1996e110ba97c171d3e5948de92beb", + "0x0000000000000000000000000000000000000000000000000000000000000032": "0x8d0d63c39ebade8509e0ae3c9c3876fb5fa112be18f905ecacfecb92057603ab", + "0x0000000000000000000000000000000000000000000000000000000000000033": "0x95eec8b2e541cad4e91de38385f2e046619f54496c2382cb6cacd5b98c26f5a4", + "0x0000000000000000000000000000000000000000000000000000000000000034": "0xf893e908917775b62bff23294dbbe3a1cd8e6cc1c35b4801887b646a6f81f17f", + "0x0000000000000000000000000000000000000000000000000000000000000035": "0xcddba7b592e3133393c16194fac7431abf2f5485ed711db282183c819e08ebaa", + "0x0000000000000000000000000000000000000000000000000000000000000036": "0x8a8d7fe3af8caa085a7639a832001457dfb9128a8061142ad0335629ff23ff9c", + "0x0000000000000000000000000000000000000000000000000000000000000037": "0xfeb3c337d7a51a6fbf00b9e34c52e1c9195c969bd4e7a0bfd51d5c5bed9c1167", + "0x0000000000000000000000000000000000000000000000000000000000000038": "0xe71f0aa83cc32edfbefa9f4d3e0174ca85182eec9f3a09f6a6c0df6377a510d7", + "0x0000000000000000000000000000000000000000000000000000000000000039": "0x31206fa80a50bb6abe29085058f16212212a60eec8f049fecb92d8c8e0a84bc0", + "0x000000000000000000000000000000000000000000000000000000000000003a": "0x21352bfecbeddde993839f614c3dac0a3ee37543f9b412b16199dc158e23b544", + "0x000000000000000000000000000000000000000000000000000000000000003b": "0x619e312724bb6d7c3153ed9de791d764a366b389af13c58bf8a8d90481a46765", + "0x000000000000000000000000000000000000000000000000000000000000003c": "0x7cdd2986268250628d0c10e385c58c6191e6fbe05191bcc04f133f2cea72c1c4", + "0x000000000000000000000000000000000000000000000000000000000000003d": "0x848930bd7ba8cac54661072113fb278869e07bb8587f91392933374d017bcbe1", + "0x000000000000000000000000000000000000000000000000000000000000003e": "0x8869ff2c22b28cc10510d9853292803328be4fb0e80495e8bb8d271f5b889636", + "0x000000000000000000000000000000000000000000000000000000000000003f": "0xb5fe28e79f1b850f8658246ce9b6a1e7b49fc06db7143e8fe0b4f2b0c5523a5c", + "0x0000000000000000000000000000000000000000000000000000000000000040": "0x985e929f70af28d0bdd1a90a808f977f597c7c778c489e98d3bd8910d31ac0f7" + } + } + }, + "number": "0x0", + "gasUsed": "0x0", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "baseFeePerGas": null +} diff --git a/packages/blockchain/src/blockchain.ts b/packages/blockchain/src/blockchain.ts index fbe0f34ac7..cbe24dfa65 100644 --- a/packages/blockchain/src/blockchain.ts +++ b/packages/blockchain/src/blockchain.ts @@ -7,7 +7,7 @@ import { ConsensusType, Hardfork, } from '@ethereumjs/common' -import { genesisStateRoot as genGenesisStateRoot } from '@ethereumjs/trie' +import { genesisStateRoot as genMerkleGenesisStateRoot } from '@ethereumjs/trie' import { AsyncEventEmitter, BIGINT_0, @@ -45,6 +45,37 @@ import type { BlockData } from '@ethereumjs/block' import type { CliqueConfig } from '@ethereumjs/common' import type { BigIntLike, DB, DBObject, GenesisState } from '@ethereumjs/util' +/** + * Verkle or Merkle genesis root + * @param genesisState + * @param common + * @returns + */ +async function genGenesisStateRoot( + genesisState: GenesisState, + common: Common +): Promise { + const genCommon = common.copy() + genCommon.setHardforkBy({ + blockNumber: 0, + td: BigInt(genCommon.genesis().difficulty), + timestamp: genCommon.genesis().timestamp, + }) + if (genCommon.isActivatedEIP(6800)) { + throw Error(`Verkle trie state not yet supported`) + } else { + return genMerkleGenesisStateRoot(genesisState) + } +} + +/** + * Returns the genesis state root if chain is well known or an empty state's root otherwise + */ +async function getGenesisStateRoot(chainId: Chain, common: Common): Promise { + const chainGenesis = ChainGenesis[chainId] + return chainGenesis !== undefined ? chainGenesis.stateRoot : genGenesisStateRoot({}, common) +} + /** * This class stores and interacts with blocks. */ @@ -234,10 +265,9 @@ export class Blockchain implements BlockchainInterface { let stateRoot = opts.genesisBlock?.header.stateRoot ?? opts.genesisStateRoot if (stateRoot === undefined) { if (this._customGenesisState !== undefined) { - stateRoot = await genGenesisStateRoot(this._customGenesisState) + stateRoot = await genGenesisStateRoot(this._customGenesisState, this.common) } else { - // eslint-disable-next-line @typescript-eslint/no-use-before-define - stateRoot = await getGenesisStateRoot(Number(this.common.chainId()) as Chain) + stateRoot = await getGenesisStateRoot(Number(this.common.chainId()) as Chain, this.common) } } @@ -476,16 +506,14 @@ export class Blockchain implements BlockchainInterface { try { const block = item instanceof BlockHeader - ? new Block(item, undefined, undefined, undefined, { - common: item.common, - }) + ? new Block(item, undefined, undefined, undefined, { common: item.common }, undefined) : item const isGenesis = block.isGenesis() // we cannot overwrite the Genesis block after initializing the Blockchain if (isGenesis) { if (equalsBytes(this.genesisBlock.hash(), block.hash())) { - // Try to re-put the exisiting genesis block, accept this + // Try to re-put the existing genesis block, accept this return } throw new Error( @@ -1419,11 +1447,3 @@ export class Blockchain implements BlockchainInterface { ) } } - -/** - * Returns the genesis state root if chain is well known or an empty state's root otherwise - */ -async function getGenesisStateRoot(chainId: Chain): Promise { - const chainGenesis = ChainGenesis[chainId] - return chainGenesis !== undefined ? chainGenesis.stateRoot : genGenesisStateRoot({}) -} diff --git a/packages/blockchain/src/db/helpers.ts b/packages/blockchain/src/db/helpers.ts index c512e38fb7..fd8cb6e58f 100644 --- a/packages/blockchain/src/db/helpers.ts +++ b/packages/blockchain/src/db/helpers.ts @@ -48,7 +48,8 @@ function DBSetBlockOrHeader(blockBody: Block | BlockHeader): DBOp[] { (blockBody instanceof Block && (blockBody.transactions.length || (blockBody.withdrawals?.length ?? 0) || - blockBody.uncleHeaders.length)) + blockBody.uncleHeaders.length || + (blockBody.executionWitness !== null && blockBody.executionWitness !== undefined))) ) { const bodyValue = RLP.encode(blockBody.raw().slice(1)) dbOps.push( diff --git a/packages/blockchain/src/db/manager.ts b/packages/blockchain/src/db/manager.ts index 6d4abd5065..304f4676b4 100644 --- a/packages/blockchain/src/db/manager.ts +++ b/packages/blockchain/src/db/manager.ts @@ -120,11 +120,11 @@ export class DBManager { // Do extra validations for withdrawal before assuming empty withdrawals if ( !equalsBytes(header.withdrawalsRoot, KECCAK256_RLP) && - (body.length !== 3 || body[2]?.length === 0) + (body.length < 3 || body[2]?.length === 0) ) { throw new Error('withdrawals root shoot be equal to hash of null when no withdrawals') } - if (body.length !== 3) body.push([]) + if (body.length <= 3) body.push([]) } } diff --git a/packages/blockchain/test/util.ts b/packages/blockchain/test/util.ts index 2741955374..cf21523340 100644 --- a/packages/blockchain/test/util.ts +++ b/packages/blockchain/test/util.ts @@ -104,7 +104,7 @@ export const generateConsecutiveBlock = ( } ) - const block = new Block(header, undefined, undefined, undefined, { common }) + const block = new Block(header, undefined, undefined, undefined, { common }, undefined) return block } diff --git a/packages/client/bin/cli.ts b/packages/client/bin/cli.ts index 2051515c7c..3d66916cf1 100755 --- a/packages/client/bin/cli.ts +++ b/packages/client/bin/cli.ts @@ -86,6 +86,11 @@ const args: ClientOpts = yargs(hideBin(process.argv)) coerce: (arg: string) => (arg ? path.resolve(arg) : undefined), implies: 'customChain', }) + .option('verkleGenesisStateRoot', { + describe: 'State root of the verkle genesis genesis (experimental)', + string: true, + coerce: (customGenesisStateRoot: string) => hexToBytes(customGenesisStateRoot), + }) .option('gethGenesis', { describe: 'Import a geth genesis file for running a custom network', coerce: (arg: string) => (arg ? path.resolve(arg) : undefined), @@ -382,6 +387,21 @@ const args: ClientOpts = yargs(hideBin(process.argv)) boolean: true, default: true, }) + .option('statelessVerkle', { + describe: 'Run verkle+ hardforks using stateless verkle stateManager (experimental)', + boolean: true, + default: true, + }) + .option('engineNewpayloadMaxExecute', { + describe: + 'Number of unexecuted blocks (including ancestors) that can be blockingly executed in engine`s new payload (if required and possible) to determine the validity of the block', + number: true, + }) + .option('skipEngineExec', { + describe: + 'Skip executing blocks in new payload calls in engine, alias for --engineNewpayloadMaxExecute=0 and overrides any engineNewpayloadMaxExecute if also provided', + boolean: true, + }) .completion() // strict() ensures that yargs throws when an invalid arg is provided .strict() @@ -485,7 +505,10 @@ async function startBlock(client: EthereumClient) { /** * Starts and returns the {@link EthereumClient} */ -async function startClient(config: Config, customGenesisState?: GenesisState) { +async function startClient( + config: Config, + genesisMeta: { genesisState?: GenesisState; genesisStateRoot?: Uint8Array } = {} +) { config.logger.info(`Data directory: ${config.datadir}`) if (config.lightserv) { config.logger.info(`Serving light peer requests`) @@ -494,11 +517,11 @@ async function startClient(config: Config, customGenesisState?: GenesisState) { const dbs = initDBs(config) let blockchain - if (customGenesisState !== undefined) { + if (genesisMeta.genesisState !== undefined || genesisMeta.genesisStateRoot !== undefined) { const validateConsensus = config.chainCommon.consensusAlgorithm() === ConsensusAlgorithm.Clique blockchain = await Blockchain.create({ db: new LevelDB(dbs.chainDB), - genesisState: customGenesisState, + ...genesisMeta, common: config.chainCommon, hardforkByHeadBlockNumber: true, validateConsensus, @@ -510,7 +533,7 @@ async function startClient(config: Config, customGenesisState?: GenesisState) { const client = await EthereumClient.create({ config, blockchain, - genesisState: customGenesisState, + ...genesisMeta, ...dbs, }) await client.open() @@ -892,6 +915,8 @@ async function run() { useStringValueTrieDB: args.useStringValueTrieDB, txLookupLimit: args.txLookupLimit, pruneEngineCache: args.pruneEngineCache, + statelessVerkle: args.statelessVerkle, + engineNewpayloadMaxExecute: args.skipEngineExec === true ? 0 : args.engineNewpayloadMaxExecute, }) config.events.setMaxListeners(50) config.events.on(Event.SERVER_LISTENING, (details) => { @@ -908,10 +933,14 @@ async function run() { const numAccounts = Object.keys(customGenesisState).length config.logger.info(`Reading custom genesis state accounts=${numAccounts}`) } + const customGenesisStateRoot = args.verkleGenesisStateRoot // Do not wait for client to be fully started so that we can hookup SIGINT handling // else a SIGINT before may kill the process in unclean manner - const clientStartPromise = startClient(config, customGenesisState) + const clientStartPromise = startClient(config, { + genesisState: customGenesisState, + genesisStateRoot: customGenesisStateRoot, + }) .then((client) => { const servers = args.rpc === true || args.rpcEngine === true ? startRPCServers(client, args as RPCArgs) : [] diff --git a/packages/client/package.json b/packages/client/package.json index 47d6f38824..5bf9e0e21e 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -68,6 +68,7 @@ "@ethereumjs/trie": "6.0.1", "@ethereumjs/tx": "5.1.0", "@ethereumjs/util": "9.0.1", + "@ethereumjs/verkle": "^0.0.1", "@ethereumjs/vm": "7.1.0", "abstract-level": "^1.0.3", "body-parser": "^1.19.2", diff --git a/packages/client/src/blockchain/chain.ts b/packages/client/src/blockchain/chain.ts index 6c1aae8d66..b7119f70b6 100644 --- a/packages/client/src/blockchain/chain.ts +++ b/packages/client/src/blockchain/chain.ts @@ -30,6 +30,8 @@ export interface ChainOptions { blockchain?: Blockchain genesisState?: GenesisState + + genesisStateRoot?: Uint8Array } /** @@ -117,6 +119,7 @@ export class Chain { public chainDB: DB public blockchain: Blockchain public _customGenesisState?: GenesisState + public _customGenesisStateRoot?: Uint8Array public opened: boolean @@ -177,6 +180,7 @@ export class Chain { this.chainDB = this.blockchain.db this._customGenesisState = options.genesisState + this._customGenesisStateRoot = options.genesisStateRoot this.opened = false } @@ -237,7 +241,10 @@ export class Chain { async open(): Promise { if (this.opened) return false await this.blockchain.db.open() - await (this.blockchain as any)._init({ genesisState: this._customGenesisState }) + await (this.blockchain as any)._init({ + genesisState: this._customGenesisState, + genesisStateRoot: this._customGenesisStateRoot, + }) this.opened = true await this.update(false) diff --git a/packages/client/src/client.ts b/packages/client/src/client.ts index 744deda4df..2af19fc561 100644 --- a/packages/client/src/client.ts +++ b/packages/client/src/client.ts @@ -53,6 +53,12 @@ export interface EthereumClientOptions { /* custom genesisState if any for the chain */ genesisState?: GenesisState + + /* custom genesisStateRoot to be used with post verkle genesis for stateless runs */ + genesisStateRoot?: Uint8Array + + /* if client can be run stateless post verkle, defaults to true for now */ + statelessVerkle?: boolean } /** diff --git a/packages/client/src/config.ts b/packages/client/src/config.ts index 3c68ea60de..b801b44260 100644 --- a/packages/client/src/config.ts +++ b/packages/client/src/config.ts @@ -326,6 +326,8 @@ export interface ConfigOptions { pruneEngineCache?: boolean snapAvailabilityDepth?: bigint snapTransitionSafeDepth?: bigint + + statelessVerkle?: boolean } export class Config { @@ -430,6 +432,8 @@ export class Config { public readonly enableSnapSync: boolean public readonly useStringValueTrieDB: boolean + public readonly statelessVerkle: boolean + public synchronized: boolean public lastsyncronized?: boolean /** lastSyncDate in ms */ @@ -514,6 +518,8 @@ export class Config { this.enableSnapSync = options.enableSnapSync ?? false this.useStringValueTrieDB = options.useStringValueTrieDB ?? false + this.statelessVerkle = options.statelessVerkle ?? true + // Start it off as synchronized if this is configured to mine or as single node this.synchronized = this.isSingleNode ?? this.mine this.lastSyncDate = 0 diff --git a/packages/client/src/execution/vmexecution.ts b/packages/client/src/execution/vmexecution.ts index d3597cdc88..ff7b6ff549 100644 --- a/packages/client/src/execution/vmexecution.ts +++ b/packages/client/src/execution/vmexecution.ts @@ -6,7 +6,11 @@ import { } from '@ethereumjs/blockchain' import { ConsensusType, Hardfork } from '@ethereumjs/common' import { getGenesis } from '@ethereumjs/genesis' -import { CacheType, DefaultStateManager } from '@ethereumjs/statemanager' +import { + CacheType, + DefaultStateManager, + StatelessVerkleStateManager, +} from '@ethereumjs/statemanager' import { Trie } from '@ethereumjs/trie' import { BIGINT_0, BIGINT_1, Lock, ValueEncoding, bytesToHex, equalsBytes } from '@ethereumjs/util' import { VM } from '@ethereumjs/vm' @@ -39,6 +43,8 @@ export class VMExecution extends Execution { private _lock = new Lock() public vm: VM + public merkleVM: VM | undefined + public verkleVM: VM | undefined public hardfork: string = '' /* Whether canonical chain execution has stayed valid or ran into an invalid block */ public chainStatus: ChainStatus | null = null @@ -58,7 +64,24 @@ export class VMExecution extends Execution { private STATS_INTERVAL = 1000 * 90 // 90 seconds private _statsInterval: NodeJS.Timeout | undefined /* global NodeJS */ - private _statsVm: VM | undefined + private _statsVM: VM | undefined + + /** + * Run a function after acquiring a lock. It is implied that we have already + * initialized the module (or we are calling this from the init function, like + * `_setCanonicalGenesisBlock`) + * @param action - function to run after acquiring a lock + * @hidden + */ + private async runWithLock(action: () => Promise): Promise { + try { + await this._lock.acquire() + const value = await action() + return value + } finally { + this._lock.release() + } + } /** * Create new VM execution module @@ -67,45 +90,13 @@ export class VMExecution extends Execution { super(options) if (this.config.vm === undefined) { - const trie = new Trie({ - db: new LevelDB(this.stateDB), - useKeyHashing: true, - cacheSize: this.config.trieCache, - valueEncoding: options.config.useStringValueTrieDB - ? ValueEncoding.String - : ValueEncoding.Bytes, - }) - - this.config.logger.info(`Initializing account cache size=${this.config.accountCache}`) - this.config.logger.info(`Initializing storage cache size=${this.config.storageCache}`) - this.config.logger.info(`Initializing code cache size=${this.config.codeCache}`) - this.config.logger.info(`Initializing trie cache size=${this.config.trieCache}`) - const stateManager = new DefaultStateManager({ - trie, - prefixStorageTrieKeys: this.config.prefixStorageTrieKeys, - accountCacheOpts: { - deactivate: false, - type: CacheType.LRU, - size: this.config.accountCache, - }, - storageCacheOpts: { - deactivate: false, - type: CacheType.LRU, - size: this.config.storageCache, - }, - codeCacheOpts: { - deactivate: false, - type: CacheType.LRU, - size: this.config.codeCache, - }, - }) - - this.vm = new (VM as any)({ - common: this.config.execCommon, - blockchain: this.chain.blockchain, - stateManager, - profilerOpts: this.config.vmProfilerOpts, - }) + if (this.config.chainCommon.gteHardfork(Hardfork.Prague)) { + this.setupVerkleVM() + this.vm = this.verkleVM! + } else { + this.setupMerkleVM() + this.vm = this.merkleVM! + } } else { this.vm = this.config.vm ;(this.vm as any).blockchain = this.chain.blockchain @@ -133,21 +124,93 @@ export class VMExecution extends Execution { } } - /** - * Run a function after acquiring a lock. It is implied that we have already - * initialized the module (or we are calling this from the init function, like - * `_setCanonicalGenesisBlock`) - * @param action - function to run after acquiring a lock - * @hidden - */ - private async runWithLock(action: () => Promise): Promise { - try { - await this._lock.acquire() - const value = await action() - return value - } finally { - this._lock.release() + setupMerkleVM() { + if (this.merkleVM !== undefined) { + return + } + const trie = new Trie({ + db: new LevelDB(this.stateDB), + useKeyHashing: true, + cacheSize: this.config.trieCache, + valueEncoding: this.config.useStringValueTrieDB ? ValueEncoding.String : ValueEncoding.Bytes, + }) + + this.config.logger.info(`Setting up merkleVM`) + this.config.logger.info(`Initializing account cache size=${this.config.accountCache}`) + this.config.logger.info(`Initializing storage cache size=${this.config.storageCache}`) + this.config.logger.info(`Initializing code cache size=${this.config.codeCache}`) + this.config.logger.info(`Initializing trie cache size=${this.config.trieCache}`) + + const stateManager = new DefaultStateManager({ + trie, + prefixStorageTrieKeys: this.config.prefixStorageTrieKeys, + accountCacheOpts: { + deactivate: false, + type: CacheType.LRU, + size: this.config.accountCache, + }, + storageCacheOpts: { + deactivate: false, + type: CacheType.LRU, + size: this.config.storageCache, + }, + codeCacheOpts: { + deactivate: false, + type: CacheType.LRU, + size: this.config.codeCache, + }, + }) + this.merkleVM = new (VM as any)({ + common: this.config.execCommon, + blockchain: this.chain.blockchain, + stateManager, + profilerOpts: this.config.vmProfilerOpts, + }) + } + + setupVerkleVM() { + if (this.verkleVM !== undefined) { + return + } + + this.config.logger.info(`Setting up verkleVM`) + const stateManager = new StatelessVerkleStateManager() + this.verkleVM = new (VM as any)({ + common: this.config.execCommon, + blockchain: this.chain.blockchain, + stateManager, + profilerOpts: this.config.vmProfilerOpts, + }) + } + + async transitionToVerkle(merkleStateRoot: Uint8Array, assignToVM: boolean = true): Promise { + if (this.vm.stateManager instanceof StatelessVerkleStateManager) { + return } + + return this.runWithLock(async () => { + if (this.merkleVM === undefined) { + this.setupMerkleVM() + } + const merkleVM = this.merkleVM! + const merkleStateManager = merkleVM.stateManager as DefaultStateManager + + if (this.verkleVM === undefined) { + this.setupVerkleVM() + } + const verkleVM = this.verkleVM! + const verkleStateManager = verkleVM.stateManager as StatelessVerkleStateManager + + const verkleStateRoot = await verkleStateManager.getTransitionStateRoot( + merkleStateManager, + merkleStateRoot + ) + await verkleStateManager.setStateRoot(verkleStateRoot) + + if (assignToVM) { + this.vm = verkleVM + } + }) } /** @@ -179,21 +242,80 @@ export class VMExecution extends Execution { const td = await this.vm.blockchain.getTotalDifficulty(headBlock.header.hash()) this.config.execCommon.setHardforkBy({ blockNumber: number, td, timestamp }) this.hardfork = this.config.execCommon.hardfork() - this.config.logger.info(`Initializing VM execution hardfork=${this.hardfork}`) - if (number === BIGINT_0) { - const genesisState = - this.chain['_customGenesisState'] ?? getGenesis(Number(this.vm.common.chainId())) - if (!genesisState) { - throw new Error('genesisState not available') + + if (this.config.execCommon.gteHardfork(Hardfork.Prague)) { + if (!this.config.statelessVerkle) { + throw Error(`Currently stateful verkle execution not supported`) + } + this.config.logger.info(`Skipping VM verkle statemanager genesis hardfork=${this.hardfork}`) + this.setupVerkleVM() + this.vm = this.verkleVM! + } else { + this.config.logger.info( + `Initializing VM merkle statemanager genesis hardfork=${this.hardfork}` + ) + this.setupMerkleVM() + this.vm = this.merkleVM! + if (number === BIGINT_0) { + const genesisState = + this.chain['_customGenesisState'] ?? getGenesis(Number(this.vm.common.chainId())) + if (!genesisState) { + throw new Error('genesisState not available') + } + await this.vm.stateManager.generateCanonicalGenesis(genesisState) } - await this.vm.stateManager.generateCanonicalGenesis(genesisState) } + await super.open() // TODO: Should a run be started to execute any left over blocks? // void this.run() }) } + /** + * Reset the execution after the chain has been reset back + */ + async checkAndReset(headBlock: Block): Promise { + if ( + this.chainStatus !== null && + (headBlock.header.number > this.chainStatus.height || + equalsBytes(headBlock.hash(), this.chainStatus?.hash)) + ) { + return + } + + const { number, timestamp, stateRoot } = headBlock.header + this.chainStatus = { + height: number, + status: ExecStatus.VALID, + root: stateRoot, + hash: headBlock.hash(), + } + + // there could to be checks here that the resetted head is a parent of the chainStatus + // but we can skip it for now trusting the chain reset has been correctly performed + const td = + headBlock.header.number === BIGINT_0 + ? headBlock.header.difficulty + : await this.chain.blockchain.getTotalDifficulty(headBlock.header.parentHash) + this.hardfork = this.config.execCommon.setHardforkBy({ + blockNumber: number, + td, + timestamp, + }) + if (this.config.execCommon.gteHardfork(Hardfork.Prague)) { + // verkleVM should already exist but we can still do an allocation just to be safe + this.setupVerkleVM() + this.vm = this.verkleVM! + } else { + // its could be a rest to a pre-merkle when the chain was never initialized + this.setupMerkleVM() + this.vm = this.merkleVM! + } + + await this.vm.stateManager.setStateRoot(stateRoot) + } + /** * Executes the block, runs the necessary verification on it, * and persists the block and the associate state into the database. @@ -216,19 +338,52 @@ export class VMExecution extends Execution { await this.runWithLock(async () => { try { + const vmHeadBlock = await this.chain.blockchain.getIteratorHead() + await this.checkAndReset(vmHeadBlock) + // running should be false here because running is always changed inside the lock and switched // to false before the lock is released this.running = true const { block, root } = opts + let vm = this.vm if (receipts === undefined) { // Check if we need to pass flag to clear statemanager cache or not const prevVMStateRoot = await this.vm.stateManager.getStateRoot() // If root is not provided its mean to be run on the same set state const parentState = root ?? prevVMStateRoot const clearCache = !equalsBytes(prevVMStateRoot, parentState) + const td = await this.chain.getTd(block.header.parentHash, block.header.number - BIGINT_1) + + const hardfork = this.config.execCommon.getHardforkBy({ + blockNumber: block.header.number, + td, + timestamp: block.header.timestamp, + }) + + if ( + !this.config.execCommon.gteHardfork(Hardfork.Prague) && + this.config.execCommon.hardforkGteHardfork(hardfork, Hardfork.Prague) + ) { + // see if this is a transition block + const parentBlock = await this.chain.getBlock(block.header.parentHash) + const parentTd = td - parentBlock.header.difficulty + const parentHf = this.config.execCommon.getHardforkBy({ + blockNumber: parentBlock.header.number, + td: parentTd, + timestamp: parentBlock.header.timestamp, + }) + + if (!this.config.execCommon.hardforkGteHardfork(parentHf, Hardfork.Prague)) { + await this.transitionToVerkle(parentBlock.header.stateRoot, false) + } + if (this.verkleVM === undefined) { + throw Error(`Invalid verkleVM=undefined`) + } + vm = this.verkleVM + } - const result = await this.vm.runBlock({ clearCache, ...opts }) + const result = await vm.runBlock({ clearCache, ...opts }) receipts = result.receipts } if (receipts !== undefined) { @@ -306,6 +461,10 @@ export class VMExecution extends Execution { throw Error(`${blockName} not in canonical chain`) } } + + const oldVmHead = await this.chain.blockchain.getIteratorHead() + await this.checkAndReset(oldVmHead) + await this.chain.blockchain.setIteratorHead('vm', vmHeadBlock.hash()) this.chainStatus = { height: vmHeadBlock.header.number, @@ -314,6 +473,26 @@ export class VMExecution extends Execution { status: ExecStatus.VALID, } + const td = await this.chain.getTd( + vmHeadBlock.header.parentHash, + vmHeadBlock.header.number - BIGINT_1 + ) + const hardfork = this.config.execCommon.setHardforkBy({ + blockNumber: vmHeadBlock.header.number, + td, + timestamp: vmHeadBlock.header.timestamp, + }) + if ( + !this.config.execCommon.gteHardfork(Hardfork.Prague) && + this.config.execCommon.hardforkGteHardfork(hardfork, Hardfork.Prague) + ) { + // verkle transition should have happened by now + if (this.verkleVM === undefined) { + throw Error(`Invalid verkleVM=undefined`) + } + this.vm = this.verkleVM + } + if (safeBlock !== undefined) { await this.chain.blockchain.setIteratorHead('safe', safeBlock.hash()) } @@ -345,6 +524,8 @@ export class VMExecution extends Execution { throw new Error('cannot get iterator head: blockchain has no getIteratorHead function') } let startHeadBlock = await blockchain.getIteratorHead() + await this.checkAndReset(startHeadBlock) + if (typeof blockchain.getCanonicalHeadBlock !== 'function') { throw new Error( 'cannot get iterator head: blockchain has no getCanonicalHeadBlock function' @@ -420,6 +601,7 @@ export class VMExecution extends Execution { timestamp, }) if (hardfork !== this.hardfork) { + const wasPrePrague = !this.config.execCommon.gteHardfork(Hardfork.Prague) const hash = short(block.hash()) this.config.superMsg( `Execution hardfork switch on block number=${number} hash=${hash} old=${this.hardfork} new=${hardfork}` @@ -429,7 +611,25 @@ export class VMExecution extends Execution { td, timestamp, }) + const isPostPrague = this.config.execCommon.gteHardfork(Hardfork.Prague) + if (wasPrePrague && isPostPrague) { + await this.transitionToVerkle(parentState!) + clearCache = false + } + } + if ( + (!this.config.execCommon.gteHardfork(Hardfork.Prague) && + this.vm.stateManager instanceof StatelessVerkleStateManager) || + (this.config.execCommon.gteHardfork(Hardfork.Prague) && + this.vm.stateManager instanceof DefaultStateManager) + ) { + throw Error( + `Invalid vm stateManager type=${typeof this.vm.stateManager} for fork=${ + this.hardfork + }` + ) } + let skipBlockValidation = false if (this.config.execCommon.consensusType() === ConsensusType.ProofOfAuthority) { // Block validation is redundant here and leads to consistency problems @@ -444,7 +644,7 @@ export class VMExecution extends Execution { throw Error('Execution stopped') } - this._statsVm = this.vm + this._statsVM = this.vm const beforeTS = Date.now() const result = await this.vm.runBlock({ block, @@ -472,9 +672,11 @@ export class VMExecution extends Execution { headBlock = block parentState = block.header.stateRoot } catch (error: any) { - // Store error block and throw which will make iterator stop, exit and save - // last successfully executed head as vmHead - errorBlock = block + // only marked the block as invalid if it was an actual execution error + // for e.g. absense of executionWitness doesn't make a block invalid + if (!`${error.message}`.includes('Invalid executionWitness=null')) { + errorBlock = block + } throw error } }, @@ -704,7 +906,7 @@ export class VMExecution extends Execution { }) if (txHashes.length === 0) { - this._statsVm = vm + this._statsVM = vm // we are skipping header validation because the block has been picked from the // blockchain and header should have already been validated while putBlock @@ -752,8 +954,8 @@ export class VMExecution extends Execution { } stats() { - if (this._statsVm !== undefined) { - const sm = this._statsVm.stateManager as any + if (this._statsVM instanceof DefaultStateManager) { + const sm = this._statsVM.stateManager as any const disactivatedStats = { size: 0, reads: 0, hits: 0, writes: 0 } let stats // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions diff --git a/packages/client/src/types.ts b/packages/client/src/types.ts index 48f576aa61..9cb9861211 100644 --- a/packages/client/src/types.ts +++ b/packages/client/src/types.ts @@ -163,4 +163,8 @@ export interface ClientOpts { vmProfileTxs?: boolean loadBlocksFromRlp?: string pruneEngineCache?: boolean + verkleGenesisStateRoot?: Uint8Array + statelessVerkle?: boolean + engineNewpayloadMaxExecute?: number + skipEngineExec?: boolean } diff --git a/packages/client/test/rpc/engine/kaustinen2.spec.ts b/packages/client/test/rpc/engine/kaustinen2.spec.ts new file mode 100644 index 0000000000..c488cf7585 --- /dev/null +++ b/packages/client/test/rpc/engine/kaustinen2.spec.ts @@ -0,0 +1,115 @@ +import { Block, BlockHeader, executionPayloadFromBeaconPayload } from '@ethereumjs/block' +import { Common, Hardfork } from '@ethereumjs/common' +import { bytesToHex } from '@ethereumjs/util' +import * as td from 'testdouble' +import { assert, describe, it } from 'vitest' + +import blocks from '../../testdata/blocks/kaustinen2.json' +import genesisJSON from '../../testdata/geth-genesis/kaustinen2.json' +import { baseRequest, params, setupChain } from '../helpers' + +import type { HttpServer } from 'jayson' + +// this verkle genesis stateroot and blockhash of the local generated kaustinen2 network +const genesisVerkleStateRoot = '0x30d24fe15e1281600a15328add431b906597d83cf33d23050627c51936bb0d1a' +const genesisVerkleBlockHash = '0x65bb31e62063fccdd3addd1da3a27c27d83f2eced51cad22da2a49e400b2f85c' +const merkleGenesisJsonBlock = { + number: '0x0', + hash: '0xdca7128b1c8b8ceff0c97c407f462dd50ee4dce2e28450b6bfecfaa8b293b7ab', + parentHash: '0x0000000000000000000000000000000000000000000000000000000000000000', + mixHash: '0x0000000000000000000000000000000000000000000000000000000000000000', + nonce: '0x0000000000000056', + sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347', + logsBloom: + '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', + transactionsRoot: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421', + stateRoot: '0xb1a96ff063ca4cdc5e605ae282c5d525894633e6e5eeac958f5b26252b62b526', + receiptsRoot: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421', + miner: '0x0000000000000000000000000000000000000000', + difficulty: '0x1', + totalDifficulty: '0x1', + extraData: '0x', + size: '0x57b', + gasLimit: '0x2fefd8', + gasUsed: '0x0', + timestamp: '0x641d76f8', + transactions: [], + uncles: [], + baseFeePerGas: '0x3b9aca00', + withdrawalsRoot: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421', + withdrawals: [], +} + +const originalValidate = (BlockHeader as any).prototype._consensusFormatValidation + +export const batchBlocks = async (server: HttpServer) => { + for (let i = 0; i < blocks.length; i++) { + const executionPayload = executionPayloadFromBeaconPayload(blocks[i] as any) + const req = params('engine_newPayloadV2', [executionPayload]) + const expectRes = (res: any) => { + assert.equal(res.body.result.status, 'VALID') + } + await baseRequest(server, req, 200, expectRes, false, false) + } +} + +describe(`verkle genesis checks`, () => { + const common = Common.fromGethGenesis(genesisJSON, { chain: 'kaustinen2' }) + it('genesis fork', async () => { + assert.equal(common.hardfork(), Hardfork.Prague, 'should be set at prague hardfork for verkle') + }) + const merkleGenesisBlock = Block.fromRPC(merkleGenesisJsonBlock, [], { common }) + assert.equal(merkleGenesisJsonBlock.hash, bytesToHex(merkleGenesisBlock.hash())) + + // get the block with the verkle genesis root instead of merkle root + const verkleGenesisBlock = Block.fromRPC( + { ...merkleGenesisJsonBlock, stateRoot: genesisVerkleStateRoot }, + [], + { common } + ) + assert.equal(genesisVerkleBlockHash, bytesToHex(verkleGenesisBlock.hash())) +}) + +describe(`invalid verkle network setup`, () => { + it('start client without verkle state root', async () => { + // assign a chain id not of kaustinen2 chain so as to not interfere with the stateroot lookup of + // kaustinen in genesis state enum of well known networks + const invalidGenesis = Object.assign({}, genesisJSON, { + config: { ...genesisJSON.config, chainId: 90069420 }, + }) + try { + await setupChain(invalidGenesis, 'post-merge', { + engine: true, + }) + assert.fail('Should have failed to start') + } catch (e: any) { + assert.equal(e.message, 'Verkle trie state not yet supported') + } + }) +}) + +describe(`valid verkle network setup`, async () => { + const { server } = await setupChain(genesisJSON, 'post-merge', { + engine: true, + genesisStateRoot: genesisVerkleStateRoot, + }) + + it('genesis should be correctly setup', async () => { + const req = params('eth_getBlockByNumber', ['0x0', false]) + const expectRes = (res: any) => { + const block0 = res.body.result + assert.equal(block0.hash, genesisVerkleBlockHash) + assert.equal(block0.stateRoot, genesisVerkleStateRoot) + } + await baseRequest(server, req, 200, expectRes, false, false) + }) + + it('should be able to apply new verkle payloads', async () => { + await batchBlocks(server) + }) + + it(`reset TD`, () => { + BlockHeader.prototype['_consensusFormatValidation'] = originalValidate + td.reset() + }) +}) diff --git a/packages/client/test/rpc/helpers.ts b/packages/client/test/rpc/helpers.ts index 5b7f183af8..088d9fae83 100644 --- a/packages/client/test/rpc/helpers.ts +++ b/packages/client/test/rpc/helpers.ts @@ -1,6 +1,6 @@ import { BlockHeader } from '@ethereumjs/block' import { Blockchain } from '@ethereumjs/blockchain' -import { Chain as ChainEnum, Common, parseGethGenesis } from '@ethereumjs/common' +import { Chain as ChainEnum, Common, Hardfork, parseGethGenesis } from '@ethereumjs/common' import { getGenesis } from '@ethereumjs/genesis' import { Address, @@ -53,6 +53,7 @@ type createClientArgs = { chain: any // Could be anything that implements a portion of the Chain interface (varies by test) opened: boolean genesisState: GenesisState + genesisStateRoot: Uint8Array } export function startRPC( methods: any, @@ -240,6 +241,7 @@ export async function baseRequest( export async function setupChain(genesisFile: any, chainName = 'dev', clientOpts: any = {}) { const genesisParams = parseGethGenesis(genesisFile, chainName) const genesisState = parseGethGenesisState(genesisFile) + const genesisStateRoot = clientOpts.genesisStateRoot const common = new Common({ chain: chainName, @@ -248,14 +250,21 @@ export async function setupChain(genesisFile: any, chainName = 'dev', clientOpts common.setHardforkBy({ blockNumber: 0, td: genesisParams.genesis.difficulty, + timestamp: genesisParams.genesis.timestamp, }) + // currently we don't have a way to create verkle genesis root so we will + // use genesisStateRoot for blockchain init as well as to start of the stateless + // client. else the stateroot could have been generated out of box + const genesisMeta = common.gteHardfork(Hardfork.Prague) ? { genesisStateRoot } : { genesisState } const blockchain = await Blockchain.create({ common, validateBlocks: false, validateConsensus: false, - genesisState, + ...genesisMeta, }) + + // for the client we can pass both genesisState and genesisStateRoot and let it s const client = createClient({ ...clientOpts, commonChain: common, @@ -263,6 +272,7 @@ export async function setupChain(genesisFile: any, chainName = 'dev', clientOpts includeVM: true, enableMetaDB: true, genesisState, + genesisStateRoot, }) const manager = createManager(client) const engineMethods = clientOpts.engine === true ? manager.getMethods(true) : {} diff --git a/packages/client/test/testdata/blocks/kaustinen2.json b/packages/client/test/testdata/blocks/kaustinen2.json new file mode 100644 index 0000000000..1e49f409f3 --- /dev/null +++ b/packages/client/test/testdata/blocks/kaustinen2.json @@ -0,0 +1,788 @@ +[ + { + "parent_hash": "0x65bb31e62063fccdd3addd1da3a27c27d83f2eced51cad22da2a49e400b2f85c", + "fee_recipient": "0xcccccccccccccccccccccccccccccccccccccccc", + "state_root": "0x30d24fe15e1281600a15328add431b906597d83cf33d23050627c51936bb0d1a", + "receipts_root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "logs_bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prev_randao": "0x65bb31e62063fccdd3addd1da3a27c27d83f2eced51cad22da2a49e400b2f85c", + "block_number": "1", + "gas_limit": "3144658", + "gas_used": "0", + "timestamp": "1699897334", + "extra_data": "0xd983010c01846765746889676f312e32302e3130856c696e7578", + "base_fee_per_gas": "875000000", + "block_hash": "0x997c1b4f06abc80b2f59ed3b75932ec07f08bc403c3eef91aee9e2be48842c27", + "transactions": [], + "withdrawals": [], + "execution_witness": { + "stateDiff": [ + { + "stem": "0x3cc88d00122c996769be8222a4d8e62caeb8929f307d2b947ac956d49b2362", + "suffixDiffs": [ + { + "suffix": "0", + "currentValue": null, + "newValue": null + }, + { + "suffix": "1", + "currentValue": null, + "newValue": null + }, + { + "suffix": "2", + "currentValue": null, + "newValue": null + }, + { + "suffix": "3", + "currentValue": null, + "newValue": null + }, + { + "suffix": "4", + "currentValue": null, + "newValue": null + } + ] + } + ], + "verkleProof": { + "otherStems": [], + "depthExtensionPresent": "0x08", + "commitmentsByPath": [], + "d": "0x3c156cfeb05e3fcddfb4a1ed08b485cffa5aec47cda7068f8d19abfc9e45c5d9", + "ipaProof": { + "cl": [ + "0x1e8bc037a7e8d8d6be22573d7e5a689effb8a2172a3fece1ff812e8ca2f7a010", + "0x621b9840ba2b87d26f343916bdb3b98de00bbed59d2bd5d0018ed469414a76e5", + "0x2daf62b58e072395d95b7c0c08c4f5fa7a939aed4bd3a650c84d111f3e4096cb", + "0x72c3d220ed0a1f2bb8ac456f1833506897ef70c211a5da87f4b6f0f7b1872a7a", + "0x376c8cc36adaa8c59d5ea2da4553fb14f2e4460856d5ea245a587eaca5323314", + "0x4262d01cd550e149dfc253ee71425344950ba6eb989542aca813995f2f6e0f42", + "0x119dd4b8979746aeb016292cdf63e1050486f20dabb4fb5ce33c79a56806cf23", + "0x4be5ceba9d6233ada63cc21e583dd3c27d8309b983d247c8bda3ce35a6145611" + ], + "cr": [ + "0x207d90229537b988e6ffade58ec996866c76a2d1a277654fb318ee35f0b7f3aa", + "0x2ffcf497ec85a2b7338e53b26ca2c3f7b3b667cb3fe3cd9338ce7aa748c24520", + "0x5d1fb43a25d969b920178988c1abe64e893ce15827ccec836c9869c018bcfa7b", + "0x450db35e5f46b1914c8befbddf376fb6e72e4d5fbe88414c495051ec6f56bb52", + "0x62a318e1241d1aab99dc4f717afaefd3f88ec6446dcc1d3bbf825afc76dbfd50", + "0x7398cd3d17b4436f012144e718048b2c617e3443b5f6551c3dfb5e5e8986da9e", + "0x5e9cae984e7e512673875810f3665b224ac30e61a3c4ef255134699b36503d05", + "0x56f85963be7815f0910983cf01122e29414f327c0641351beda0ae2c2502e739" + ], + "finalEvaluation": "0x137a6618e6cde3243b5cc8963c92751bf82ec08d28e5b9b2a193a42619bcd1ed" + } + } + } + }, + { + "parent_hash": "0x997c1b4f06abc80b2f59ed3b75932ec07f08bc403c3eef91aee9e2be48842c27", + "fee_recipient": "0xcccccccccccccccccccccccccccccccccccccccc", + "state_root": "0x30d24fe15e1281600a15328add431b906597d83cf33d23050627c51936bb0d1a", + "receipts_root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "logs_bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prev_randao": "0xae5c4a884a86a417470042cc784d628d8ede255992144d52649d564ac97dd82c", + "block_number": "2", + "gas_limit": "3147727", + "gas_used": "0", + "timestamp": "1699897340", + "extra_data": "0xd983010c01846765746889676f312e32302e3130856c696e7578", + "base_fee_per_gas": "765625000", + "block_hash": "0x831bf4167e6ba809055c956f6189e5d46cf6b4db9254af6a1a66503bd95d75ca", + "transactions": [], + "withdrawals": [], + "execution_witness": { + "stateDiff": [ + { + "stem": "0x3cc88d00122c996769be8222a4d8e62caeb8929f307d2b947ac956d49b2362", + "suffixDiffs": [ + { + "suffix": "0", + "currentValue": null, + "newValue": null + }, + { + "suffix": "1", + "currentValue": null, + "newValue": null + }, + { + "suffix": "2", + "currentValue": null, + "newValue": null + }, + { + "suffix": "3", + "currentValue": null, + "newValue": null + }, + { + "suffix": "4", + "currentValue": null, + "newValue": null + } + ] + } + ], + "verkleProof": { + "otherStems": [], + "depthExtensionPresent": "0x08", + "commitmentsByPath": [], + "d": "0x3c156cfeb05e3fcddfb4a1ed08b485cffa5aec47cda7068f8d19abfc9e45c5d9", + "ipaProof": { + "cl": [ + "0x1e8bc037a7e8d8d6be22573d7e5a689effb8a2172a3fece1ff812e8ca2f7a010", + "0x621b9840ba2b87d26f343916bdb3b98de00bbed59d2bd5d0018ed469414a76e5", + "0x2daf62b58e072395d95b7c0c08c4f5fa7a939aed4bd3a650c84d111f3e4096cb", + "0x72c3d220ed0a1f2bb8ac456f1833506897ef70c211a5da87f4b6f0f7b1872a7a", + "0x376c8cc36adaa8c59d5ea2da4553fb14f2e4460856d5ea245a587eaca5323314", + "0x4262d01cd550e149dfc253ee71425344950ba6eb989542aca813995f2f6e0f42", + "0x119dd4b8979746aeb016292cdf63e1050486f20dabb4fb5ce33c79a56806cf23", + "0x4be5ceba9d6233ada63cc21e583dd3c27d8309b983d247c8bda3ce35a6145611" + ], + "cr": [ + "0x207d90229537b988e6ffade58ec996866c76a2d1a277654fb318ee35f0b7f3aa", + "0x2ffcf497ec85a2b7338e53b26ca2c3f7b3b667cb3fe3cd9338ce7aa748c24520", + "0x5d1fb43a25d969b920178988c1abe64e893ce15827ccec836c9869c018bcfa7b", + "0x450db35e5f46b1914c8befbddf376fb6e72e4d5fbe88414c495051ec6f56bb52", + "0x62a318e1241d1aab99dc4f717afaefd3f88ec6446dcc1d3bbf825afc76dbfd50", + "0x7398cd3d17b4436f012144e718048b2c617e3443b5f6551c3dfb5e5e8986da9e", + "0x5e9cae984e7e512673875810f3665b224ac30e61a3c4ef255134699b36503d05", + "0x56f85963be7815f0910983cf01122e29414f327c0641351beda0ae2c2502e739" + ], + "finalEvaluation": "0x137a6618e6cde3243b5cc8963c92751bf82ec08d28e5b9b2a193a42619bcd1ed" + } + } + } + }, + { + "parent_hash": "0x831bf4167e6ba809055c956f6189e5d46cf6b4db9254af6a1a66503bd95d75ca", + "fee_recipient": "0xcccccccccccccccccccccccccccccccccccccccc", + "state_root": "0x4250f5f8c4067a671b247ea6f8b820982f9057aa4062a88d1d7165d79892b9a3", + "receipts_root": "0xc3b8f4b1785850ff169304af7194d35792f4a71215b92a134b6670be472bfae5", + "logs_bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prev_randao": "0x011d0e875b91fc39d02b7ad37a2b176959f41b04b629a7cb0a63f130c23f71c3", + "block_number": "3", + "gas_limit": "3150799", + "gas_used": "34300", + "timestamp": "1699897346", + "extra_data": "0xd983010c01846765746889676f312e32302e3130856c696e7578", + "base_fee_per_gas": "669921875", + "block_hash": "0xb197644aa5e5ef320bc203a3ee57c3e507c3d6ffa8477ce083ca267863d55e02", + "transactions": [ + "0x02f87283010f2c808405f5e1008511d970eaa0830f4240943da33b9a0894b908ddbb00d96399e506515a1009830f424080c001a0b42278ecb4ab875bb5b930354f803f154a3cc9704844936f1af609d6dc2bbf29a03b9296672f5722e03968187e9bf60f1ec9eeb93d7436fae3260c1358f8bc2c75" + ], + "withdrawals": [], + "execution_witness": { + "stateDiff": [ + { + "stem": "0x3cc88d00122c996769be8222a4d8e62caeb8929f307d2b947ac956d49b2362", + "suffixDiffs": [ + { + "suffix": "0", + "currentValue": null, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "suffix": "1", + "currentValue": null, + "newValue": "0x007cee9b1e030000000000000000000000000000000000000000000000000000" + }, + { + "suffix": "2", + "currentValue": null, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "suffix": "3", + "currentValue": null, + "newValue": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + }, + { + "suffix": "4", + "currentValue": null, + "newValue": null + } + ] + }, + { + "stem": "0x5e3427be607e90505472f200e64a2ebfcb990b46f8688d0b0f35a9c11025e0", + "suffixDiffs": [ + { + "suffix": "0", + "currentValue": null, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "suffix": "1", + "currentValue": null, + "newValue": "0x40420f0000000000000000000000000000000000000000000000000000000000" + }, + { + "suffix": "2", + "currentValue": null, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "suffix": "3", + "currentValue": null, + "newValue": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + }, + { + "suffix": "4", + "currentValue": null, + "newValue": null + } + ] + }, + { + "stem": "0x97233a822ee74c294ccec8e4e0c65106b374d4423d5d09236d0f6c6647e185", + "suffixDiffs": [ + { + "suffix": "0", + "currentValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": null + }, + { + "suffix": "1", + "currentValue": "0x0000004a48011416954508000000000000000000000000000000000000000000", + "newValue": "0x0c99639f43e91316954508000000000000000000000000000000000000000000" + }, + { + "suffix": "2", + "currentValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0100000000000000000000000000000000000000000000000000000000000000" + }, + { + "suffix": "3", + "currentValue": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "newValue": null + }, + { + "suffix": "4", + "currentValue": null, + "newValue": null + } + ] + } + ], + "verkleProof": { + "otherStems": [], + "depthExtensionPresent": "0x08080a", + "commitmentsByPath": [ + "0x6d377ca1fdd68b453d921cb4bd01a57cd2e06ae8573482c779fdcd7eea9a0a6c", + "0x29f3b12087b4d56fb2b406eadbbb2677427fb8b72b0c9221bb1acfe10b5e9494" + ], + "d": "0x31ac0c6a2ffaebf19e06070c9dd51edf0b4e226be8ce82c89b5ce7cd9007002c", + "ipaProof": { + "cl": [ + "0x250c5b780488a534e7db36e3331edc20e8bf66686e7e4babe3c09c61d502f84b", + "0x0af08c0c70c9ac0a156fcb0307e573c0cada87c4f5d55c4705e85ddd01a78e4d", + "0x5b2a0e06d51e12dc994b36d140a1c7f82913ac8a8ad61adc833944cafca80d75", + "0x54c67b4692bc0d424ea20787842858b13591af5b2de0213070294d15ebbe94f2", + "0x2685e70ccee07cf86c19a08ce06fa6fd739d94117f9c9251bedbe1683bf19c2e", + "0x71ffa0a6760c59c711f57757e97802bd4440d86ea76c58ae821beadfa6e654ec", + "0x331551f3488ff10ced2fd229c36110c83e9c4a9b94532bc08bda4128f392c7c5", + "0x52defe3fb4e63399ddc600afb55c5754f62670355c7378b0a3015e94278c365d" + ], + "cr": [ + "0x2519f1964a29c23f99284d5543f9d3edb61c75a2bed357a0f337d92c558d5458", + "0x51a00d6dcf8457fd8db623e71118a406f781c2a7b6c1deb783b676c89d32b681", + "0x3c9c51736b579624939648a6416e4f14cde382fc5aef7b0c06eb00184b6c944f", + "0x055bd0d33005e2d823b1a06eb5c610a73a89a45393142351ea54df0994e17a75", + "0x4a92c119a1f305455ee9c42cc3130a1eba083c40580e75e93a86174b479e25e9", + "0x6adb4916dcd820c358d77f73481cc8b935bd032ebe08c78272be05218b8c8a0f", + "0x218d77f25c096818426f1dd17818579ed0723c5de905b4403e51f76b546ca38b", + "0x1038998e1602cc4ba49005d77327937a0a5c95f62acae1c4157abdb6880bb242" + ], + "finalEvaluation": "0x1cbe43e36c4c77ae43e3051d7dcf977ca5b35011e1f0195b9de022818301438e" + } + } + } + }, + { + "parent_hash": "0xb197644aa5e5ef320bc203a3ee57c3e507c3d6ffa8477ce083ca267863d55e02", + "fee_recipient": "0xcccccccccccccccccccccccccccccccccccccccc", + "state_root": "0x4250f5f8c4067a671b247ea6f8b820982f9057aa4062a88d1d7165d79892b9a3", + "receipts_root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "logs_bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prev_randao": "0x7477e90a214b800fb9f8000a909ef7a7c831bb439fef70499052c87459e7f552", + "block_number": "4", + "gas_limit": "3153874", + "gas_used": "0", + "timestamp": "1699897352", + "extra_data": "0xd983010c01846765746889676f312e32302e3130856c696e7578", + "base_fee_per_gas": "588004855", + "block_hash": "0xa4f8ae89e318800edb233e97663f122044d5e4ae9f4dfd64f59acb97aba15b3d", + "transactions": [], + "withdrawals": [], + "execution_witness": { + "stateDiff": [ + { + "stem": "0x3cc88d00122c996769be8222a4d8e62caeb8929f307d2b947ac956d49b2362", + "suffixDiffs": [ + { + "suffix": "0", + "currentValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": null + }, + { + "suffix": "1", + "currentValue": "0x007cee9b1e030000000000000000000000000000000000000000000000000000", + "newValue": null + }, + { + "suffix": "2", + "currentValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": null + }, + { + "suffix": "3", + "currentValue": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "newValue": null + }, + { + "suffix": "4", + "currentValue": null, + "newValue": null + } + ] + } + ], + "verkleProof": { + "otherStems": [], + "depthExtensionPresent": "0x0a", + "commitmentsByPath": [ + "0x3602af74c4621b740a52f19778bf2c4f5749833b22edf0e95e3234168c786234", + "0x5213f3b137020e7e95ac1c5ac1ddac551b9c7cc80663a2a625e4382d907685d8" + ], + "d": "0x6efdb8268b2ed07371ab19bdae6f2e966034c2ee380b45ad41a1a92b3ebb435c", + "ipaProof": { + "cl": [ + "0x4a58265ee6e48d145093ef17c90c65c45fffa6f8384d37b4d5d782b670b5ad73", + "0x19cef344cf6406509a612697df1f5879dd2235d353660f19939edd331a4b46b8", + "0x5352f3ff1a77bcea8859b8d1bf906d658f60e94d723d9f4dfb3f822cc6c4f293", + "0x06fe05179105212e2eb4ee546a5969814f90863a208800787f330026677a1351", + "0x10231b0c4720d0208f8e1f7fc70a1994af1af308eb5cefa6e5b8fe2e3f5c36e8", + "0x2ea4da976f38ad1cc275871904f269cd36b62149e0c4271f43516472013e6fe6", + "0x328e67ea51377efca4b5f336e90e68e3524b876d0c44002850b84b94e5a88acb", + "0x30fe2558df07d09d025ae35c7d2f4802f92832503579de2bb718fd19577e2b9b" + ], + "cr": [ + "0x2359207ecf58dd1c10c6fbd3cc6b4a27a9005438951faedf5d631356bebd22af", + "0x2ab9cfc92d8f0f98e7f70383b058545cd075f45689622821e09d7f5e83d0b44a", + "0x10f2e0eb95041e2258fad7a24a17bb62017656f72027d63633c9566d60d1eacc", + "0x25acb28b7990eb2b478151b5714996e12e20b0098577f18ee4bbfe765bcb4c8f", + "0x0170c542013175cd68223688552ad5ecbb70b5a16e60145771ddb1a4b730f214", + "0x178df6d6d14c74cc6fbc7da9d877ffff47b43f374b6e5b8157086b8ee4f03f6e", + "0x46492793a51370908302f4f9e936417ee95d63aa8bfe3b2edfaacb75d92c21ac", + "0x4c24f9b2d541a32cf43593cc1607effdce6814ec1ebd9d1ea69f15c77b9bb6a2" + ], + "finalEvaluation": "0x0bcac30e940d1fbe2948be28f9c14afc070222e03f392ef79725a6bda9d17ad7" + } + } + } + }, + { + "parent_hash": "0xa4f8ae89e318800edb233e97663f122044d5e4ae9f4dfd64f59acb97aba15b3d", + "fee_recipient": "0xcccccccccccccccccccccccccccccccccccccccc", + "state_root": "0x4b20302831ee663994bcb346aa8c49de52f501b52997ba47b49649c43124904f", + "receipts_root": "0xc3b8f4b1785850ff169304af7194d35792f4a71215b92a134b6670be472bfae5", + "logs_bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prev_randao": "0xdb36ad05305cd8212ed3381592f882431f1b851ebbd29ad0feac6f0e52a55cbd", + "block_number": "5", + "gas_limit": "3156952", + "gas_used": "34300", + "timestamp": "1699897358", + "extra_data": "0xd983010c01846765746889676f312e32302e3130856c696e7578", + "base_fee_per_gas": "514504249", + "block_hash": "0x81cf4fcface70ad71b73a5f313400ac10c08fe33935d78bb2275ce6747c5b406", + "transactions": [ + "0x02f87283010f2c018405f5e100850a814f2988830f4240943da33b9a0894b908ddbb00d96399e506515a1009830f424080c001a0a465121d691cfa8cee351bc2716f1c9ca9bf13326093f15e38cbedb78227af92a04a15f8ee7f5856291b015f3a95b1978f6833a4c4731c3a5078721cb0f0641348" + ], + "withdrawals": [], + "execution_witness": { + "stateDiff": [ + { + "stem": "0x3cc88d00122c996769be8222a4d8e62caeb8929f307d2b947ac956d49b2362", + "suffixDiffs": [ + { + "suffix": "0", + "currentValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": null + }, + { + "suffix": "1", + "currentValue": "0x007cee9b1e030000000000000000000000000000000000000000000000000000", + "newValue": "0x00f8dc373d060000000000000000000000000000000000000000000000000000" + }, + { + "suffix": "2", + "currentValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": null + }, + { + "suffix": "3", + "currentValue": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "newValue": null + }, + { + "suffix": "4", + "currentValue": null, + "newValue": null + } + ] + }, + { + "stem": "0x5e3427be607e90505472f200e64a2ebfcb990b46f8688d0b0f35a9c11025e0", + "suffixDiffs": [ + { + "suffix": "0", + "currentValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": null + }, + { + "suffix": "1", + "currentValue": "0x40420f0000000000000000000000000000000000000000000000000000000000", + "newValue": "0x80841e0000000000000000000000000000000000000000000000000000000000" + }, + { + "suffix": "2", + "currentValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": null + }, + { + "suffix": "3", + "currentValue": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "newValue": null + }, + { + "suffix": "4", + "currentValue": null, + "newValue": null + } + ] + }, + { + "stem": "0x97233a822ee74c294ccec8e4e0c65106b374d4423d5d09236d0f6c6647e185", + "suffixDiffs": [ + { + "suffix": "0", + "currentValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": null + }, + { + "suffix": "1", + "currentValue": "0x0c99639f43e91316954508000000000000000000000000000000000000000000", + "newValue": "0xb0ddae2218d61316954508000000000000000000000000000000000000000000" + }, + { + "suffix": "2", + "currentValue": "0x0100000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x0200000000000000000000000000000000000000000000000000000000000000" + }, + { + "suffix": "3", + "currentValue": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "newValue": null + }, + { + "suffix": "4", + "currentValue": null, + "newValue": null + } + ] + } + ], + "verkleProof": { + "otherStems": [], + "depthExtensionPresent": "0x0a0a0a", + "commitmentsByPath": [ + "0x3602af74c4621b740a52f19778bf2c4f5749833b22edf0e95e3234168c786234", + "0x5213f3b137020e7e95ac1c5ac1ddac551b9c7cc80663a2a625e4382d907685d8", + "0x18df835e0891dec6af9ab1014cfa419cd3a0ec8fd1937ff1c478a8cca17fec89", + "0x0afb82b44a0a45f072e2d9f75d74cb6b1f19711c30f95e67a8b67e4b5810a214", + "0x6db0f61ac54f18358f02683a676a45a16d15f0bce0772ca0c92bb4bf5980b1b5", + "0x32c8845bba888721c1fb7ce75d70a7e20b195fa4bc3d8d0c566e9c6aefb81429" + ], + "d": "0x634fae8e0f97dfed86ed58061c08654b8df161cfa133098643a6ece8af5f076e", + "ipaProof": { + "cl": [ + "0x52f3bd558dd2e226e28f029a8afd0cfbd48b5fc74309e76b28fa7d2165933e71", + "0x65bcab2d79371e9ec8cb3b6bed8b0fefe42cc7c92ba02ea8bef5e603cff7d733", + "0x502fef5f1299c3d81f9b558088424448f81e62dbf4d39d8b3db7f0ec17900e2d", + "0x3c1532a2b81d72a3005eb502a5cac73ec4b9b5e5f7ef46eaf45c3bd221953be3", + "0x58f9fcfcd3e7acb50d51ffdaaa8c5cd95289038a3334b2088a9e9f35f0c2b305", + "0x16c2735193a895bc955aa906c999fde489ea4584c83e7dfd7e335385968c1689", + "0x019fd3cd6c8df2e30ff42e87043c3e6783be11d039be6211c5d4c70cccb6fc41", + "0x5e99042581d29ce46bc40e1ddce5b087c0ad9f1405618d540c088a1525881ec7" + ], + "cr": [ + "0x647b30c6015fc8d0a85fd0d54268c0f8ac804c297a50caefc31341878fe51389", + "0x5052cff45999dcef8beb6bc8a089eb0b2aba0f53fed05caba508e0d7e3390488", + "0x57bab8adb1d1ad380fb201ddcd21ab7d8ca28a5d6dc6bc05a57dcc2201e25025", + "0x1aa5b880b18147d6db6fb03eca2221201d874cd362523a2ef4a8c6490679d7e5", + "0x304abd16f9a8598c0b8020f164a763141a7507529f2270861606929cbf8bf8dc", + "0x004c630be92bb68b186a8f83def940450cf2ce330089c9225e50114cb14f0387", + "0x3af5cf8aa59e85a4a8d262dc6d3a139989929cee98dea9afd524da264babfb4f", + "0x2e5ea3b5fdd80c4eb4e3bd7f16be44747368cb541ccb75ceb26c7426745f3248" + ], + "finalEvaluation": "0x0562f49390508e8a657c7690dd43bf259965452585fea1ebb4ebd076eaeb05f4" + } + } + } + }, + { + "parent_hash": "0x81cf4fcface70ad71b73a5f313400ac10c08fe33935d78bb2275ce6747c5b406", + "fee_recipient": "0xcccccccccccccccccccccccccccccccccccccccc", + "state_root": "0x4b20302831ee663994bcb346aa8c49de52f501b52997ba47b49649c43124904f", + "receipts_root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "logs_bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prev_randao": "0x98f6d35950dd43a4b3850b84213f46603d89d28e0ee77be5a45b468a04baa2fa", + "block_number": "6", + "gas_limit": "3160033", + "gas_used": "0", + "timestamp": "1699897364", + "extra_data": "0xd983010c01846765746889676f312e32302e3130856c696e7578", + "base_fee_per_gas": "451588729", + "block_hash": "0xe8f8aee5b549dffbc6ee37cbcefb3ba0d0b04dbbf931598fe3ddefa4936adae5", + "transactions": [], + "withdrawals": [], + "execution_witness": { + "stateDiff": [ + { + "stem": "0x3cc88d00122c996769be8222a4d8e62caeb8929f307d2b947ac956d49b2362", + "suffixDiffs": [ + { + "suffix": "0", + "currentValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": null + }, + { + "suffix": "1", + "currentValue": "0x00f8dc373d060000000000000000000000000000000000000000000000000000", + "newValue": null + }, + { + "suffix": "2", + "currentValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": null + }, + { + "suffix": "3", + "currentValue": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "newValue": null + }, + { + "suffix": "4", + "currentValue": null, + "newValue": null + } + ] + } + ], + "verkleProof": { + "otherStems": [], + "depthExtensionPresent": "0x0a", + "commitmentsByPath": [ + "0x29e615233d2b8fa3621c62250d4d8bbaef899b06ffafdc5de864d656f9c004b7", + "0x64b20c84f53d077f01a7818f67d2f975eaefa7722be90ca062c30c9c083bbcd2" + ], + "d": "0x4b54c77b8b5a612cafeeed38806ee21c7c4cf356e24dab2b740bffa56db4532c", + "ipaProof": { + "cl": [ + "0x5401e49d28116b01f8c88a23951bb97b870bcf0c1a686a2216c0a6ab1d0980ca", + "0x4bcdb912ea7bc8e79f85e56ec064a119be5d2957ca5dd706d79e39a212c20f0c", + "0x4897419b281e181b7c86de7c77f7eabbe78f3ede04fe66c1d0807e0188c488e0", + "0x4c6bf2502c8d72a7692b0ebdce97882db786f089d75ccb2df042576fecb54e95", + "0x0c6eb9ef3d089038cfd867925ada9f0d76bc69eba4b80e3ae4f03db71347520b", + "0x680b0bdb201c8765b0375a4e1eecc69607cf0a190e0d0a0df91613cb10c187f5", + "0x49417a59b2405b0117d5c1b1baed25319f9f1eb8aaa04cd73c30474d6f1d4b42", + "0x2dadc51222595c67e441515a6b87966384b0ded8e5bf8b3c55d7d63d08cb2c65" + ], + "cr": [ + "0x207de707a365bb8516ae012c28d998c6b9d03e78617f712957f640f55bc50009", + "0x352b1d8322433a27a2468963a61c81fe6d96ddb12e4755d88f377c8b012de331", + "0x6745c34e3c1292e88e8d564f003870c6381920724a9c9bd50866b88626d99b04", + "0x552b584ef2c001bf5b66a9358c3055f9274f231867746e0faf77d2f0d41cb939", + "0x576db2a9b2fb8e2de022a29743dc8ddb5777c3d7d9bce242bb88bfdb1da136d9", + "0x0342d60f32675d2c18da7e872fb761dbb410cae4d38e1ac75278f0ed5e1979b1", + "0x27c2458e23bbf066f7a3285d71f2934050a92cb282d8395409b80502f253f613", + "0x5a067db1769ab6202d9dcb7d2910b7b7e10129aa5d1fa34baa159a097db93c46" + ], + "finalEvaluation": "0x05d983cebb39139feddbe89d8ff57e69674fdc059a347db1dd9e713e1b65ec41" + } + } + } + }, + { + "parent_hash": "0xe8f8aee5b549dffbc6ee37cbcefb3ba0d0b04dbbf931598fe3ddefa4936adae5", + "fee_recipient": "0xcccccccccccccccccccccccccccccccccccccccc", + "state_root": "0x4b20302831ee663994bcb346aa8c49de52f501b52997ba47b49649c43124904f", + "receipts_root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "logs_bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prev_randao": "0x07d083040dcf80f9ae5c5bd84651b5ec5fda254025271057f8b3d8120459bda4", + "block_number": "7", + "gas_limit": "3163117", + "gas_used": "0", + "timestamp": "1699897370", + "extra_data": "0xd983010c01846765746889676f312e32302e3130856c696e7578", + "base_fee_per_gas": "395140138", + "block_hash": "0x42db9449e69ce333690212e6d5fd64b742ac7d86fd7674afefed03bc1129b624", + "transactions": [], + "withdrawals": [], + "execution_witness": { + "stateDiff": [ + { + "stem": "0x3cc88d00122c996769be8222a4d8e62caeb8929f307d2b947ac956d49b2362", + "suffixDiffs": [ + { + "suffix": "0", + "currentValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": null + }, + { + "suffix": "1", + "currentValue": "0x00f8dc373d060000000000000000000000000000000000000000000000000000", + "newValue": null + }, + { + "suffix": "2", + "currentValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": null + }, + { + "suffix": "3", + "currentValue": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "newValue": null + }, + { + "suffix": "4", + "currentValue": null, + "newValue": null + } + ] + } + ], + "verkleProof": { + "otherStems": [], + "depthExtensionPresent": "0x0a", + "commitmentsByPath": [ + "0x29e615233d2b8fa3621c62250d4d8bbaef899b06ffafdc5de864d656f9c004b7", + "0x64b20c84f53d077f01a7818f67d2f975eaefa7722be90ca062c30c9c083bbcd2" + ], + "d": "0x4b54c77b8b5a612cafeeed38806ee21c7c4cf356e24dab2b740bffa56db4532c", + "ipaProof": { + "cl": [ + "0x5401e49d28116b01f8c88a23951bb97b870bcf0c1a686a2216c0a6ab1d0980ca", + "0x4bcdb912ea7bc8e79f85e56ec064a119be5d2957ca5dd706d79e39a212c20f0c", + "0x4897419b281e181b7c86de7c77f7eabbe78f3ede04fe66c1d0807e0188c488e0", + "0x4c6bf2502c8d72a7692b0ebdce97882db786f089d75ccb2df042576fecb54e95", + "0x0c6eb9ef3d089038cfd867925ada9f0d76bc69eba4b80e3ae4f03db71347520b", + "0x680b0bdb201c8765b0375a4e1eecc69607cf0a190e0d0a0df91613cb10c187f5", + "0x49417a59b2405b0117d5c1b1baed25319f9f1eb8aaa04cd73c30474d6f1d4b42", + "0x2dadc51222595c67e441515a6b87966384b0ded8e5bf8b3c55d7d63d08cb2c65" + ], + "cr": [ + "0x207de707a365bb8516ae012c28d998c6b9d03e78617f712957f640f55bc50009", + "0x352b1d8322433a27a2468963a61c81fe6d96ddb12e4755d88f377c8b012de331", + "0x6745c34e3c1292e88e8d564f003870c6381920724a9c9bd50866b88626d99b04", + "0x552b584ef2c001bf5b66a9358c3055f9274f231867746e0faf77d2f0d41cb939", + "0x576db2a9b2fb8e2de022a29743dc8ddb5777c3d7d9bce242bb88bfdb1da136d9", + "0x0342d60f32675d2c18da7e872fb761dbb410cae4d38e1ac75278f0ed5e1979b1", + "0x27c2458e23bbf066f7a3285d71f2934050a92cb282d8395409b80502f253f613", + "0x5a067db1769ab6202d9dcb7d2910b7b7e10129aa5d1fa34baa159a097db93c46" + ], + "finalEvaluation": "0x05d983cebb39139feddbe89d8ff57e69674fdc059a347db1dd9e713e1b65ec41" + } + } + } + }, + { + "parent_hash": "0x42db9449e69ce333690212e6d5fd64b742ac7d86fd7674afefed03bc1129b624", + "fee_recipient": "0xcccccccccccccccccccccccccccccccccccccccc", + "state_root": "0x4b20302831ee663994bcb346aa8c49de52f501b52997ba47b49649c43124904f", + "receipts_root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "logs_bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prev_randao": "0xb0a73f71497e1599a0df3799604f52b6ab7e0eeadbbfd4be762506b72715ed74", + "block_number": "8", + "gas_limit": "3166204", + "gas_used": "0", + "timestamp": "1699897376", + "extra_data": "0xd983010c01846765746889676f312e32302e3130856c696e7578", + "base_fee_per_gas": "345747621", + "block_hash": "0x88bf75dd8909f8c47f5f3b0c0c89cf425e71cb5ae8cb92a0f1add8c96f93b063", + "transactions": [], + "withdrawals": [], + "execution_witness": { + "stateDiff": [ + { + "stem": "0x3cc88d00122c996769be8222a4d8e62caeb8929f307d2b947ac956d49b2362", + "suffixDiffs": [ + { + "suffix": "0", + "currentValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": null + }, + { + "suffix": "1", + "currentValue": "0x00f8dc373d060000000000000000000000000000000000000000000000000000", + "newValue": null + }, + { + "suffix": "2", + "currentValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": null + }, + { + "suffix": "3", + "currentValue": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "newValue": null + }, + { + "suffix": "4", + "currentValue": null, + "newValue": null + } + ] + } + ], + "verkleProof": { + "otherStems": [], + "depthExtensionPresent": "0x0a", + "commitmentsByPath": [ + "0x29e615233d2b8fa3621c62250d4d8bbaef899b06ffafdc5de864d656f9c004b7", + "0x64b20c84f53d077f01a7818f67d2f975eaefa7722be90ca062c30c9c083bbcd2" + ], + "d": "0x4b54c77b8b5a612cafeeed38806ee21c7c4cf356e24dab2b740bffa56db4532c", + "ipaProof": { + "cl": [ + "0x5401e49d28116b01f8c88a23951bb97b870bcf0c1a686a2216c0a6ab1d0980ca", + "0x4bcdb912ea7bc8e79f85e56ec064a119be5d2957ca5dd706d79e39a212c20f0c", + "0x4897419b281e181b7c86de7c77f7eabbe78f3ede04fe66c1d0807e0188c488e0", + "0x4c6bf2502c8d72a7692b0ebdce97882db786f089d75ccb2df042576fecb54e95", + "0x0c6eb9ef3d089038cfd867925ada9f0d76bc69eba4b80e3ae4f03db71347520b", + "0x680b0bdb201c8765b0375a4e1eecc69607cf0a190e0d0a0df91613cb10c187f5", + "0x49417a59b2405b0117d5c1b1baed25319f9f1eb8aaa04cd73c30474d6f1d4b42", + "0x2dadc51222595c67e441515a6b87966384b0ded8e5bf8b3c55d7d63d08cb2c65" + ], + "cr": [ + "0x207de707a365bb8516ae012c28d998c6b9d03e78617f712957f640f55bc50009", + "0x352b1d8322433a27a2468963a61c81fe6d96ddb12e4755d88f377c8b012de331", + "0x6745c34e3c1292e88e8d564f003870c6381920724a9c9bd50866b88626d99b04", + "0x552b584ef2c001bf5b66a9358c3055f9274f231867746e0faf77d2f0d41cb939", + "0x576db2a9b2fb8e2de022a29743dc8ddb5777c3d7d9bce242bb88bfdb1da136d9", + "0x0342d60f32675d2c18da7e872fb761dbb410cae4d38e1ac75278f0ed5e1979b1", + "0x27c2458e23bbf066f7a3285d71f2934050a92cb282d8395409b80502f253f613", + "0x5a067db1769ab6202d9dcb7d2910b7b7e10129aa5d1fa34baa159a097db93c46" + ], + "finalEvaluation": "0x05d983cebb39139feddbe89d8ff57e69674fdc059a347db1dd9e713e1b65ec41" + } + } + } + } +] \ No newline at end of file diff --git a/packages/client/test/testdata/geth-genesis/kaustinen2.json b/packages/client/test/testdata/geth-genesis/kaustinen2.json new file mode 100644 index 0000000000..a865839056 --- /dev/null +++ b/packages/client/test/testdata/geth-genesis/kaustinen2.json @@ -0,0 +1,86 @@ +{ + "config": { + "chainId": 69420, + "homesteadBlock": 0, + "daoForkBlock": 0, + "daoForkSupport": false, + "eip150Block": 0, + "eip150Hash": "0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0", + "eip155Block": 0, + "eip158Block": 0, + "byzantiumBlock": 0, + "constantinopleBlock": 0, + "petersburgBlock": 0, + "istanbulBlock": 0, + "muirGlacierBlock": 0, + "berlinBlock": 0, + "londonBlock": 0, + "mergeNetsplitBlock": 0, + "shanghaiTime":0, + "pragueTime":1679652600, + "terminalTotalDifficulty": 0, + "terminalTotalDifficultyPassed": true, + "proofInBlocks": true + }, + "nonce": "0x56", + "timestamp": "1679652600", + "extraData": "0x", + "gasLimit": "0x2fefd8", + "difficulty": "0x1", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase": "0x0000000000000000000000000000000000000000", + "alloc": { + "0xf97e180c050e5Ab072211Ad2C213Eb5AEE4DF134": { + "balance": "10000000000000000000000000" + }, + "0x878705ba3f8bc32fcf7f4caa1a35e72af65cf766": { + "balance": "10000000000000000000000000" + }, + "0x97C9B168C5E14d5D369B6D88E9776E5B7b11dcC1": { + "balance": "10000000000000000000000000" + }, + "0x2c3b8eb88245b03d2ee67a24b54525b4696d827f": { + "balance": "10000000000000000000000000" + }, + "0x4242424242424242424242424242424242424242": { + "balance": "0", + "code": "0x60806040526004361061003f5760003560e01c806301ffc9a71461004457806322895118146100a4578063621fd130146101ba578063c5f2892f14610244575b600080fd5b34801561005057600080fd5b506100906004803603602081101561006757600080fd5b50357fffffffff000000000000000000000000000000000000000000000000000000001661026b565b604080519115158252519081900360200190f35b6101b8600480360360808110156100ba57600080fd5b8101906020810181356401000000008111156100d557600080fd5b8201836020820111156100e757600080fd5b8035906020019184600183028401116401000000008311171561010957600080fd5b91939092909160208101903564010000000081111561012757600080fd5b82018360208201111561013957600080fd5b8035906020019184600183028401116401000000008311171561015b57600080fd5b91939092909160208101903564010000000081111561017957600080fd5b82018360208201111561018b57600080fd5b803590602001918460018302840111640100000000831117156101ad57600080fd5b919350915035610304565b005b3480156101c657600080fd5b506101cf6110b5565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102095781810151838201526020016101f1565b50505050905090810190601f1680156102365780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561025057600080fd5b506102596110c7565b60408051918252519081900360200190f35b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a70000000000000000000000000000000000000000000000000000000014806102fe57507fffffffff0000000000000000000000000000000000000000000000000000000082167f8564090700000000000000000000000000000000000000000000000000000000145b92915050565b6030861461035d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806118056026913960400191505060405180910390fd5b602084146103b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603681526020018061179c6036913960400191505060405180910390fd5b6060821461040f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260298152602001806118786029913960400191505060405180910390fd5b670de0b6b3a7640000341015610470576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806118526026913960400191505060405180910390fd5b633b9aca003406156104cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260338152602001806117d26033913960400191505060405180910390fd5b633b9aca00340467ffffffffffffffff811115610535576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061182b6027913960400191505060405180910390fd5b6060610540826114ba565b90507f649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c589898989858a8a6105756020546114ba565b6040805160a0808252810189905290819060208201908201606083016080840160c085018e8e80828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690910187810386528c815260200190508c8c808284376000838201819052601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690920188810386528c5181528c51602091820193918e019250908190849084905b83811015610648578181015183820152602001610630565b50505050905090810190601f1680156106755780820380516001836020036101000a031916815260200191505b5086810383528881526020018989808284376000838201819052601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018881038452895181528951602091820193918b019250908190849084905b838110156106ef5781810151838201526020016106d7565b50505050905090810190601f16801561071c5780820380516001836020036101000a031916815260200191505b509d505050505050505050505050505060405180910390a1600060028a8a600060801b604051602001808484808284377fffffffffffffffffffffffffffffffff0000000000000000000000000000000090941691909301908152604080517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0818403018152601090920190819052815191955093508392506020850191508083835b602083106107fc57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016107bf565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610859573d6000803e3d6000fd5b5050506040513d602081101561086e57600080fd5b5051905060006002806108846040848a8c6116fe565b6040516020018083838082843780830192505050925050506040516020818303038152906040526040518082805190602001908083835b602083106108f857805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016108bb565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610955573d6000803e3d6000fd5b5050506040513d602081101561096a57600080fd5b5051600261097b896040818d6116fe565b60405160009060200180848480828437919091019283525050604080518083038152602092830191829052805190945090925082918401908083835b602083106109f457805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016109b7565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610a51573d6000803e3d6000fd5b5050506040513d6020811015610a6657600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b60208310610ada57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610a9d565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610b37573d6000803e3d6000fd5b5050506040513d6020811015610b4c57600080fd5b50516040805160208101858152929350600092600292839287928f928f92018383808284378083019250505093505050506040516020818303038152906040526040518082805190602001908083835b60208310610bd957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610b9c565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610c36573d6000803e3d6000fd5b5050506040513d6020811015610c4b57600080fd5b50516040518651600291889160009188916020918201918291908601908083835b60208310610ca957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610c6c565b6001836020036101000a0380198251168184511680821785525050505050509050018367ffffffffffffffff191667ffffffffffffffff1916815260180182815260200193505050506040516020818303038152906040526040518082805190602001908083835b60208310610d4e57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610d11565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610dab573d6000803e3d6000fd5b5050506040513d6020811015610dc057600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b60208310610e3457805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610df7565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610e91573d6000803e3d6000fd5b5050506040513d6020811015610ea657600080fd5b50519050858114610f02576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260548152602001806117486054913960600191505060405180910390fd5b60205463ffffffff11610f60576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806117276021913960400191505060405180910390fd5b602080546001019081905560005b60208110156110a9578160011660011415610fa0578260008260208110610f9157fe5b0155506110ac95505050505050565b600260008260208110610faf57fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061102557805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610fe8565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015611082573d6000803e3d6000fd5b5050506040513d602081101561109757600080fd5b50519250600282049150600101610f6e565b50fe5b50505050505050565b60606110c26020546114ba565b905090565b6020546000908190815b60208110156112f05781600116600114156111e6576002600082602081106110f557fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061116b57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161112e565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa1580156111c8573d6000803e3d6000fd5b5050506040513d60208110156111dd57600080fd5b505192506112e2565b600283602183602081106111f657fe5b015460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061126b57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161122e565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa1580156112c8573d6000803e3d6000fd5b5050506040513d60208110156112dd57600080fd5b505192505b6002820491506001016110d1565b506002826112ff6020546114ba565b600060401b6040516020018084815260200183805190602001908083835b6020831061135a57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161131d565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790527fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000095909516920191825250604080518083037ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8018152601890920190819052815191955093508392850191508083835b6020831061143f57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101611402565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa15801561149c573d6000803e3d6000fd5b5050506040513d60208110156114b157600080fd5b50519250505090565b60408051600880825281830190925260609160208201818036833701905050905060c082901b8060071a60f81b826000815181106114f457fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060061a60f81b8260018151811061153757fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060051a60f81b8260028151811061157a57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060041a60f81b826003815181106115bd57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060031a60f81b8260048151811061160057fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060021a60f81b8260058151811061164357fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060011a60f81b8260068151811061168657fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060001a60f81b826007815181106116c957fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535050919050565b6000808585111561170d578182fd5b83861115611719578182fd5b505082019391909203915056fe4465706f736974436f6e74726163743a206d65726b6c6520747265652066756c6c4465706f736974436f6e74726163743a207265636f6e7374727563746564204465706f7369744461746120646f6573206e6f74206d6174636820737570706c696564206465706f7369745f646174615f726f6f744465706f736974436f6e74726163743a20696e76616c6964207769746864726177616c5f63726564656e7469616c73206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c7565206e6f74206d756c7469706c65206f6620677765694465706f736974436f6e74726163743a20696e76616c6964207075626b6579206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f20686967684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f206c6f774465706f736974436f6e74726163743a20696e76616c6964207369676e6174757265206c656e677468a26469706673582212201dd26f37a621703009abf16e77e69c93dc50c79db7f6cc37543e3e0e3decdc9764736f6c634300060b0033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000022": "0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b", + "0x0000000000000000000000000000000000000000000000000000000000000023": "0xdb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71", + "0x0000000000000000000000000000000000000000000000000000000000000024": "0xc78009fdf07fc56a11f122370658a353aaa542ed63e44c4bc15ff4cd105ab33c", + "0x0000000000000000000000000000000000000000000000000000000000000025": "0x536d98837f2dd165a55d5eeae91485954472d56f246df256bf3cae19352a123c", + "0x0000000000000000000000000000000000000000000000000000000000000026": "0x9efde052aa15429fae05bad4d0b1d7c64da64d03d7a1854a588c2cb8430c0d30", + "0x0000000000000000000000000000000000000000000000000000000000000027": "0xd88ddfeed400a8755596b21942c1497e114c302e6118290f91e6772976041fa1", + "0x0000000000000000000000000000000000000000000000000000000000000028": "0x87eb0ddba57e35f6d286673802a4af5975e22506c7cf4c64bb6be5ee11527f2c", + "0x0000000000000000000000000000000000000000000000000000000000000029": "0x26846476fd5fc54a5d43385167c95144f2643f533cc85bb9d16b782f8d7db193", + "0x000000000000000000000000000000000000000000000000000000000000002a": "0x506d86582d252405b840018792cad2bf1259f1ef5aa5f887e13cb2f0094f51e1", + "0x000000000000000000000000000000000000000000000000000000000000002b": "0xffff0ad7e659772f9534c195c815efc4014ef1e1daed4404c06385d11192e92b", + "0x000000000000000000000000000000000000000000000000000000000000002c": "0x6cf04127db05441cd833107a52be852868890e4317e6a02ab47683aa75964220", + "0x000000000000000000000000000000000000000000000000000000000000002d": "0xb7d05f875f140027ef5118a2247bbb84ce8f2f0f1123623085daf7960c329f5f", + "0x000000000000000000000000000000000000000000000000000000000000002e": "0xdf6af5f5bbdb6be9ef8aa618e4bf8073960867171e29676f8b284dea6a08a85e", + "0x000000000000000000000000000000000000000000000000000000000000002f": "0xb58d900f5e182e3c50ef74969ea16c7726c549757cc23523c369587da7293784", + "0x0000000000000000000000000000000000000000000000000000000000000030": "0xd49a7502ffcfb0340b1d7885688500ca308161a7f96b62df9d083b71fcc8f2bb", + "0x0000000000000000000000000000000000000000000000000000000000000031": "0x8fe6b1689256c0d385f42f5bbe2027a22c1996e110ba97c171d3e5948de92beb", + "0x0000000000000000000000000000000000000000000000000000000000000032": "0x8d0d63c39ebade8509e0ae3c9c3876fb5fa112be18f905ecacfecb92057603ab", + "0x0000000000000000000000000000000000000000000000000000000000000033": "0x95eec8b2e541cad4e91de38385f2e046619f54496c2382cb6cacd5b98c26f5a4", + "0x0000000000000000000000000000000000000000000000000000000000000034": "0xf893e908917775b62bff23294dbbe3a1cd8e6cc1c35b4801887b646a6f81f17f", + "0x0000000000000000000000000000000000000000000000000000000000000035": "0xcddba7b592e3133393c16194fac7431abf2f5485ed711db282183c819e08ebaa", + "0x0000000000000000000000000000000000000000000000000000000000000036": "0x8a8d7fe3af8caa085a7639a832001457dfb9128a8061142ad0335629ff23ff9c", + "0x0000000000000000000000000000000000000000000000000000000000000037": "0xfeb3c337d7a51a6fbf00b9e34c52e1c9195c969bd4e7a0bfd51d5c5bed9c1167", + "0x0000000000000000000000000000000000000000000000000000000000000038": "0xe71f0aa83cc32edfbefa9f4d3e0174ca85182eec9f3a09f6a6c0df6377a510d7", + "0x0000000000000000000000000000000000000000000000000000000000000039": "0x31206fa80a50bb6abe29085058f16212212a60eec8f049fecb92d8c8e0a84bc0", + "0x000000000000000000000000000000000000000000000000000000000000003a": "0x21352bfecbeddde993839f614c3dac0a3ee37543f9b412b16199dc158e23b544", + "0x000000000000000000000000000000000000000000000000000000000000003b": "0x619e312724bb6d7c3153ed9de791d764a366b389af13c58bf8a8d90481a46765", + "0x000000000000000000000000000000000000000000000000000000000000003c": "0x7cdd2986268250628d0c10e385c58c6191e6fbe05191bcc04f133f2cea72c1c4", + "0x000000000000000000000000000000000000000000000000000000000000003d": "0x848930bd7ba8cac54661072113fb278869e07bb8587f91392933374d017bcbe1", + "0x000000000000000000000000000000000000000000000000000000000000003e": "0x8869ff2c22b28cc10510d9853292803328be4fb0e80495e8bb8d271f5b889636", + "0x000000000000000000000000000000000000000000000000000000000000003f": "0xb5fe28e79f1b850f8658246ce9b6a1e7b49fc06db7143e8fe0b4f2b0c5523a5c", + "0x0000000000000000000000000000000000000000000000000000000000000040": "0x985e929f70af28d0bdd1a90a808f977f597c7c778c489e98d3bd8910d31ac0f7" + } + } + }, + "number": "0x0", + "gasUsed": "0x0", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000" +} diff --git a/packages/common/src/chains.ts b/packages/common/src/chains.ts index 209b03278a..55dd26c2ee 100644 --- a/packages/common/src/chains.ts +++ b/packages/common/src/chains.ts @@ -566,4 +566,86 @@ export const chains: ChainsDict = { 'enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@all.holesky.ethdisco.net', ], }, + kaustinen: { + name: 'kaustinen', + chainId: 69420, + networkId: 69420, + defaultHardfork: 'prague', + consensus: { + type: 'pos', + algorithm: 'casper', + }, + comment: 'Verkle kaustinen testnet 2 (likely temporary, do not hard-wire into production code)', + url: 'https://github.com/eth-clients/kaustinen/', + genesis: { + difficulty: '0x01', + extraData: '0x', + gasLimit: '0x17D7840', + nonce: '0x0000000000001234', + timestamp: '0x65608a64', + }, + hardforks: [ + { + name: 'chainstart', + block: 0, + }, + { + name: 'homestead', + block: 0, + }, + { + name: 'tangerineWhistle', + block: 0, + }, + { + name: 'spuriousDragon', + block: 0, + }, + { + name: 'byzantium', + block: 0, + }, + { + name: 'constantinople', + block: 0, + }, + { + name: 'petersburg', + block: 0, + }, + { + name: 'istanbul', + block: 0, + }, + { + name: 'berlin', + block: 0, + }, + { + name: 'london', + block: 0, + }, + { + name: 'paris', + ttd: '0', + block: 0, + }, + { + name: 'mergeForkIdTransition', + block: 0, + }, + { + name: 'shanghai', + block: null, + timestamp: '0', + }, + { + name: 'prague', + block: null, + timestamp: '1700825700', + }, + ], + bootstrapNodes: [], + dnsNetworks: [], + }, } diff --git a/packages/common/src/eips.ts b/packages/common/src/eips.ts index 282521c448..97c0262452 100644 --- a/packages/common/src/eips.ts +++ b/packages/common/src/eips.ts @@ -471,6 +471,22 @@ export const EIPs: EIPsDict = { minimumHardfork: Hardfork.London, requiredEIPs: [], }, + 6800: { + comment: 'Ethereum state using a unified verkle tree (experimental)', + url: 'https://github.com/ethereum/EIPs/pull/6800', + status: Status.Draft, + minimumHardfork: Hardfork.London, + requiredEIPs: [], + gasConfig: {}, + gasPrices: { + tx: { + v: 34300, + d: 'Per transaction. NOTE: Not payable on data of calls between transactions', + }, + }, + vm: {}, + pow: {}, + }, 7516: { comment: 'BLOBBASEFEE opcode', url: 'https://eips.ethereum.org/EIPS/eip-7516', diff --git a/packages/common/src/enums.ts b/packages/common/src/enums.ts index 352527ab53..e18f0f6a1b 100644 --- a/packages/common/src/enums.ts +++ b/packages/common/src/enums.ts @@ -5,6 +5,7 @@ export enum Chain { Goerli = 5, Sepolia = 11155111, Holesky = 17000, + Kaustinen = 69420, } /** @@ -43,6 +44,11 @@ export const ChainGenesis: Record = { blockNumber: BIGINT_0, stateRoot: hexToBytes('0x69d8c9d72f6fa4ad42d4702b433707212f90db395eb54dc20bc85de253788783'), }, + [Chain.Kaustinen]: { + name: 'kaustinen', + blockNumber: BIGINT_0, + stateRoot: hexToBytes('0x5e8519756841faf0b2c28951c451b61a4b407b70a5ce5b57992f4bec973173ff'), + }, } export enum Hardfork { @@ -64,6 +70,7 @@ export enum Hardfork { Paris = 'paris', Shanghai = 'shanghai', Cancun = 'cancun', + Prague = 'prague', } export enum ConsensusType { diff --git a/packages/common/src/hardforks.ts b/packages/common/src/hardforks.ts index a3c0267411..588096e2cb 100644 --- a/packages/common/src/hardforks.ts +++ b/packages/common/src/hardforks.ts @@ -839,4 +839,12 @@ export const hardforks: HardforksDict = { status: Status.Final, eips: [1153, 4844, 4788, 5656, 6780, 7516], }, + prague: { + name: 'prague', + comment: + 'Next feature hardfork after cancun replaing merkle based state with a verkle based one (incomplete/experimental)', + url: 'https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/prague.md', + status: Status.Draft, + eips: [6800], + }, } diff --git a/packages/common/src/utils.ts b/packages/common/src/utils.ts index a3dc52b0b2..550b05c6e9 100644 --- a/packages/common/src/utils.ts +++ b/packages/common/src/utils.ts @@ -127,6 +127,7 @@ function parseGethParams(json: any, mergeForkIdPostMerge: boolean = true) { [Hardfork.MergeForkIdTransition]: { name: 'mergeForkBlock', postMerge: mergeForkIdPostMerge }, [Hardfork.Shanghai]: { name: 'shanghaiTime', postMerge: true, isTimestamp: true }, [Hardfork.Cancun]: { name: 'cancunTime', postMerge: true, isTimestamp: true }, + [Hardfork.Prague]: { name: 'pragueTime', postMerge: true, isTimestamp: true }, } // forkMapRev is the map from config field name to Hardfork @@ -152,20 +153,23 @@ function parseGethParams(json: any, mergeForkIdPostMerge: boolean = true) { })) .filter((fork) => fork.block !== null || fork.timestamp !== undefined) as ConfigHardfork[] - for (const hf of params.hardforks) { - if (hf.timestamp === genesisTimestamp) { - hf.timestamp = 0 - } - } - params.hardforks.sort(function (a: ConfigHardfork, b: ConfigHardfork) { return (a.block ?? Infinity) - (b.block ?? Infinity) }) params.hardforks.sort(function (a: ConfigHardfork, b: ConfigHardfork) { - return (a.timestamp ?? genesisTimestamp) - (b.timestamp ?? genesisTimestamp) + // non timestamp forks come before any timestamp forks + return (a.timestamp ?? 0) - (b.timestamp ?? 0) }) + // only set the genesis timestamp forks to zero post the above sort has happended + // to get the correct sorting + for (const hf of params.hardforks) { + if (hf.timestamp === genesisTimestamp) { + hf.timestamp = 0 + } + } + if (config.terminalTotalDifficulty !== undefined) { // Following points need to be considered for placement of merge hf // - Merge hardfork can't be placed at genesis diff --git a/packages/evm/src/evm.ts b/packages/evm/src/evm.ts index a692797943..11d64d5a06 100644 --- a/packages/evm/src/evm.ts +++ b/packages/evm/src/evm.ts @@ -80,6 +80,7 @@ export class EVM implements EVMInterface { Hardfork.Paris, Hardfork.Shanghai, Hardfork.Cancun, + Hardfork.Prague, ] protected _tx?: { gasPrice: bigint @@ -164,7 +165,7 @@ export class EVM implements EVMInterface { // Supported EIPs const supportedEIPs = [ 1153, 1559, 2315, 2565, 2718, 2929, 2930, 3074, 3198, 3529, 3540, 3541, 3607, 3651, 3670, - 3855, 3860, 4399, 4895, 4788, 4844, 5133, 5656, 6780, 7516, + 3855, 3860, 4399, 4895, 4788, 4844, 5133, 5656, 6780, 6800, 7516, ] for (const eip of this.common.eips()) { diff --git a/packages/genesis/src/genesisStates/kaustinen.ts b/packages/genesis/src/genesisStates/kaustinen.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/genesis/test/index.spec.ts b/packages/genesis/test/index.spec.ts index 0a63015733..fcd24fd667 100644 --- a/packages/genesis/test/index.spec.ts +++ b/packages/genesis/test/index.spec.ts @@ -1,16 +1,17 @@ -import { ChainGenesis } from '@ethereumjs/common' +import { Chain, ChainGenesis } from '@ethereumjs/common' import { genesisStateRoot as genGenesisStateRoot } from '@ethereumjs/trie' import { bytesToHex, equalsBytes } from '@ethereumjs/util' import { assert, describe, it } from 'vitest' import { getGenesis } from '../src/index.js' -import type { Chain } from '@ethereumjs/common' - describe('genesis test', () => { it('tests getGenesis', async () => { const chainIds = Object.keys(ChainGenesis) for (const chainId of chainIds) { + // Kaustinen can have an empty genesis state since verkle blocks contain their pre-state + if (Number(chainId) === Chain.Kaustinen) continue + const { name, stateRoot: expectedRoot } = ChainGenesis[chainId as unknown as Chain] const genesisState = getGenesis(Number(chainId)) diff --git a/packages/statemanager/package.json b/packages/statemanager/package.json index 881eca1d1b..78c6c69c01 100644 --- a/packages/statemanager/package.json +++ b/packages/statemanager/package.json @@ -61,5 +61,13 @@ "@ethereumjs/block": "^5.0.1", "@ethereumjs/genesis": "^0.2.0", "@types/debug": "^4.1.9" + }, + "peerDependencies": { + "@ethereumjs/verkle": "^0.0.1" + }, + "peerDependenciesMeta": { + "@ethereumjs/verkle": { + "optional": true + } } } diff --git a/packages/statemanager/src/index.ts b/packages/statemanager/src/index.ts index 1e7a6ee9fb..fad219d75a 100644 --- a/packages/statemanager/src/index.ts +++ b/packages/statemanager/src/index.ts @@ -1,3 +1,4 @@ export * from './cache/index.js' export * from './rpcStateManager.js' +export * from './statelessVerkleStateManager.js' export * from './stateManager.js' diff --git a/packages/statemanager/src/statelessVerkleStateManager.ts b/packages/statemanager/src/statelessVerkleStateManager.ts new file mode 100644 index 0000000000..10e79478f2 --- /dev/null +++ b/packages/statemanager/src/statelessVerkleStateManager.ts @@ -0,0 +1,645 @@ +import { + Account, + KECCAK256_NULL_S, + bigIntToBytes, + bytesToBigInt, + bytesToHex, + bytesToInt32, + hexToBytes, + padToEven, + setLengthRight, + short, + toBytes, + zeros, +} from '@ethereumjs/util' +import { getKey, getStem, verifyUpdate } from '@ethereumjs/verkle' +import debugDefault from 'debug' +import { keccak256 } from 'ethereum-cryptography/keccak.js' +import { concatBytes, equalsBytes } from 'ethereum-cryptography/utils' + +import { AccountCache, CacheType, StorageCache } from './cache/index.js' +import { OriginalStorageCache } from './cache/originalStorageCache.js' + +import type { DefaultStateManager } from './stateManager.js' +import type { VerkleExecutionWitness } from '@ethereumjs/block' +import type { + AccountFields, + Common, + EVMStateManagerInterface, + Proof, + StorageDump, + StorageRange, +} from '@ethereumjs/common' +import type { Address, PrefixedHexString } from '@ethereumjs/util' + +const { debug: createDebugLogger } = debugDefault + +const debug = createDebugLogger('statemanager:verkle') + +export interface VerkleState { + [key: PrefixedHexString]: PrefixedHexString +} + +export interface EncodedVerkleProof { + [key: PrefixedHexString]: PrefixedHexString +} + +type CacheOptions = { + /** + * Allows for cache deactivation + * + * Depending on the use case and underlying datastore (and eventual concurrent cache + * mechanisms there), usage with or without cache can be faster + * + * Default: false + */ + deactivate?: boolean + + /** + * Cache type to use. + * + * Available options: + * + * ORDERED_MAP: Cache with no fixed upper bound and dynamic allocation, + * use for dynamic setups like testing or similar. + * + * LRU: LRU cache with pre-allocation of memory and a fixed size. + * Use for larger and more persistent caches. + */ + type?: CacheType + + /** + * Size of the cache (only for LRU cache) + * + * Default: 100000 (account cache) / 20000 (storage cache) + * + * Note: the cache/trie interplay mechanism is designed in a way that + * the theoretical number of max modified accounts between two flush operations + * should be smaller than the cache size, otherwise the cache will "forget" the + * old modifications resulting in an incomplete set of trie-flushed accounts. + */ + size?: number +} + +type CacheSettings = { + deactivate: boolean + type: CacheType + size: number +} + +/** + * Options dictionary. + */ +export interface StatelessVerkleStateManagerOpts { + accountCacheOpts?: CacheOptions + /** + * The common to use + */ + common?: Common + storageCacheOpts?: CacheOptions +} + +/** + * Tree key constants. + */ +const VERSION_LEAF_KEY = toBytes(0) +const BALANCE_LEAF_KEY = toBytes(1) +const NONCE_LEAF_KEY = toBytes(2) +const CODE_KECCAK_LEAF_KEY = toBytes(3) +const CODE_SIZE_LEAF_KEY = toBytes(4) + +const HEADER_STORAGE_OFFSET = 64 +const CODE_OFFSET = 128 +const VERKLE_NODE_WIDTH = 256 +const MAIN_STORAGE_OFFSET = 256 ** 31 + +const PUSH_OFFSET = 95 +// eslint-disable-next-line @typescript-eslint/no-unused-vars +const PUSH1 = PUSH_OFFSET + 1 +// eslint-disable-next-line @typescript-eslint/no-unused-vars +const PUSH32 = PUSH_OFFSET + 32 + +/** + * Stateless Verkle StateManager implementation for the VM. + * + * Experimental. + * + * This State Manager enables stateless block execution by building a + * temporary (1-block) state from the verkle block witness. + * The Stateless Verkle State Manager then uses that populated state + * to fetch data requested by the the VM. + * + */ +export class StatelessVerkleStateManager implements EVMStateManagerInterface { + _accountCache?: AccountCache + _storageCache?: StorageCache + _codeCache: { [key: string]: Uint8Array } + + originalStorageCache: OriginalStorageCache + + protected readonly _accountCacheSettings: CacheSettings + protected readonly _storageCacheSettings: CacheSettings + + /** + * StateManager is run in DEBUG mode (default: false) + * Taken from DEBUG environment variable + * + * Safeguards on debug() calls are added for + * performance reasons to avoid string literal evaluation + * @hidden + */ + protected readonly DEBUG: boolean = false + + private _executionWitness?: VerkleExecutionWitness + + private _proof: Uint8Array | undefined + + // State along execution (should update) + private _state: VerkleState = {} + + // Post-state provided from the executionWitness. + // Should not update. Used for comparing our computed post-state with the canonical one. + private _postState: VerkleState = {} + + // Checkpointing + private _checkpoints: VerkleState[] = [] + + /** + * Instantiate the StateManager interface. + */ + constructor(opts: StatelessVerkleStateManagerOpts = {}) { + this._accountCacheSettings = { + deactivate: opts.accountCacheOpts?.deactivate ?? 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 ?? 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.originalStorageCache = new OriginalStorageCache(this.getContractStorage.bind(this)) + + this._codeCache = {} + + // Skip DEBUG calls unless 'ethjs' included in environmental DEBUG variables + // Additional window check is to prevent vite browser bundling (and potentially other) to break + this.DEBUG = + typeof window === 'undefined' ? process?.env?.DEBUG?.includes('ethjs') ?? false : false + + /* + * For a custom StateManager implementation adopt these + * callbacks passed to the `Cache` instantiated to perform + * the `get`, `put` and `delete` operations with the + * desired backend. + */ + // const getCb: get = async (address) => { + // return undefined + // } + // const putCb: put = async (keyBuf, accountRlp) => {} + // const deleteCb = async (keyBuf: Uint8Array) => {} + // this._cache = new Cache({ get, putCb, deleteCb }) + } + + async getTransitionStateRoot(_: DefaultStateManager, __: Uint8Array): Promise { + throw Error('not implemented') + } + + public initVerkleExecutionWitness(executionWitness?: VerkleExecutionWitness | null) { + if (executionWitness === null || executionWitness === undefined) { + throw Error(`Invalid executionWitness=${executionWitness} for initVerkleExecutionWitness`) + } + + this._executionWitness = executionWitness + this._proof = executionWitness.verkleProof as unknown as Uint8Array + + // Populate the pre-state and post-state from the executionWitness + const preStateRaw = executionWitness.stateDiff.flatMap(({ stem, suffixDiffs }) => { + const suffixDiffPairs = suffixDiffs.map(({ currentValue, suffix }) => { + const key = `${stem}${padToEven(suffix.toString(16))}` + + // TODO: Evaluate if we should store and handle null in a special way + // Currently we are replacing `null` with 0x00..00 (32 bytes) [expect for codeHash, suffix 3, where we use the empty codeHash] for simplifying handling and comparisons + // Also, test data has been inconsistent in this regard, so this simplifies things while things get more standardized + + if (Number(suffix) === 3) { + return { [key]: currentValue ?? KECCAK256_NULL_S } + } + + return { + [key]: currentValue ?? bytesToHex(zeros(32)), + } + }) + + return suffixDiffPairs + }) + + const preState = preStateRaw.reduce((prevValue, currentValue) => { + const acc = { ...prevValue, ...currentValue } + return acc + }, {}) + + this._state = preState + + const postStateRaw = executionWitness.stateDiff.flatMap(({ stem, suffixDiffs }) => { + const suffixDiffPairs = suffixDiffs.map(({ newValue, suffix }) => { + const key = `${stem}${padToEven(suffix.toString(16))}` + // A postState value of null means there was no change from the preState. + // In this implementation, we therefore replace null with the preState. + const value = newValue ?? this._state[key] + + return { + [key]: value, + } + }) + + return suffixDiffPairs + }) + + const postState = postStateRaw.reduce((prevValue, currentValue) => { + const acc = { ...prevValue, ...currentValue } + return acc + }, {}) + + this._postState = postState + debug('initVerkleExecutionWitness preState', this._state) + debug('initVerkleExecutionWitness postState', this._postState) + } + + getTreeKeyForVersion(stem: Uint8Array) { + return getKey(stem, VERSION_LEAF_KEY) + } + + getTreeKeyForBalance(stem: Uint8Array) { + return getKey(stem, BALANCE_LEAF_KEY) + } + + getTreeKeyForNonce(stem: Uint8Array) { + return getKey(stem, NONCE_LEAF_KEY) + } + + getTreeKeyForCodeHash(stem: Uint8Array) { + return getKey(stem, CODE_KECCAK_LEAF_KEY) + } + + getTreeKeyForCodeSize(stem: Uint8Array) { + return getKey(stem, CODE_SIZE_LEAF_KEY) + } + + getTreeKeyForCodeChunk(address: Address, chunkId: number) { + return getKey( + getStem(address, Math.floor((CODE_OFFSET + chunkId) / VERKLE_NODE_WIDTH)), + toBytes((CODE_OFFSET + chunkId) % VERKLE_NODE_WIDTH) + ) + } + + chunkifyCode(code: Uint8Array) { + // Pad code to multiple of 31 bytes + if (code.length % 31 !== 0) { + const paddingLength = 31 - (code.length % 31) + code = setLengthRight(code, code.length + paddingLength) + } + + throw new Error('Not implemented') + } + + getTreeKeyForStorageSlot(address: Address, storageKey: number) { + let position: number + if (storageKey < CODE_OFFSET - HEADER_STORAGE_OFFSET) { + position = HEADER_STORAGE_OFFSET + storageKey + } else { + position = MAIN_STORAGE_OFFSET + storageKey + } + + return getKey( + getStem(address, Math.floor(position / VERKLE_NODE_WIDTH)), + toBytes(position % VERKLE_NODE_WIDTH) + ) + } + + /** + * Copies the current instance of the `StateManager` + * at the last fully committed point, i.e. as if all current + * checkpoints were reverted. + */ + shallowCopy(): EVMStateManagerInterface { + const stateManager = new StatelessVerkleStateManager() + stateManager.initVerkleExecutionWitness(this._executionWitness!) + return stateManager + } + + /** + * Adds `value` to the state trie as code, and sets `codeHash` on the account + * corresponding to `address` to reference this. + * @param address - Address of the `account` to add the `code` for + * @param value - The value of the `code` + */ + async putContractCode(address: Address, value: Uint8Array): Promise { + const stem = getStem(address, 0) + const codeHashKey = this.getTreeKeyForCodeHash(stem) + + const codeHash = bytesToHex(keccak256(value)) + + this._state[bytesToHex(codeHashKey)] = codeHash + + if (this.DEBUG) { + debug(`putContractCode address=${address.toString()} value=${short(value)}`) + } + + if (KECCAK256_NULL_S === codeHash) { + // If the code hash is the null hash, no code has to be stored + return + } + + // TODO: Slice the code into chunks and add them to the state + throw new Error('Not implemented') + } + + /** + * Gets the code corresponding to the provided `address`. + * @param address - Address to get the `code` for + * @returns {Promise} - Resolves with the code corresponding to the provided address. + * Returns an empty `Uint8Array` if the account has no associated code. + */ + async getContractCode(address: Address): Promise { + if (this.DEBUG) { + debug(`getContractCode address=${address.toString()}`) + } + // Get the contract code size + const codeSizeKey = this.getTreeKeyForCodeSize(getStem(address, 0)) + + const codeSizeLE = hexToBytes(this._state[bytesToHex(codeSizeKey)] ?? '0x') + + // Calculate number of chunks + const chunks = Math.ceil(bytesToInt32(codeSizeLE, true) / 32) + + const retrievedChunks: Uint8Array[] = [] + + // Retrieve all code chunks + for (let chunkId = 0; chunkId < chunks; chunkId++) { + retrievedChunks.push(this.getTreeKeyForCodeChunk(address, chunkId)) + } + + // Aggregate code chunks + const code = concatBytes(...retrievedChunks) + + // Return code chunks + return code + } + + /** + * Gets the storage value associated with the provided `address` and `key`. This method returns + * the shortest representation of the stored value. + * @param address - Address of the account to get the storage for + * @param key - Key in the account's storage to get the value for. Must be 32 bytes long. + * @returns {Promise} - The storage value for the account + * corresponding to the provided address at the provided key. + * If this does not exist an empty `Uint8Array` is returned. + */ + async getContractStorage(address: Address, key: Uint8Array): Promise { + const storageKey = this.getTreeKeyForStorageSlot(address, Number(bytesToHex(key))) + const storage = toBytes(this._state[bytesToHex(storageKey)]) + + return storage + } + + /** + * Adds value to the state for the `account` + * corresponding to `address` at the provided `key`. + * @param address - Address to set a storage value for + * @param key - Key to set the value at. Must be 32 bytes long. + * @param value - Value to set at `key` for account corresponding to `address`. Cannot be more than 32 bytes. Leading zeros are stripped. If it is a empty or filled with zeros, deletes the value. + */ + async putContractStorage(address: Address, key: Uint8Array, value: Uint8Array): Promise { + const storageKey = this.getTreeKeyForStorageSlot(address, Number(bytesToHex(key))) + this._state[bytesToHex(storageKey)] = bytesToHex(value) + } + + /** + * Clears all storage entries for the account corresponding to `address`. + * @param address - Address to clear the storage of + */ + async clearContractStorage(address: Address): Promise { + const stem = getStem(address, 0) + const codeHashKey = this.getTreeKeyForCodeHash(stem) + // Update codeHash to `c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470` + this._state[bytesToHex(codeHashKey)] = KECCAK256_NULL_S + + // TODO: Clear all storage slots (how?) + } + + async getAccount(address: Address): Promise { + const stem = getStem(address, 0) + const balanceKey = this.getTreeKeyForBalance(stem) + const nonceKey = this.getTreeKeyForNonce(stem) + const codeHashKey = this.getTreeKeyForCodeHash(stem) + + const balanceRaw = this._state[bytesToHex(balanceKey)] + const nonceRaw = this._state[bytesToHex(nonceKey)] + const codeHash = this._state[bytesToHex(codeHashKey)] + + const account = Account.fromAccountData({ + balance: + typeof balanceRaw === 'string' ? bytesToBigInt(hexToBytes(balanceRaw), true) : undefined, + nonce: typeof nonceRaw === 'string' ? bytesToBigInt(hexToBytes(nonceRaw), true) : undefined, + codeHash, + }) + if (this.DEBUG) { + debug( + `getAccount address=${address.toString()} stem=${short(stem)} balance=${ + account.balance + } nonce=${account.nonce} codeHash=${short(account.codeHash)} storageHash=${short( + account.storageRoot + )}` + ) + } + return account + } + + async putAccount(address: Address, account: Account): Promise { + const stem = getStem(address, 0) + const balanceKey = this.getTreeKeyForBalance(stem) + const nonceKey = this.getTreeKeyForNonce(stem) + const codeHashKey = this.getTreeKeyForCodeHash(stem) + + const balanceBuf = setLengthRight(bigIntToBytes(account.balance, true), 32) + const nonceBuf = setLengthRight(bigIntToBytes(account.nonce, true), 32) + + this._state[bytesToHex(balanceKey)] = bytesToHex(balanceBuf) + this._state[bytesToHex(nonceKey)] = bytesToHex(nonceBuf) + this._state[bytesToHex(codeHashKey)] = bytesToHex(account.codeHash) + + if (this.DEBUG) { + debug( + `putAccount address=${address.toString()} stem=${short(stem)} balance=${ + account.balance + } nonce=${account.nonce} codeHash=${short(account.codeHash)} storageHash=${short( + account.storageRoot + )}` + ) + } + } + + /** + * Deletes an account from state under the provided `address`. + * @param address - Address of the account which should be deleted + */ + async deleteAccount(address: Address) { + this._accountCache!.del(address) + + if (!this._storageCacheSettings.deactivate) { + this._storageCache?.clearContractStorage(address) + } + } + + async modifyAccountFields(address: Address, accountFields: AccountFields): Promise { + const account = await this.getAccount(address) + + 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) + } + + getProof(_: Address, __: Uint8Array[] = []): Promise { + throw new Error('Not implemented yet') + } + + async verifyProof(parentVerkleRoot: Uint8Array): Promise { + // Implementation: https://github.com/crate-crypto/rust-verkle-wasm/blob/master/src/lib.rs#L45 + // The root is the root of the current (un-updated) trie + // The proof is proof of membership of all of the accessed values + // keys_values is a map from the key of the accessed value to a tuple + // the tuple contains the old value and the updated value + // + // This function returns the new root when all of the updated values are applied + + const updatedStateRoot: Uint8Array = verifyUpdate( + parentVerkleRoot, + this._proof!, // TODO: Convert this into a Uint8Array ingestible by the method + new Map() // TODO: Generate the keys_values map from the old to the updated value + ) + + // TODO: Not sure if this should return the updated state Root (current block) or the un-updated one (parent block) + const verkleRoot = await this.getStateRoot() + + // Verify that updatedStateRoot matches the state root of the block + return equalsBytes(updatedStateRoot, verkleRoot) + } + + // Verifies that the witness post-state matches the computed post-state + verifyPostState(): boolean { + for (const [key, canonicalValue] of Object.entries(this._postState)) { + const computedValue = this._state[key] + if (canonicalValue !== computedValue) { + debug( + `verifyPostState failed for key ${key}. Canonical value: ${canonicalValue}, computed value: ${computedValue}` + ) + return false + } + } + return true + } + + /** + * Checkpoints the current state of the StateManager instance. + * State changes that follow can then be committed by calling + * `commit` or `reverted` by calling rollback. + */ + async checkpoint(): Promise { + this._checkpoints.push(this._state) + this._accountCache?.checkpoint() + this._storageCache?.checkpoint() + } + + /** + * Commits the current change-set to the instance since the + * last call to checkpoint. + */ + async commit(): Promise { + this._checkpoints.pop() + this._accountCache!.commit() + } + + // TODO + async hasStateRoot(_: Uint8Array): Promise { + return true + } + + /** + * Reverts the current change-set to the instance since the + * last call to checkpoint. + */ + async revert(): Promise { + // setup trie checkpointing + this._accountCache?.revert() + this._storageCache?.revert() + this._codeCache = {} + } + + /** + * Writes all cache items to the trie + */ + async flush(): Promise {} + + /** + * Gets the verkle root. + * NOTE: this needs some examination in the code where this is needed + * and if we have the verkle root present + * @returns {Promise} - Returns the verkle root of the `StateManager` + */ + async getStateRoot(): Promise { + return new Uint8Array(0) + } + + /** + * TODO: needed? + * Maybe in this context: reset to original pre state suffice + * @param stateRoot - The verkle root to reset the instance to + */ + async setStateRoot(_: Uint8Array): Promise {} + + /** + * Dumps the RLP-encoded storage values for an `account` specified by `address`. + * @param address - The address of the `account` to return storage for + * @returns {Promise} - The state of the account as an `Object` map. + * Keys are are the storage keys, values are the storage values as strings. + * Both are represented as hex strings without the `0x` prefix. + */ + async dumpStorage(_: Address): Promise { + throw Error('not implemented') + } + + dumpStorageRange(_: Address, __: bigint, ___: number): Promise { + throw Error('not implemented') + } + + /** + * Clears all underlying caches + */ + clearCaches() { + this._accountCache?.clear() + this._storageCache?.clear() + } + + generateCanonicalGenesis(_initState: any): Promise { + return Promise.resolve() + } +} diff --git a/packages/statemanager/test/statelessVerkleStateManager.spec.ts b/packages/statemanager/test/statelessVerkleStateManager.spec.ts new file mode 100644 index 0000000000..3b3e6e5267 --- /dev/null +++ b/packages/statemanager/test/statelessVerkleStateManager.spec.ts @@ -0,0 +1,46 @@ +import { Block } from '@ethereumjs/block' +import { Common } from '@ethereumjs/common' +import { Address, bytesToHex } from '@ethereumjs/util' +import { assert, describe, it } from 'vitest' + +import { StatelessVerkleStateManager } from '../src/index.js' + +import * as testnetVerkleKaustinen from './testdata/testnetVerkleKaustinen.json' +import * as verkleBlockJSON from './testdata/verkleKaustinenBlock.json' + +describe('StatelessVerkleStateManager: Kaustinen Verkle Block', () => { + const common = Common.fromGethGenesis(testnetVerkleKaustinen, { + chain: 'customChain', + eips: [6800], + }) + const block = Block.fromBlockData(verkleBlockJSON, { common }) + + it('initPreState()', async () => { + const stateManager = new StatelessVerkleStateManager() + stateManager.initVerkleExecutionWitness(block.executionWitness) + + assert.ok(Object.keys(stateManager['_state']).length !== 0, 'should initialize with state') + }) + + it('getAccount()', async () => { + const stateManager = new StatelessVerkleStateManager({ common }) + stateManager.initVerkleExecutionWitness(block.executionWitness) + + const account = await stateManager.getAccount( + Address.fromString('0x9791ded6e5d3d5dafca71bb7bb2a14187d17e32e') + ) + + assert.equal(account.balance, 99765345920194942688594n, 'should have correct balance') + assert.equal(account.nonce, 3963257n, 'should have correct nonce') + assert.equal( + bytesToHex(account.storageRoot), + '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421', + 'should have correct storageRoot' + ) + assert.equal( + bytesToHex(account.codeHash), + '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470', + 'should have correct codeHash' + ) + }) +}) diff --git a/packages/statemanager/test/testdata/testnetVerkleKaustinen.json b/packages/statemanager/test/testdata/testnetVerkleKaustinen.json new file mode 100644 index 0000000000..7000c1bb60 --- /dev/null +++ b/packages/statemanager/test/testdata/testnetVerkleKaustinen.json @@ -0,0 +1,76 @@ +{ + "config": { + "chainId": 69420, + "homesteadBlock": 0, + "daoForkBlock": 0, + "daoForkSupport": false, + "eip150Block": 0, + "eip150Hash": "0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0", + "eip155Block": 0, + "eip158Block": 0, + "byzantiumBlock": 0, + "constantinopleBlock": 0, + "petersburgBlock": 0, + "istanbulBlock": 0, + "muirGlacierBlock": 0, + "berlinBlock": 0, + "londonBlock": 0, + "cancunBlock": 0, + "mergeNetsplitBlock": 0, + "terminalTotalDifficulty": 0, + "ethash": {} + }, + "nonce": "0x56", + "timestamp": "1679652600", + "extraData": "0x", + "gasLimit": "0x2fefd8", + "difficulty": "0x1", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase": "0x0000000000000000000000000000000000000000", + "alloc": { + "0xf97e180c050e5Ab072211Ad2C213Eb5AEE4DF134": { + "balance": "10000000000000000000000000" + }, + "0x4242424242424242424242424242424242424242": { + "balance": "0", + "code": "0x60806040526004361061003f5760003560e01c806301ffc9a71461004457806322895118146100a4578063621fd130146101ba578063c5f2892f14610244575b600080fd5b34801561005057600080fd5b506100906004803603602081101561006757600080fd5b50357fffffffff000000000000000000000000000000000000000000000000000000001661026b565b604080519115158252519081900360200190f35b6101b8600480360360808110156100ba57600080fd5b8101906020810181356401000000008111156100d557600080fd5b8201836020820111156100e757600080fd5b8035906020019184600183028401116401000000008311171561010957600080fd5b91939092909160208101903564010000000081111561012757600080fd5b82018360208201111561013957600080fd5b8035906020019184600183028401116401000000008311171561015b57600080fd5b91939092909160208101903564010000000081111561017957600080fd5b82018360208201111561018b57600080fd5b803590602001918460018302840111640100000000831117156101ad57600080fd5b919350915035610304565b005b3480156101c657600080fd5b506101cf6110b5565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102095781810151838201526020016101f1565b50505050905090810190601f1680156102365780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561025057600080fd5b506102596110c7565b60408051918252519081900360200190f35b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a70000000000000000000000000000000000000000000000000000000014806102fe57507fffffffff0000000000000000000000000000000000000000000000000000000082167f8564090700000000000000000000000000000000000000000000000000000000145b92915050565b6030861461035d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806118056026913960400191505060405180910390fd5b602084146103b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603681526020018061179c6036913960400191505060405180910390fd5b6060821461040f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260298152602001806118786029913960400191505060405180910390fd5b670de0b6b3a7640000341015610470576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806118526026913960400191505060405180910390fd5b633b9aca003406156104cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260338152602001806117d26033913960400191505060405180910390fd5b633b9aca00340467ffffffffffffffff811115610535576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061182b6027913960400191505060405180910390fd5b6060610540826114ba565b90507f649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c589898989858a8a6105756020546114ba565b6040805160a0808252810189905290819060208201908201606083016080840160c085018e8e80828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690910187810386528c815260200190508c8c808284376000838201819052601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690920188810386528c5181528c51602091820193918e019250908190849084905b83811015610648578181015183820152602001610630565b50505050905090810190601f1680156106755780820380516001836020036101000a031916815260200191505b5086810383528881526020018989808284376000838201819052601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018881038452895181528951602091820193918b019250908190849084905b838110156106ef5781810151838201526020016106d7565b50505050905090810190601f16801561071c5780820380516001836020036101000a031916815260200191505b509d505050505050505050505050505060405180910390a1600060028a8a600060801b604051602001808484808284377fffffffffffffffffffffffffffffffff0000000000000000000000000000000090941691909301908152604080517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0818403018152601090920190819052815191955093508392506020850191508083835b602083106107fc57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016107bf565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610859573d6000803e3d6000fd5b5050506040513d602081101561086e57600080fd5b5051905060006002806108846040848a8c6116fe565b6040516020018083838082843780830192505050925050506040516020818303038152906040526040518082805190602001908083835b602083106108f857805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016108bb565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610955573d6000803e3d6000fd5b5050506040513d602081101561096a57600080fd5b5051600261097b896040818d6116fe565b60405160009060200180848480828437919091019283525050604080518083038152602092830191829052805190945090925082918401908083835b602083106109f457805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016109b7565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610a51573d6000803e3d6000fd5b5050506040513d6020811015610a6657600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b60208310610ada57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610a9d565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610b37573d6000803e3d6000fd5b5050506040513d6020811015610b4c57600080fd5b50516040805160208101858152929350600092600292839287928f928f92018383808284378083019250505093505050506040516020818303038152906040526040518082805190602001908083835b60208310610bd957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610b9c565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610c36573d6000803e3d6000fd5b5050506040513d6020811015610c4b57600080fd5b50516040518651600291889160009188916020918201918291908601908083835b60208310610ca957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610c6c565b6001836020036101000a0380198251168184511680821785525050505050509050018367ffffffffffffffff191667ffffffffffffffff1916815260180182815260200193505050506040516020818303038152906040526040518082805190602001908083835b60208310610d4e57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610d11565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610dab573d6000803e3d6000fd5b5050506040513d6020811015610dc057600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b60208310610e3457805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610df7565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610e91573d6000803e3d6000fd5b5050506040513d6020811015610ea657600080fd5b50519050858114610f02576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260548152602001806117486054913960600191505060405180910390fd5b60205463ffffffff11610f60576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806117276021913960400191505060405180910390fd5b602080546001019081905560005b60208110156110a9578160011660011415610fa0578260008260208110610f9157fe5b0155506110ac95505050505050565b600260008260208110610faf57fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061102557805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610fe8565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015611082573d6000803e3d6000fd5b5050506040513d602081101561109757600080fd5b50519250600282049150600101610f6e565b50fe5b50505050505050565b60606110c26020546114ba565b905090565b6020546000908190815b60208110156112f05781600116600114156111e6576002600082602081106110f557fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061116b57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161112e565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa1580156111c8573d6000803e3d6000fd5b5050506040513d60208110156111dd57600080fd5b505192506112e2565b600283602183602081106111f657fe5b015460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061126b57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161122e565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa1580156112c8573d6000803e3d6000fd5b5050506040513d60208110156112dd57600080fd5b505192505b6002820491506001016110d1565b506002826112ff6020546114ba565b600060401b6040516020018084815260200183805190602001908083835b6020831061135a57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161131d565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790527fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000095909516920191825250604080518083037ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8018152601890920190819052815191955093508392850191508083835b6020831061143f57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101611402565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa15801561149c573d6000803e3d6000fd5b5050506040513d60208110156114b157600080fd5b50519250505090565b60408051600880825281830190925260609160208201818036833701905050905060c082901b8060071a60f81b826000815181106114f457fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060061a60f81b8260018151811061153757fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060051a60f81b8260028151811061157a57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060041a60f81b826003815181106115bd57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060031a60f81b8260048151811061160057fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060021a60f81b8260058151811061164357fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060011a60f81b8260068151811061168657fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060001a60f81b826007815181106116c957fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535050919050565b6000808585111561170d578182fd5b83861115611719578182fd5b505082019391909203915056fe4465706f736974436f6e74726163743a206d65726b6c6520747265652066756c6c4465706f736974436f6e74726163743a207265636f6e7374727563746564204465706f7369744461746120646f6573206e6f74206d6174636820737570706c696564206465706f7369745f646174615f726f6f744465706f736974436f6e74726163743a20696e76616c6964207769746864726177616c5f63726564656e7469616c73206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c7565206e6f74206d756c7469706c65206f6620677765694465706f736974436f6e74726163743a20696e76616c6964207075626b6579206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f20686967684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f206c6f774465706f736974436f6e74726163743a20696e76616c6964207369676e6174757265206c656e677468a26469706673582212201dd26f37a621703009abf16e77e69c93dc50c79db7f6cc37543e3e0e3decdc9764736f6c634300060b0033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000022": "0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b", + "0x0000000000000000000000000000000000000000000000000000000000000023": "0xdb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71", + "0x0000000000000000000000000000000000000000000000000000000000000024": "0xc78009fdf07fc56a11f122370658a353aaa542ed63e44c4bc15ff4cd105ab33c", + "0x0000000000000000000000000000000000000000000000000000000000000025": "0x536d98837f2dd165a55d5eeae91485954472d56f246df256bf3cae19352a123c", + "0x0000000000000000000000000000000000000000000000000000000000000026": "0x9efde052aa15429fae05bad4d0b1d7c64da64d03d7a1854a588c2cb8430c0d30", + "0x0000000000000000000000000000000000000000000000000000000000000027": "0xd88ddfeed400a8755596b21942c1497e114c302e6118290f91e6772976041fa1", + "0x0000000000000000000000000000000000000000000000000000000000000028": "0x87eb0ddba57e35f6d286673802a4af5975e22506c7cf4c64bb6be5ee11527f2c", + "0x0000000000000000000000000000000000000000000000000000000000000029": "0x26846476fd5fc54a5d43385167c95144f2643f533cc85bb9d16b782f8d7db193", + "0x000000000000000000000000000000000000000000000000000000000000002a": "0x506d86582d252405b840018792cad2bf1259f1ef5aa5f887e13cb2f0094f51e1", + "0x000000000000000000000000000000000000000000000000000000000000002b": "0xffff0ad7e659772f9534c195c815efc4014ef1e1daed4404c06385d11192e92b", + "0x000000000000000000000000000000000000000000000000000000000000002c": "0x6cf04127db05441cd833107a52be852868890e4317e6a02ab47683aa75964220", + "0x000000000000000000000000000000000000000000000000000000000000002d": "0xb7d05f875f140027ef5118a2247bbb84ce8f2f0f1123623085daf7960c329f5f", + "0x000000000000000000000000000000000000000000000000000000000000002e": "0xdf6af5f5bbdb6be9ef8aa618e4bf8073960867171e29676f8b284dea6a08a85e", + "0x000000000000000000000000000000000000000000000000000000000000002f": "0xb58d900f5e182e3c50ef74969ea16c7726c549757cc23523c369587da7293784", + "0x0000000000000000000000000000000000000000000000000000000000000030": "0xd49a7502ffcfb0340b1d7885688500ca308161a7f96b62df9d083b71fcc8f2bb", + "0x0000000000000000000000000000000000000000000000000000000000000031": "0x8fe6b1689256c0d385f42f5bbe2027a22c1996e110ba97c171d3e5948de92beb", + "0x0000000000000000000000000000000000000000000000000000000000000032": "0x8d0d63c39ebade8509e0ae3c9c3876fb5fa112be18f905ecacfecb92057603ab", + "0x0000000000000000000000000000000000000000000000000000000000000033": "0x95eec8b2e541cad4e91de38385f2e046619f54496c2382cb6cacd5b98c26f5a4", + "0x0000000000000000000000000000000000000000000000000000000000000034": "0xf893e908917775b62bff23294dbbe3a1cd8e6cc1c35b4801887b646a6f81f17f", + "0x0000000000000000000000000000000000000000000000000000000000000035": "0xcddba7b592e3133393c16194fac7431abf2f5485ed711db282183c819e08ebaa", + "0x0000000000000000000000000000000000000000000000000000000000000036": "0x8a8d7fe3af8caa085a7639a832001457dfb9128a8061142ad0335629ff23ff9c", + "0x0000000000000000000000000000000000000000000000000000000000000037": "0xfeb3c337d7a51a6fbf00b9e34c52e1c9195c969bd4e7a0bfd51d5c5bed9c1167", + "0x0000000000000000000000000000000000000000000000000000000000000038": "0xe71f0aa83cc32edfbefa9f4d3e0174ca85182eec9f3a09f6a6c0df6377a510d7", + "0x0000000000000000000000000000000000000000000000000000000000000039": "0x31206fa80a50bb6abe29085058f16212212a60eec8f049fecb92d8c8e0a84bc0", + "0x000000000000000000000000000000000000000000000000000000000000003a": "0x21352bfecbeddde993839f614c3dac0a3ee37543f9b412b16199dc158e23b544", + "0x000000000000000000000000000000000000000000000000000000000000003b": "0x619e312724bb6d7c3153ed9de791d764a366b389af13c58bf8a8d90481a46765", + "0x000000000000000000000000000000000000000000000000000000000000003c": "0x7cdd2986268250628d0c10e385c58c6191e6fbe05191bcc04f133f2cea72c1c4", + "0x000000000000000000000000000000000000000000000000000000000000003d": "0x848930bd7ba8cac54661072113fb278869e07bb8587f91392933374d017bcbe1", + "0x000000000000000000000000000000000000000000000000000000000000003e": "0x8869ff2c22b28cc10510d9853292803328be4fb0e80495e8bb8d271f5b889636", + "0x000000000000000000000000000000000000000000000000000000000000003f": "0xb5fe28e79f1b850f8658246ce9b6a1e7b49fc06db7143e8fe0b4f2b0c5523a5c", + "0x0000000000000000000000000000000000000000000000000000000000000040": "0x985e929f70af28d0bdd1a90a808f977f597c7c778c489e98d3bd8910d31ac0f7" + } + } + }, + "number": "0x0", + "gasUsed": "0x0", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "baseFeePerGas": null +} diff --git a/packages/statemanager/test/testdata/verkleKaustinenBlock.json b/packages/statemanager/test/testdata/verkleKaustinenBlock.json new file mode 100644 index 0000000000..8597462e71 --- /dev/null +++ b/packages/statemanager/test/testdata/verkleKaustinenBlock.json @@ -0,0 +1,647 @@ +{ + "header": { + "baseFeePerGas": "0x8", + "blockHash": "0xb528b8feb9f7c45dc76b1dab179567f3fcbba43069c0835e20e2080b9e1bf47d", + "blockNumber": "0x680c5", + "extraData": "0x", + "feeRecipient": "0xf97e180c050e5ab072211ad2c213eb5aee4df134", + "gasLimit": "0x1c9c380", + "gasUsed": "0x9f08f", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "parentHash": "0x87c1abaf5d93799d62a37db5506cbc09551bc53433796ca7906b1de6c683b305", + "prevRandao": "0xde46f41bf314eee291472323c0ca8f2739ad687c5b29ef9ee496cf98add9e7bb", + "receiptsRoot": "0x4bdd2c518110f2142b6368dde87fe25609646f6c589397cf759baf3c7344ab9b", + "stateRoot": "0x43a3e98ba6fb6b303692b5279c7eeb8a191aa7cbff0ffd425368eb34a470268b", + "timestamp": "0x646f4448", + "transactionsTrie": "0x6158b8a8726077d42aac4433db063c79f8413054842d21cae7345941b86e9f35" + }, + "transactions": [ + { + "type": "0x2", + "nonce": "0x3", + "gasLimit": "0x23011", + "to": "0x", + "value": "0x0", + "data": "0x608060405234801561001057600080fd5b50610150806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80632e64cec11461003b5780636057361d14610059575b600080fd5b610043610075565b60405161005091906100a1565b60405180910390f35b610073600480360381019061006e91906100ed565b61007e565b005b60008054905090565b8060008190555050565b6000819050919050565b61009b81610088565b82525050565b60006020820190506100b66000830184610092565b92915050565b600080fd5b6100ca81610088565b81146100d557600080fd5b50565b6000813590506100e7816100c1565b92915050565b600060208284031215610103576101026100bc565b5b6000610111848285016100d8565b9150509291505056fea26469706673582212208f6a6e5a1a593ae1ba29bd21e9d6e9092ae1df1986f8e8de139149a0e99dce1564736f6c63430008120033", + "v": "0x1", + "r": "0x272074bd1345fad76ab5e5a41b575890ebbb83747eb407e58caf61cbc503d357", + "s": "0x33d7a5ef1209b877e6cfb5aeab25e120e5a0d1acfc628ff04b85d7f0df4b3ddf", + "chainId": "0x10f2c", + "maxPriorityFeePerGas": "0x9502f900", + "maxFeePerGas": "0x9502f910", + "accessList": [] + }, + { + "type": "0x2", + "nonce": "0x4", + "gasLimit": "0x23011", + "to": "0x", + "value": "0x0", + "data": "0x608060405234801561001057600080fd5b50610150806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80632e64cec11461003b5780636057361d14610059575b600080fd5b610043610075565b60405161005091906100a1565b60405180910390f35b610073600480360381019061006e91906100ed565b61007e565b005b60008054905090565b8060008190555050565b6000819050919050565b61009b81610088565b82525050565b60006020820190506100b66000830184610092565b92915050565b600080fd5b6100ca81610088565b81146100d557600080fd5b50565b6000813590506100e7816100c1565b92915050565b600060208284031215610103576101026100bc565b5b6000610111848285016100d8565b9150509291505056fea26469706673582212208f6a6e5a1a593ae1ba29bd21e9d6e9092ae1df1986f8e8de139149a0e99dce1564736f6c63430008120033", + "v": "0x0", + "r": "0xedf90bc7c4803cd34a1db633a06ba65d2aa15fbcacd24840a7787892efe0f05f", + "s": "0x5729091ec8aee9f2cada76ee82a6d67c575dcd9a138c9c99d92740ba2aff4ace", + "chainId": "0x10f2c", + "maxPriorityFeePerGas": "0x9502f900", + "maxFeePerGas": "0x9502f910", + "accessList": [] + }, + { + "type": "0x0", + "nonce": "0x3c7979", + "gasLimit": "0x186a0", + "to": "0xfc32a5c92c78e00b753283f45fd00c684ecff693", + "value": "0x0", + "data": "0x7f2d01a9842cdc19531652a41333db96f8f11f504385613a98b2e1394c095dc2bd60f9527f61d73699c64e21e12f8fe4a2ee7011812c49407abd0af9b8a5a7d66d507dadba610119527f44b98490e04b17a045b4e61761d325c37f808a7e5943e0373a559fb6598d5427610139527f8978a03e359c3e219cf3111998317cc24c", + "v": "0x21e7c", + "r": "0x7623d524742ccbc3059ea95d603b3fac066daf4300bd6d58f1378cb742c004fc", + "s": "0x1a057f8ccc7b60bb53683b72f9fe8c050ba7e96f4a5c77a1f96f922e4020f219", + "gasPrice": "0x3b9b1368" + }, + { + "type": "0x0", + "nonce": "0x3c797a", + "gasLimit": "0x186a0", + "to": "0x66a68bc25814f4d763327f7b9774463af847806d", + "value": "0x0", + "data": "0x60a7606b5360a3606c53609a606d536021606e5360e1606f5379600060ac5560006003556000606755", + "v": "0x21e7c", + "r": "0xcc2dd5879ca718288f279c1e0e9f521bf17cf19a6bee3522fe8fa019c169e485", + "s": "0x548cbe026fad70112faea072a1dc36a797e0bc0f97b1a82ddbe3568d15feece4", + "gasPrice": "0x3b9b1368" + }, + { + "type": "0x1", + "nonce": "0x3c797b", + "gasLimit": "0x186a0", + "to": "0x", + "value": "0x0", + "data": "0x7e7f7654ea857876c2f81f3e9ac805692ec2a16d2262c71961753ad1d251d71c2f386024527f9183f5f9fdffbfb870a8d8c150597eb13f88c691d53a9fdd5fb80287dc96699b6031527fbf80293e0df727acdb32469584afd3c7eeb61bdda84f2dacd0b37a44aa6204126051527fa9d47cae3479a9e05fad17765c563caf9e43", + "v": "0x0", + "r": "0xc74589e3654e1065977e507d0785ab4b22fbb0f0c05791ce6b2ceb53b86fc70c", + "s": "0x76eba80a9488ef2073a0a7c8fd914ece9c33e915e59884737ad45b78349ebd73", + "chainId": "0x10f2c", + "gasPrice": "0x3b9b1368", + "accessList": [] + }, + { + "type": "0x0", + "nonce": "0x3c797c", + "gasLimit": "0x186a0", + "to": "0x", + "value": "0x0", + "data": "0x78600060b1556091604e53605b604f5360ca605053606460515360eb60525360c360535360d760545360736055536082605653600b605753604b6058536054605953603c605a5360c2605b536073605c53600b605d5360ff605e537f5b823f64815224d1718fdfd1f205b06828542ca9426a5a88be06cfbe3d37001e60bd5260", + "v": "0x21e7b", + "r": "0xa1f2db6e99a5bc25f992a224c89cd9e158544ee16292e5fe00ddc3b22462cbd9", + "s": "0x73ecebc3c5772309cbabb11ab1b4c284e0cd625177202d7e052946e13ec99319", + "gasPrice": "0x3b9b1368" + }, + { + "type": "0x0", + "nonce": "0x3c797d", + "gasLimit": "0x186a0", + "to": "0xb02a2eda1b317fbd16760128836b0ac59b560e9d", + "value": "0x0", + "data": "0x7f53a1da3bbb96dc7f50d0b6f982567bc224e05c981d0a626f516323930b1d5e95602852604660485360b7604953cf6000609c55604a60245360ad602553607c602653607e60275360ae602853602b6029536003602a5360ee602b5360a5602c5360d5602d5360a7602e5360cf602f5360ba603053601c603153608260325360", + "v": "0x21e7c", + "r": "0x519314cb62a34f2578f94c084e8ff4cd7a8148270edcef572c2cde24f38960bc", + "s": "0x67cfbd75c6c556cd3b4c0e34fc098a3fce8c8fae4230106e9340c858c12a0323", + "gasPrice": "0x3b9b1368" + }, + { + "type": "0x0", + "nonce": "0x3c797e", + "gasLimit": "0x186a0", + "to": "0xae7d74fe5748f2675946c7542f4a3c729037b417", + "value": "0x0", + "data": "0x", + "v": "0x21e7c", + "r": "0xc6b4d19380f4e1527dddb9e82021cba2ce483d144e2360c3e31f8bbd5950d96b", + "s": "0x5f503fd55dcb51605d870a9833a8e8b4e8d352efd4798be70ae273185a3194f8", + "gasPrice": "0x3b9b1368" + }, + { + "type": "0x2", + "nonce": "0x3c797f", + "gasLimit": "0x186a0", + "to": "0xb02a2eda1b317fbd16760128836b0ac59b560e9d", + "value": "0x0", + "data": "0x9b948702eeb75ba77ffa681fb04ba4b3ff1fd0cd9b4c773796f008e230da7ef9f9ffd7ec04212d29d4604e527f76b3bf72263ccb7bc2a5a1c7d4529fd2e617ead0c0a8bc22b48bd887770897d9606e527fa241ae8d0974af7c4329355d6ba6b82741e0b2f3fa12755c1b4373c174b58f34608e527fb8e59608c4d61527cb6af4", + "v": "0x0", + "r": "0xaec3bb3876aa6301f1a4f03a3ec65cad1de1b12323fd1cfea76dad95740a83b0", + "s": "0x421a2088a5b1d14aa357ac368bb4f7a0052bfcc79693fb531e3aeb44e5937b0c", + "chainId": "0x10f2c", + "maxPriorityFeePerGas": "0x3b9b1360", + "maxFeePerGas": "0x3b9b1368", + "accessList": [] + }, + { + "type": "0x1", + "nonce": "0x3c7980", + "gasLimit": "0x186a0", + "to": "0xb02a2eda1b317fbd16760128836b0ac59b560e9d", + "value": "0x0", + "data": "0x600060565560006041557fdaf76cfabc5c32c462d3caf74accf78f4941c9bc501b9064aa1a52cfc0d1b1cd6013527f0b03c5292bd0ab5eace6a0a857290695e471f4893253a163f8ec6149e0e1d1dd6033527fc866d02fc029f173ae232870cb8ea7fc272bd888c47c1460685bce303e1c939b6053527f82e4fbc264bea50b0e", + "v": "0x1", + "r": "0xbb14b1bf1dc47e99ba5176f0051f87a5af3ad4596bdbc982767704aae6329a4d", + "s": "0x6790cd2ad26afb01edbe78279975f60a465afc88899f258e89d9352f00a4afb", + "chainId": "0x10f2c", + "gasPrice": "0x3b9b1368", + "accessList": [] + } + ], + "executionWitness": { + "stateDiff": [ + { + "stem": "0x290378459380774194f3dd7af473757815a18a7dcb4eb6ca719dd127ccea28", + "suffixDiffs": [ + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 0 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 1 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 2 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 3 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 4 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 128 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 129 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 130 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 131 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 132 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 133 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 134 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 135 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 136 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 137 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 138 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 139 + } + ] + }, + { + "stem": "0x3560782eb707a3a378ef492c66a4c38f1e33daaf9ec700b31f356d3e72e774", + "suffixDiffs": [ + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 0 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 1 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 2 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 3 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 4 + } + ] + }, + { + "stem": "0x4d97c3dfe169c2aab9b20fa5bbb6f6e53e4560767896523f6e5a93e09297be", + "suffixDiffs": [ + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 0 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 1 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 2 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 3 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 4 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 128 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 129 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 130 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 131 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 132 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 133 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 134 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 135 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 136 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 137 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 138 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 139 + } + ] + }, + { + "stem": "0x84c05df768c23da56ace0e5bc7988d5dd032a1e2d8ea3c7145afc81bc0fba2", + "suffixDiffs": [ + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 0 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 2 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 3 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 128 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 129 + } + ] + }, + { + "stem": "0x8b900b79d7f493c4fb3a8fba13196cc0e76478a36b8674a6dfe6ddee66a9b4", + "suffixDiffs": [ + { + "currentValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x", + "suffix": 0 + }, + { + "currentValue": "0xb8ea48b767f7c48a000000000000000000000000000000000000000000000000", + "newValue": "0x", + "suffix": 1 + }, + { + "currentValue": "0x0300000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x", + "suffix": 2 + }, + { + "currentValue": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "newValue": "0x", + "suffix": 3 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 4 + } + ] + }, + { + "stem": "0xad6c8b059c0aa4becd95161a2f297e0074af3048e47e671544c520eb0c4ab8", + "suffixDiffs": [ + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 0 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 1 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 2 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 3 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 4 + } + ] + }, + { + "stem": "0xae1b106992d792cbeb5d96559894c2a8dda72c9414cfb3532325f4633047ae", + "suffixDiffs": [ + { + "currentValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newValue": "0x", + "suffix": 0 + }, + { + "currentValue": "0x525de5f1f51e4d4a201500000000000000000000000000000000000000000000", + "newValue": "0x", + "suffix": 1 + }, + { + "currentValue": "0x79793c0000000000000000000000000000000000000000000000000000000000", + "newValue": "0x", + "suffix": 2 + }, + { + "currentValue": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "newValue": "0x", + "suffix": 3 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 4 + } + ] + }, + { + "stem": "0xd68b7458f07bf329e87b81f099f9c3855d43aeeed7748d85d222b3a8d69152", + "suffixDiffs": [ + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 0 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 1 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 2 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 3 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 4 + } + ] + }, + { + "stem": "0xee9707ef2846473a6fe4e10781a3b8b225ea950a7c89fb88f01c3544a41dfb", + "suffixDiffs": [ + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 0 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 1 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 2 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 3 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 4 + } + ] + }, + { + "stem": "0xf48b4a9ad9ca0b7761b6557aa59cc184a3d14dc8b6af87741fd29e19c11111", + "suffixDiffs": [ + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 0 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 1 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 2 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 3 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 4 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 128 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 130 + }, + { + "currentValue": "0x", + "newValue": "0x", + "suffix": 131 + } + ] + } + ], + "verkleProof": { + "commitmentsByPath": [ + "0x18f21df848fbde27fbe0f8a231b4561ed8993588010b01b6e076cac910b87c42", + "0x0520fa7a1eaa72f303b4bd5edfdc58235942f3a48a88ceb669d24ddb85586f55", + "0x186e9dc2f984e5db103680adbfdd83c2f6df0376daae0384d6bdc63d3ee1383b", + "0x32a41cdc3f91731a5ff0239e98d63b7e63880dda4a2bce20abe615b8bdbb81ae", + "0x4b22c6bdd8233349c3966c44fe7322213431df9fc3e3cc6fce0c7d7fd0fb0c22", + "0x56653741afebf8e9ed40e310ba9868bf8736e50463ad8d0a9fd700f2a35a7570", + "0x3c0d513d31e51867367010464d08a84a85c975528f7aaf1f059c0f2d5a8b90ca", + "0x10dd60b1df160579af0d2667dcf6358e340aeef59ad6b00200f56ee8af850b39", + "0x2dcb916d0a9a01ba6254922ae3492284c46345e3e7e0fc94f4fc0978ba0e4b00", + "0x192f580695485d9fe38610a4d3d1af7ef4daaa5b5a512e6e9574191ccfd02670", + "0x08b9cb110253c94d40df41d56745b8767b1ddac66e3d378f04fed2b007f5db7b", + "0x1cfb1a085e241a26fefbcd19e5c8fa14a5abe38eff6d78a7671475e74c900ec8", + "0x63be1f65657faa7d706b908d3b3b3674f5d8d858b790480dd8a4d9c2ce9369fc", + "0x08652f5969f0d7f893dea8a247dbc70bcc10a54ad86684cd9f15288b056d5e96", + "0x2758d93b5d57c8bb8985b8245ebc4b9f8c3dd1e376119a1a99416cd16c4d459c", + "0x38af2cefe233d1f2c0a8d116fafa67725c9201d65e3a5b7b6e2c615c13a5eec7", + "0x0c3dec1d8094db18271c95c0292877dfe14076d5bd965b7da4b090f8e0c3cf26", + "0x2ab4e41a5e97902d093bd194d7e9fb15d7b6866d083cc2cde9b1e60235d3e759", + "0x1ea2625ea1d3b62c540749ebcb1daa2eefda6478d1958c067e8d65bf473a15e5", + "0x30a3c5b308656a1ff8fd9cb982cdcd7050a477459d33da41e312615af4028569", + "0x073afcac9107622d7e81726ef59c8e30f7c0228724ab6ca437d34ad7dd89169d", + "0x5ff714b854edbf2e5eb9f994ca2ca4ff30fdef76d62091c9920463487c91fe0c", + "0x4deb8879de6ddbc6c99dd321e1b26b70fbdb2fe080d8244a2b9e1ddb63ae4fcf", + "0x2644e2ebafd0c4b847fe534f833d79899e9dbaedb3e7b0715326ac3f8de5a2ef", + "0x09eb0175311484f786ba1e12f5dd80823fb9bb806de46cac8f10b72b91019b75" + ], + "d": "0x06110992b049b61a7543a1a388a08b7aa967580266b12b1880dfd8b8aa1e2aa3", + "depthExtensionPresent": "0x181818181a181a181819", + "ipaProof": { + "cl": [ + "0x7201d3474df7071d5b08628720df125d3c576b7310a99a67e57c5d364f442aed", + "0x5eb72934160412aba09e9f28d911577942c171cf0921c016eb7887aa8ae0ce05", + "0x69a486db0afb403ea7c64d00bdde39e53112a41fa48fdc1403a392f12a5dc02c", + "0x461f0f169a348da80089c2f59d99a2a372de7be4f9b80c734d87b951b51ef39c", + "0x66a53133a17a72f39492d3430fb8b476bbe3c56fbfe59c44bdfca4a9a3a5e99c", + "0x497cc3587d1994f6ae21b2e7ffd97f5505c9aaaa9c6288267dc8e1c326b8118a", + "0x1cb46f70017c2f54571b8620e237cb3b94b41e37894c29a3fcb1685ffcd56083", + "0x5a249d17a2257c122743ec27afbb7624e52819c6ef6c6d081d4c023012931381" + ], + "cr": [ + "0x1be4988b202837e86a2e3ba61ba5fc62e4bb36bebad554193df623270ef0c9fd", + "0x2120506addcff94106a227c0ba2812cbc21f7003fac2643d4ec2b1ed8a9df858", + "0x6a0a5aa53dbf13b873669715f5a8245d76dc41bfb6c9a002347ece4cc8aea838", + "0x0f2558cd2bdd186be9d721a24679f1d92c599abdf25ac4b1294df2f090be3091", + "0x0a3a12eebd6234289697b747d242fa4ea769802c5a28c739534324f070fb7102", + "0x5984c0dd556fca9e7e7335eb03670ca08787292b0eb9de624ce88f421d531f8e", + "0x47f7f6d5b603026777d3f57fa1657ba257df66adf890ea4d5da454b44816ebc7", + "0x23d9bd0146baffdef1fac45f9b573596a15f72ae0f84aa2b82689ea2a6c95f2a" + ], + "finalEvaluation": "0x0fb5674a2d8693294a5cfc0f95ae7ce5a6c4112255dc7a25afd76446863612b1" + }, + "otherStems": ["0xf48b4afcf49fabd63c9ea130cd708c6f1a1c2cfd8329c9265395a00f670658"] + } + } +} diff --git a/packages/statemanager/tsconfig.prod.cjs.json b/packages/statemanager/tsconfig.prod.cjs.json index e314b6daea..1310ffb7a9 100644 --- a/packages/statemanager/tsconfig.prod.cjs.json +++ b/packages/statemanager/tsconfig.prod.cjs.json @@ -9,6 +9,7 @@ "references": [ { "path": "../common/tsconfig.prod.cjs.json" }, { "path": "../trie/tsconfig.prod.cjs.json" }, - { "path": "../util/tsconfig.prod.cjs.json" } + { "path": "../util/tsconfig.prod.cjs.json" }, + { "path": "../verkle/tsconfig.prod.cjs.json" } ] } diff --git a/packages/statemanager/tsconfig.prod.esm.json b/packages/statemanager/tsconfig.prod.esm.json index 2a65463a73..e43dc97915 100644 --- a/packages/statemanager/tsconfig.prod.esm.json +++ b/packages/statemanager/tsconfig.prod.esm.json @@ -9,6 +9,7 @@ "references": [ { "path": "../common/tsconfig.prod.esm.json" }, { "path": "../trie/tsconfig.prod.esm.json" }, - { "path": "../util/tsconfig.prod.esm.json" } + { "path": "../util/tsconfig.prod.esm.json" }, + { "path": "../verkle/tsconfig.prod.esm.json" } ] } diff --git a/packages/statemanager/vitest.config.browser.ts b/packages/statemanager/vitest.config.browser.ts index d5531f5613..da0e9a04bc 100644 --- a/packages/statemanager/vitest.config.browser.ts +++ b/packages/statemanager/vitest.config.browser.ts @@ -7,6 +7,8 @@ export default defineConfig({ test: { exclude: [ ...configDefaults.exclude, + // Importing pedersenHash through wasm failed. + 'test/statelessVerkleStateManager.spec.ts', // Importing a module script failed. 'test/rpcStateManager.spec.ts', // undefined is not an object (evaluating 'state.reading') diff --git a/packages/util/src/bytes.ts b/packages/util/src/bytes.ts index 83761b9f31..534bc37b52 100644 --- a/packages/util/src/bytes.ts +++ b/packages/util/src/bytes.ts @@ -52,7 +52,10 @@ for (let i = 0; i <= 256 * 256 - 1; i++) { * @param {Uint8Array} bytes the bytes to convert * @returns {bigint} */ -export const bytesToBigInt = (bytes: Uint8Array): bigint => { +export const bytesToBigInt = (bytes: Uint8Array, littleEndian = false): bigint => { + if (littleEndian) { + bytes.reverse() + } const hex = bytesToHex(bytes) if (hex === '0x') { return BIGINT_0 @@ -132,9 +135,11 @@ export const intToBytes = (i: number): Uint8Array => { * * @param {bigint} num the bigint to convert * @returns {Uint8Array} */ -export const bigIntToBytes = (num: bigint): Uint8Array => { +export const bigIntToBytes = (num: bigint, littleEndian = false): Uint8Array => { // eslint-disable-next-line @typescript-eslint/no-use-before-define - return toBytes('0x' + padToEven(num.toString(16))) + const bytes = toBytes('0x' + padToEven(num.toString(16))) + + return littleEndian ? bytes.reverse() : bytes } /** diff --git a/packages/verkle/src/util/crypto.ts b/packages/verkle/src/util/crypto.ts index ab32c4ba5c..a2b6ce31e0 100644 --- a/packages/verkle/src/util/crypto.ts +++ b/packages/verkle/src/util/crypto.ts @@ -1,31 +1,48 @@ -import { type Address, concatBytes, int32ToBytes, setLengthLeft } from '@ethereumjs/util' +import { + type Address, + bytesToHex, + concatBytes, + int32ToBytes, + setLengthLeft, + setLengthRight, +} from '@ethereumjs/util' import { pedersen_hash, verify_update } from 'rust-verkle-wasm' -import type { Point } from '../types' +import type { Point } from '../types.js' export function pedersenHash(input: Uint8Array): Uint8Array { const pedersenHash = pedersen_hash(input) if (pedersenHash === null) { throw new Error( - 'pedersenHash: Wrong pedersenHash input. This might happen if length is not correct.' + `pedersenHash: Wrong pedersenHash input: ${bytesToHex( + input + )}. This might happen if length is not correct.` ) } return pedersenHash } +export function verifyUpdate( + root: Uint8Array, + proof: Uint8Array, + keyValues: Map +): Uint8Array { + return verify_update(root, proof, keyValues) +} + /** * @dev Returns the 31-bytes verkle tree stem for a given address and tree index. * @dev Assumes that the verkle node width = 256 * @param address The address to generate the tree key for. - * @param treeIndex The index of the tree to generate the key for. + * @param treeIndex The index of the tree to generate the key for. Defaults to 0. * @return The 31-bytes verkle tree stem as a Uint8Array. */ -export function getStem(address: Address, treeIndex: number): Uint8Array { +export function getStem(address: Address, treeIndex: number = 0): Uint8Array { const address32 = setLengthLeft(address.toBytes(), 32) - const treeIndexBytes = int32ToBytes(treeIndex, true) + const treeIndexBytes = setLengthRight(int32ToBytes(treeIndex, true), 32) const input = concatBytes(address32, treeIndexBytes) @@ -38,12 +55,12 @@ export function getStem(address: Address, treeIndex: number): Uint8Array { * @dev Returns the tree key for a given verkle tree stem, and sub index. * @dev Assumes that the verkle node width = 256 * @param stem The 31-bytes verkle tree stem as a Uint8Array. - * @param subIndex The sub index of the tree to generate the key for. + * @param subIndex The sub index of the tree to generate the key for as a Uint8Array. * @return The tree key as a Uint8Array. */ + export function getKey(stem: Uint8Array, subIndex: Uint8Array): Uint8Array { const treeKey = concatBytes(stem, subIndex) - return treeKey } diff --git a/packages/verkle/src/verkleTree.ts b/packages/verkle/src/verkleTree.ts index 3c6ac9fba6..b756262f6a 100644 --- a/packages/verkle/src/verkleTree.ts +++ b/packages/verkle/src/verkleTree.ts @@ -1,14 +1,5 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ -import { - KeyEncoding, - Lock, - MapDB, - ValueEncoding, - bytesToHex, - equalsBytes, - hexToBytes, - zeros, -} from '@ethereumjs/util' +import { KeyEncoding, Lock, ValueEncoding, equalsBytes, zeros } from '@ethereumjs/util' import { CheckpointDB } from './db/checkpoint.js' import { InternalNode } from './node/internalNode.js' @@ -23,7 +14,7 @@ import { import { WalkController, matchingBytesLength } from './util/index.js' import type { VerkleNode } from './node/types.js' -import type { FoundNodeFunction, Point } from './types.js' +import type { FoundNodeFunction } from './types.js' import type { BatchDBOp, DB, PutBatch } from '@ethereumjs/util' interface Path { diff --git a/packages/verkle/test/crypto.spec.ts b/packages/verkle/test/crypto.spec.ts new file mode 100644 index 0000000000..b1448edac2 --- /dev/null +++ b/packages/verkle/test/crypto.spec.ts @@ -0,0 +1,20 @@ +import { Address, bytesToHex } from '@ethereumjs/util' +import { assert, describe, it } from 'vitest' + +import { getStem } from '../src/index.js' + +describe('Verkle cryptographic helpers', () => { + it('getStem(): returns the expected stems', async () => { + // Empty address + assert.equal( + bytesToHex(getStem(Address.fromString('0x0000000000000000000000000000000000000000'))), + '0xbf101a6e1c8e83c11bd203a582c7981b91097ec55cbd344ce09005c1f26d19' + ) + + // Non-empty address + assert.equal( + bytesToHex(getStem(Address.fromString('0x71562b71999873DB5b286dF957af199Ec94617f7'))), + '0x274cde18dd9dbb04caf16ad5ee969c19fe6ca764d5688b5e1d419f4ac6cd16' + ) + }) +}) diff --git a/packages/verkle/test/node/internalNode.spec.ts b/packages/verkle/test/internalNode.spec.ts similarity index 87% rename from packages/verkle/test/node/internalNode.spec.ts rename to packages/verkle/test/internalNode.spec.ts index f27b375a86..9a538e5044 100644 --- a/packages/verkle/test/node/internalNode.spec.ts +++ b/packages/verkle/test/internalNode.spec.ts @@ -1,11 +1,11 @@ import { equalsBytes, randomBytes } from '@ethereumjs/util' import { assert, describe, it } from 'vitest' -import { NODE_WIDTH, VerkleNodeType } from '../../src/node/index.js' -import { InternalNode } from '../../src/node/internalNode.js' -import { POINT_IDENTITY } from '../../src/util/crypto.js' +import { NODE_WIDTH, VerkleNodeType } from '../src/node/index.js' +import { InternalNode } from '../src/node/internalNode.js' +import { POINT_IDENTITY } from '../src/util/crypto.js' -import type { Point } from '../../src/types.js' +import type { Point } from '../src/types.js' describe('verkle node - internal', () => { it('constructor should create an internal node', async () => { diff --git a/packages/verkle/test/node/leafNode.spec.ts b/packages/verkle/test/leafNode.spec.ts similarity index 89% rename from packages/verkle/test/node/leafNode.spec.ts rename to packages/verkle/test/leafNode.spec.ts index 251c4cc6c3..c405c78ee1 100644 --- a/packages/verkle/test/node/leafNode.spec.ts +++ b/packages/verkle/test/leafNode.spec.ts @@ -1,10 +1,10 @@ import { equalsBytes, randomBytes } from '@ethereumjs/util' import { assert, describe, it } from 'vitest' -import { VerkleNodeType } from '../../src/node/index.js' -import { LeafNode } from '../../src/node/leafNode.js' +import { VerkleNodeType } from '../src/node/index.js' +import { LeafNode } from '../src/node/leafNode.js' -import type { Point } from '../../src/types.js' +import type { Point } from '../src/types.js' describe('verkle node - leaf', () => { it('constructor should create an leaf node', async () => { diff --git a/packages/vm/src/runBlock.ts b/packages/vm/src/runBlock.ts index 9db284bb86..19c40e4078 100644 --- a/packages/vm/src/runBlock.ts +++ b/packages/vm/src/runBlock.ts @@ -1,6 +1,7 @@ import { Block } from '@ethereumjs/block' import { ConsensusType, Hardfork } from '@ethereumjs/common' import { RLP } from '@ethereumjs/rlp' +import { StatelessVerkleStateManager } from '@ethereumjs/statemanager' import { Trie } from '@ethereumjs/trie' import { TransactionType } from '@ethereumjs/tx' import { @@ -60,6 +61,7 @@ export async function runBlock(this: VM, opts: RunBlockOpts): Promise> + try { result = await applyBlock.bind(this)(block, opts) if (this.DEBUG) { @@ -183,7 +203,8 @@ export async function runBlock(this: VM, opts: RunBlockOpts): Promise { const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Berlin }) // Block - const block: Omit, 'withdrawals'> = Block.fromBlockData({}, { common }) + const block: Omit< + Required, + 'withdrawals' | 'executionWitness' + > = Block.fromBlockData({}, { common }) assert.ok(block, 'block') // Transactions