Skip to content

Commit

Permalink
Statemanager proof function tree shake (#3672)
Browse files Browse the repository at this point in the history
* Move proof functions from Merkle sm over to being standalone functions

* Remove unneeded parameter from fromMerkleStateProof

* Export merkle sm proof functions

* Refactor tests to use new standalone sm proof functions

* stateManager: Fix linting issues

* Make debugger a class field

* Move proof functions from verkle sm over to being standalone functions

* Remove getProof and verifyProof for the stateless verkle sm

* Remove unused accountExists function on RPCSm

* Remove accountExists function on RPCStateeManager

* Move getProof function of RPCStateManager over to being standalone

* Export proof functions from statemanager package

* Fix test

* Fix and reembed example

* Fix getProof rpc method by checking which proof function to use for given sm

* Remove getProof and verifyProof from sm interface and fix errors

* Fix linting issues

* Fix lint issue

---------

Co-authored-by: Holger Drewes <Holger.Drewes@gmail.com>
  • Loading branch information
scorbajio and holgerd77 authored Sep 17, 2024
1 parent 766bd8f commit d7a9ff2
Show file tree
Hide file tree
Showing 17 changed files with 454 additions and 385 deletions.
19 changes: 15 additions & 4 deletions packages/client/src/rpc/modules/eth.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { createBlock } from '@ethereumjs/block'
import { Hardfork } from '@ethereumjs/common'
import {
MerkleStateManager,
StatelessVerkleStateManager,
getMerkleStateProof,
getVerkleStateProof,
} from '@ethereumjs/statemanager'
import {
Capability,
createBlob4844TxFromSerializedNetworkWrapper,
Expand Down Expand Up @@ -1246,14 +1252,19 @@ export class Eth {

const vm = await this._vm.shallowCopy()

if (!('getProof' in vm.stateManager)) {
throw new Error('getProof RPC method not supported with the StateManager provided')
}
await vm.stateManager.setStateRoot(block.header.stateRoot)

const address = createAddressFromString(addressHex)
const slots = slotsHex.map((slotHex) => setLengthLeft(hexToBytes(slotHex), 32))
const proof = await vm.stateManager.getProof!(address, slots)
let proof: Proof
if (vm.stateManager instanceof MerkleStateManager) {
proof = await getMerkleStateProof(vm.stateManager, address, slots)
} else if (vm.stateManager instanceof StatelessVerkleStateManager) {
proof = await getVerkleStateProof(vm.stateManager, address, slots)
} else {
throw new Error('getProof RPC method not supported with the StateManager provided')
}

for (const p of proof.storageProof) {
p.key = bigIntToHex(BigInt(p.key))
}
Expand Down
2 changes: 0 additions & 2 deletions packages/common/src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,6 @@ export interface StateManagerInterface {
* on usage (check for existence)
*/
// Client RPC
getProof?(address: Address, storageSlots: Uint8Array[]): Promise<Proof>
dumpStorage?(address: Address): Promise<StorageDump>
dumpStorageRange?(address: Address, startKey: bigint, limit: number): Promise<StorageRange>

Expand All @@ -169,7 +168,6 @@ export interface StateManagerInterface {
executionWitness?: VerkleExecutionWitness | null,
accessWitness?: AccessWitnessInterface,
): void
verifyVerkleProof?(): boolean
verifyPostState?(): boolean
checkChunkWitnessPresent?(contract: Address, programCounter: number): Promise<boolean>
getAppliedKey?(address: Uint8Array): Uint8Array // only for preimages
Expand Down
26 changes: 17 additions & 9 deletions packages/statemanager/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ It also includes a checkpoint/revert/commit mechanism to either persist or rever
```ts
// ./examples/basicUsage.ts

import { DefaultStateManager } from '@ethereumjs/statemanager'
import { MerkleStateManager } from '@ethereumjs/statemanager'
import { Account, Address, hexToBytes } from '@ethereumjs/util'

const main = async () => {
const stateManager = new DefaultStateManager()
const stateManager = new MerkleStateManager()
const address = new Address(hexToBytes('0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b'))
const account = new Account(BigInt(0), BigInt(1000))
await stateManager.checkpoint()
Expand Down Expand Up @@ -106,12 +106,17 @@ See below example for common usage:
```ts
// ./examples/fromProofInstantiation.ts

import { DefaultStateManager } from '@ethereumjs/statemanager'
import {
MerkleStateManager,
getMerkleStateProof,
fromMerkleStateProof,
addMerkleStateProofData,
} from '@ethereumjs/statemanager'
import { Address, hexToBytes } from '@ethereumjs/util'

const main = async () => {
// setup `stateManager` with some existing address
const stateManager = new DefaultStateManager()
const stateManager = new MerkleStateManager()
const contractAddress = new Address(hexToBytes('0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b'))
const byteCode = hexToBytes('0x67ffffffffffffffff600160006000fb')
const storageKey1 = hexToBytes(
Expand All @@ -127,12 +132,15 @@ const main = async () => {
await stateManager.putStorage(contractAddress, storageKey1, storageValue1)
await stateManager.putStorage(contractAddress, storageKey2, storageValue2)

const proof = await stateManager.getProof(contractAddress)
const proofWithStorage = await stateManager.getProof(contractAddress, [storageKey1, storageKey2])
const partialStateManager = await DefaultStateManager.fromProof(proof)
const proof = await getMerkleStateProof(stateManager, contractAddress)
const proofWithStorage = await getMerkleStateProof(stateManager, contractAddress, [
storageKey1,
storageKey2,
])
const partialStateManager = await fromMerkleStateProof(proof)

// To add more proof data, use `addProofData`
await partialStateManager.addProofData(proofWithStorage)
await addMerkleStateProofData(partialStateManager, proofWithStorage)
console.log(await partialStateManager.getCode(contractAddress)) // contract bytecode is not included in proof
console.log(await partialStateManager.getStorage(contractAddress, storageKey1), storageValue1) // should match
console.log(await partialStateManager.getStorage(contractAddress, storageKey2), storageValue2) // should match
Expand Down Expand Up @@ -197,7 +205,7 @@ const main = async () => {
const state = new RPCStateManager({ provider, blockTag })
const evm = await createEVM({ blockchain, stateManager: state }) // note that evm is ready to run BLOCKHASH opcodes (over RPC)
} catch (e) {
console.log(e.message) // fetch would fail because provider url is not real. please replace provider with a valid rpc url string.
console.log(e.message) // fetch would fail because provider url is not real. please replace provider with a valid RPC url string.
}
}
void main()
Expand Down
18 changes: 13 additions & 5 deletions packages/statemanager/examples/fromProofInstantiation.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { MerkleStateManager } from '@ethereumjs/statemanager'
import {
MerkleStateManager,
addMerkleStateProofData,
fromMerkleStateProof,
getMerkleStateProof,
} from '@ethereumjs/statemanager'
import { Address, hexToBytes } from '@ethereumjs/util'

const main = async () => {
Expand All @@ -19,12 +24,15 @@ const main = async () => {
await stateManager.putStorage(contractAddress, storageKey1, storageValue1)
await stateManager.putStorage(contractAddress, storageKey2, storageValue2)

const proof = await stateManager.getProof(contractAddress)
const proofWithStorage = await stateManager.getProof(contractAddress, [storageKey1, storageKey2])
const partialStateManager = await MerkleStateManager.fromProof(proof)
const proof = await getMerkleStateProof(stateManager, contractAddress)
const proofWithStorage = await getMerkleStateProof(stateManager, contractAddress, [
storageKey1,
storageKey2,
])
const partialStateManager = await fromMerkleStateProof(proof)

// To add more proof data, use `addProofData`
await partialStateManager.addProofData(proofWithStorage)
await addMerkleStateProofData(partialStateManager, proofWithStorage)
console.log(await partialStateManager.getCode(contractAddress)) // contract bytecode is not included in proof
console.log(await partialStateManager.getStorage(contractAddress, storageKey1), storageValue1) // should match
console.log(await partialStateManager.getStorage(contractAddress, storageKey2), storageValue2) // should match
Expand Down
1 change: 1 addition & 0 deletions packages/statemanager/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export * from './accessWitness.js'
export * from './cache/index.js'
export * from './merkleStateManager.js'
export * from './proofs/index.js'
export * from './rpcStateManager.js'
export * from './simpleStateManager.js'
export * from './statefulVerkleStateManager.js'
Expand Down
Loading

0 comments on commit d7a9ff2

Please sign in to comment.