Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✅ Test: MOre stateManager test coverage #1299

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

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

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

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

2 changes: 1 addition & 1 deletion packages/state/docs/functions/commit.md

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

2 changes: 1 addition & 1 deletion packages/state/docs/functions/getContractStorage.md

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

2 changes: 1 addition & 1 deletion packages/state/docs/functions/putContractStorage.md

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

32 changes: 32 additions & 0 deletions packages/state/src/actions/__snapshots__/commit.spec.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP

exports[`commit should clear all storage entries for the account corresponding to `address` 1`] = `
[

Map {
"0000000000000000000000000000000004277dc9" => undefined,
}
,
Map {},
]
`;

exports[`commit should clear all storage entries for the account corresponding to `address` 2`] = `
[

Map {
"0000000000000000000000000000000004277dc9" => undefined,
}
,
Map {},
]
`;

exports[`commit should clear all storage entries for the account corresponding to `address` 3`] = `
[
Map {},
Map {},
]
`;

exports[`commit should clear all storage entries for the account corresponding to `address` 4`] = `"0x886f43e0144bf4f5748e999d0178ed7e4edea8ad708e0bf26a61341e8ae91d1e"`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP

exports[`deepCopy should throw if uncommitted state 1`] = `[InternalError: Attempted to deepCopy state with uncommitted checkpoints

Docs: https://tevm.sh/reference/tevm/errors/classes/internalerror/
Version: 1.1.0.next-73]`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP

exports[`generateCanonicalGenesis should successfully generate canonical genesis 1`] = `{}`;

exports[`generateCanonicalGenesis should throw if there are uncommitted checkpoints 1`] = `[InternalError: Attempted to generateCanonicalGenesis state with uncommitted checkpoints

Docs: https://tevm.sh/reference/tevm/errors/classes/internalerror/
Version: 1.1.0.next-73]`;
159 changes: 159 additions & 0 deletions packages/state/src/actions/__snapshots__/getAccount.spec.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP

exports[`getAccount forking Should fetch account from remote provider if not in cache and fork transport is provided 1`] = `
Account {
"balance": 121136012589291788664n,
"codeHash": Uint8Array [
197,
210,
70,
1,
134,
247,
35,
60,
146,
126,
125,
178,
220,
199,
3,
192,
229,
0,
182,
83,
202,
130,
39,
59,
123,
250,
216,
4,
93,
133,
164,
112,
],
"nonce": 654430n,
"storageRoot": Uint8Array [
86,
232,
31,
23,
27,
204,
85,
166,
255,
131,
69,
230,
146,
192,
248,
110,
91,
72,
224,
27,
153,
108,
173,
192,
1,
98,
47,
181,
227,
99,
180,
33,
],
}
`;

exports[`getAccount forking Should fetch account from remote provider if not in cache and fork transport is provided 2`] = `
Account {
"balance": 121136012589291788664n,
"codeHash": Uint8Array [
197,
210,
70,
1,
134,
247,
35,
60,
146,
126,
125,
178,
220,
199,
3,
192,
229,
0,
182,
83,
202,
130,
39,
59,
123,
250,
216,
4,
93,
133,
164,
112,
],
"nonce": 654430n,
"storageRoot": Uint8Array [
86,
232,
31,
23,
27,
204,
85,
166,
255,
131,
69,
230,
146,
192,
248,
110,
91,
72,
224,
27,
153,
108,
173,
192,
1,
98,
47,
181,
227,
99,
180,
33,
],
}
`;

exports[`getAccount forking Should return undefined and cache as undefined for empty remote account 1`] = `
{
"accountRLP": undefined,
}
`;

exports[`getAccount forking Should return undefined and cache as undefined for empty remote account 2`] = `{}`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP

exports[`getContractStorage should throw an error if the key is not 32 bytes long 1`] = `
"Storage key must be 32 bytes long. Received 2. If using numberToHex make the length 32.

Docs: https://tevm.sh/reference/tevm/errors/classes/internalerror/
Version: 1.1.0.next-73"
`;

exports[`getContractStorage forking should fetch storage from remote provider if not in cache and fork transport is provided 1`] = `
Uint8Array [
0,
]
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP

exports[`putContractStorage should throw an error if the key is not 32 bytes long 1`] = `[InternalError: Storage key must be 32 bytes long. Received 18,52

Docs: https://tevm.sh/reference/tevm/errors/classes/internalerror/
Version: 1.1.0.next-73]`;

exports[`putContractStorage should throw an error if the account does not exist 1`] = `[InternalError: cannot putContractStorage on non existing acccount! Consider checking if account exists first

Docs: https://tevm.sh/reference/tevm/errors/classes/internalerror/
Version: 1.1.0.next-73]`;
2 changes: 0 additions & 2 deletions packages/state/src/actions/commit.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { keccak256, numberToHex, toHex } from 'viem'
import { dumpCanonicalGenesis } from './dumpCannonicalGenesis.js'

// TODO we might want to sometimes prune state roots

/**
* Commits the current change-set to the instance since the
* last call to checkpoint.
Expand Down
92 changes: 85 additions & 7 deletions packages/state/src/actions/commit.spec.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,105 @@
import { describe, expect, it } from 'bun:test'
import { beforeEach, describe, expect, it, jest } from 'bun:test'
import { createAddress } from '@tevm/address'
import { EthjsAccount } from '@tevm/utils'
import { createBaseState } from '../createBaseState.js'
import { checkpoint } from './checkpoint.js'
import { commit } from './commit.js'
import { putAccount } from './putAccount.js'

describe(commit.name, () => {
it('should clear all storage entries for the account corresponding to `address`', async () => {
// No mocks
const baseState = createBaseState({
loggingLevel: 'warn',
})
await putAccount(baseState)(createAddress(69696969), EthjsAccount.fromAccountData({ balance: 20n }))
expect(baseState.caches.storage._checkpoints).toBe(0)
expect(baseState.caches.accounts._checkpoints).toBe(0)
expect(baseState.caches.contracts._checkpoints).toBe(0)
await checkpoint(baseState)()
expect(baseState.caches.storage._checkpoints).toBe(1)
expect(baseState.caches.accounts._checkpoints).toBe(1)
expect(baseState.caches.contracts._checkpoints).toBe(1)
expect(baseState.caches.accounts._diffCache).toEqual([new Map(), new Map()])
expect(baseState.caches.accounts._diffCache).toEqual([
new Map(
Object.entries({
'0000000000000000000000000000000004277dc9': undefined,
}),
),
new Map(),
])
expect(baseState.caches.storage._diffCache).toEqual([new Map(), new Map()])
await commit(baseState)(true)
expect(baseState.caches.storage._checkpoints).toBe(1)
expect(baseState.caches.accounts._checkpoints).toBe(1)
expect(baseState.caches.contracts._checkpoints).toBe(1)
expect(baseState.caches.accounts._diffCache).toEqual([
new Map(
Object.entries({
'0000000000000000000000000000000004277dc9': undefined,
}),
),
new Map(),
])
expect(baseState.caches.storage._diffCache).toEqual([new Map(), new Map()])
expect(baseState.getCurrentStateRoot()).toEqual(
'0x886f43e0144bf4f5748e999d0178ed7e4edea8ad708e0bf26a61341e8ae91d1e',
)
})

let baseState: ReturnType<typeof createBaseState>

beforeEach(() => {
baseState = createBaseState({
loggingLevel: 'warn',
})
baseState.getCurrentStateRoot = jest.fn(() => 'existingStateRoot') as any
baseState.setCurrentStateRoot = jest.fn()
baseState.logger.debug = jest.fn()
baseState.options.onCommit = jest.fn()
baseState.stateRoots.set = jest.fn()
baseState.caches.accounts.commit = jest.fn()
baseState.caches.contracts.commit = jest.fn()
baseState.caches.storage.commit = jest.fn()
})

it('should commit to existing state root', async () => {
await checkpoint(baseState)()
await commit(baseState)()
expect(baseState.caches.storage._checkpoints).toBe(0)
expect(baseState.caches.accounts._checkpoints).toBe(0)
expect(baseState.caches.contracts._checkpoints).toBe(0)
expect(baseState.caches.accounts._diffCache).toEqual([new Map()])
expect(baseState.caches.storage._diffCache).toEqual([new Map()])

expect(baseState.getCurrentStateRoot).toHaveBeenCalled()
expect(baseState.setCurrentStateRoot).toHaveBeenCalledWith('existingStateRoot')
expect(baseState.logger.debug).toHaveBeenCalledWith('Comitting to existing state root...')
expect(baseState.stateRoots.set).toHaveBeenCalledWith('existingStateRoot', expect.any(Object))
expect(baseState.caches.accounts.commit).toHaveBeenCalled()
expect(baseState.caches.contracts.commit).toHaveBeenCalled()
expect(baseState.caches.storage.commit).toHaveBeenCalled()
expect(baseState.options.onCommit).toHaveBeenCalledWith(baseState)
})

it('should commit to a new state root', async () => {
await checkpoint(baseState)()
await commit(baseState)(true)

expect(baseState.setCurrentStateRoot).toHaveBeenCalledWith(expect.any(String))
expect(baseState.logger.debug).toHaveBeenCalledWith(
expect.objectContaining({ root: expect.any(String) }),
'Committing to new state root...',
)
expect(baseState.stateRoots.set).toHaveBeenCalledWith(expect.any(String), expect.any(Object))
expect(baseState.caches.accounts.commit).toHaveBeenCalled()
expect(baseState.caches.contracts.commit).toHaveBeenCalled()
expect(baseState.caches.storage.commit).toHaveBeenCalled()
expect(baseState.options.onCommit).toHaveBeenCalledWith(baseState)
})

it('should handle onCommit callback correctly', async () => {
const onCommitMock = jest.fn()
baseState.options.onCommit = onCommitMock

await checkpoint(baseState)()
await commit(baseState)()

expect(onCommitMock).toHaveBeenCalledWith(baseState)
})
})
Loading
Loading