-
Notifications
You must be signed in to change notification settings - Fork 791
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
statemanager: cache and other refactors #3569
Changes from 1 commit
fa3c2ec
bd1f237
d5aaf30
533fa8c
31c94af
bba928b
a04158d
2431594
814b9f7
2439219
4c6240f
5e1666d
c754eac
5d4895c
888b20e
905a52e
f30288a
ba00837
c037ae2
fdcdb36
3d93587
48baee3
f0b66bf
5f4c253
7fe21fd
4864383
b6ee97b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Unchanged files with check annotations Beta
) | ||
const vmCopy = await vm.shallowCopy() | ||
assert.isUndefined( | ||
Check failure on line 22 in packages/vm/test/api/copy.spec.ts
|
||
await vmCopy.stateManager.getAccount(address), | ||
'non-committed checkpoints will not be copied', | ||
) |
const storage = genesisState[contractAddress][2] | ||
// Returned value should be 4, because we are trying to trigger the method `retrieve` | ||
// in the contract, which returns the variable stored in slot 0x00..00 | ||
assert.equal(bytesToHex(callResult.execResult.returnValue), storage[0][1]) | ||
Check failure on line 116 in packages/vm/test/api/customChain.spec.ts
|
||
}) | ||
it('setHardfork', async () => { |
resultNotActivated.execResult.executionGasUsed - resultActivated.execResult.executionGasUsed | ||
const expected = common.param('callNewAccountGas') | ||
assert.equal(diff, expected, 'precompiles are activated') | ||
Check failure on line 335 in packages/vm/test/api/index.spec.ts
|
||
}) | ||
}) | ||
}) |
await runBlock(vm, { block, skipBlockValidation: true, generate: true }) | ||
const storage = await vm.stateManager.getStorage(defaultAuthAddr, zeros(32)) | ||
assert.ok(equalsBytes(storage, new Uint8Array([2]))) | ||
Check failure on line 677 in packages/vm/test/api/runBlock.spec.ts
|
||
}) | ||
}) |
await runTx(vm, { tx, skipHardForkValidation: true }) | ||
const hash = await vm.stateManager.getStorage(codeAddr, zeros(32)) | ||
assert.deepEqual(hash, KECCAK256_NULL, 'hash ok') | ||
Check failure on line 790 in packages/vm/test/api/runTx.spec.ts
|
||
}) | ||
it('Validate CALL does not charge new account gas when calling CALLER and caller is non-empty', async () => { | ||
const acc = await vm.stateManager.getAccount(addr) | ||
acc!.balance = BigInt(tx.gasLimit * tx.gasPrice + tx.value) | ||
await vm.stateManager.putAccount(addr, acc!) | ||
assert.equal( | ||
Check failure on line 821 in packages/vm/test/api/runTx.spec.ts
|
||
(await runTx(vm, { tx, skipHardForkValidation: true })).totalGasSpent, | ||
BigInt(27818), | ||
'did not charge callNewAccount', | ||
const acc = await vm.stateManager.getAccount(addr) | ||
acc!.balance = BigInt(tx.gasLimit * tx.gasPrice + tx.value) | ||
await vm.stateManager.putAccount(addr, acc!) | ||
assert.equal( | ||
Check failure on line 852 in packages/vm/test/api/runTx.spec.ts
|
||
(await runTx(vm, { tx, skipHardForkValidation: true })).totalGasSpent, | ||
BigInt(13001), | ||
'did not charge callNewAccount', |
} | ||
const result = await runTest(test) | ||
assert.deepEqual(returndata, result[0].execResult.returnValue) | ||
Check failure on line 101 in packages/vm/test/api/EIPs/eip-1153.spec.ts
|
||
assert.equal(undefined, result[0].execResult.exceptionError) | ||
}) | ||
} | ||
const [result] = await runTest(test) | ||
assert.equal(bytesToInt(result.execResult.returnValue), 0xaa) | ||
Check failure on line 661 in packages/vm/test/api/EIPs/eip-1153.spec.ts
|
||
}) | ||
}) |
assert.equal(res.execResult.executionGasUsed, BigInt(testCase.used)) | ||
assert.equal(res.execResult.gasRefund, BigInt(testCase.refund)) | ||
} catch (e: any) { | ||
assert.fail(e.message) | ||
Check failure on line 62 in packages/vm/test/api/EIPs/eip-1283-net-gas-metering.spec.ts
|
||
} | ||
} | ||
}) |
if (account !== undefined) { | ||
this._caches.account!.put(address, account) | ||
} else { | ||
this._caches.account!.del(address) | ||
} | ||
} | ||
} | ||
this._debug(`Delete account ${address}`) | ||
} | ||
this._caches?.deleteAccount(address) | ||
if (this._caches === undefined || this._caches.settings.account.deactivate === true) { | ||
await this._trie.del(address.bytes) | ||
} | ||
} |
debug(`putCode address=${address.toString()} value=${short(value)}`) | ||
} | ||
this._caches?.code?.put(address, value) | ||
const codeHash = keccak256(value) | ||
if (KECCAK256_NULL === codeHash) { | ||
// If the code hash is the null hash, no code has to be stored | ||
debug(`getCode address=${address.toString()}`) | ||
} | ||
if (this._caches !== undefined && !this._caches.settings.code.deactivate) { | ||
const elem = this._caches.code?.get(address) | ||
if (elem !== undefined) { | ||
return elem.code ?? new Uint8Array(0) | ||
} | ||
// Return accessedCode where only accessed code has been copied | ||
const contactCode = accessedCode.slice(0, codeSize) | ||
if (this._caches !== undefined && !this._caches.settings.code.deactivate) { | ||
this._caches.code?.put(address, contactCode) | ||
} | ||
return contactCode | ||
} | ||
async getCodeSize(address: Address): Promise<number> { | ||
if (this._caches !== undefined && !this._caches.settings.account.deactivate) { | ||
const elem = this._caches.account!.get(address) | ||
if (elem !== undefined) { | ||
const account = | ||
elem.accountRLP !== undefined ? createPartialAccountFromRLP(elem.accountRLP) : undefined | ||
* If this does not exist an empty `Uint8Array` is returned. | ||
*/ | ||
async getStorage(address: Address, key: Uint8Array): Promise<Uint8Array> { | ||
if (this._caches !== undefined && !this._caches.settings.storage.deactivate) { | ||
const value = this._caches.storage!.get(address, key) | ||
if (value !== undefined) { | ||
return value | ||
} | ||
) | ||
const storageValue = toBytes(this._state[bytesToHex(storageKey)]) | ||
if (this._caches !== undefined && !this._caches.settings.storage.deactivate) { | ||
this._caches.storage?.put(address, key, storageValue ?? hexToBytes('0x80')) | ||
} | ||
return storageValue | ||
* @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 putStorage(address: Address, key: Uint8Array, value: Uint8Array): Promise<void> { | ||
if (this._caches !== undefined && !this._caches.settings.storage.deactivate) { | ||
this._caches.storage!.put(address, key, value) | ||
} else { | ||
// TODO: Consider refactoring this in a writeContractStorage function? Like in stateManager.ts | ||
const storageKey = await getVerkleTreeKeyForStorageSlot( | ||
async clearStorage(address: Address): Promise<void> { | ||
const stem = getVerkleStem(this.verkleCrypto, address, 0) | ||
const codeHashKey = getVerkleKey(stem, VerkleLeafType.CodeHash) | ||
this._caches?.storage?.clearStorage(address) | ||
// Update codeHash to `c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470` | ||
this._state[bytesToHex(codeHashKey)] = KECCAK256_NULL_S | ||
} | ||
} | ||
if (this._caches !== undefined && !this._caches.settings.account.deactivate) { | ||
this._caches.account?.put(address, account, true) | ||
} | ||
return account | ||
if (account !== undefined) { | ||
this._caches?.account?.put(address, account, true) | ||
} else { | ||
this._caches?.account?.del(address) | ||
} | ||
} | ||
} | ||
const { address, type } = accessedState | ||
switch (type) { | ||
case AccessedStateType.Version: { | ||
const encodedAccount = this._caches?.account?.get(address)?.accountRLP | ||
if (encodedAccount === undefined) { | ||
return null | ||
} | ||
return ZEROVALUE | ||
} | ||
case AccessedStateType.Balance: { | ||
const encodedAccount = this._caches?.account?.get(address)?.accountRLP | ||
if (encodedAccount === undefined) { | ||
return null | ||
} | ||
} | ||
case AccessedStateType.Nonce: { | ||
const encodedAccount = this._caches?.account?.get(address)?.accountRLP | ||
if (encodedAccount === undefined) { | ||
return null | ||
} | ||
} | ||
case AccessedStateType.CodeHash: { | ||
const encodedAccount = this._caches?.account?.get(address)?.accountRLP | ||
if (encodedAccount === undefined) { | ||
return null | ||
} | ||
} | ||
case AccessedStateType.CodeSize: { | ||
const codeSize = this._caches?.code?.get(address)?.code?.length | ||
if (codeSize === undefined) { | ||
// it could be an EOA lets check for that | ||
const encodedAccount = this._caches?.account?.get(address)?.accountRLP | ||
if (encodedAccount === undefined) { | ||
return null | ||
} | ||
case AccessedStateType.Code: { | ||
const { codeOffset } = accessedState | ||
const code = this._caches?.code?.get(address)?.code | ||
if (code === undefined) { | ||
return null | ||
} | ||
const { slot } = accessedState | ||
const key = setLengthLeft(bigIntToBytes(slot), 32) | ||
const storage = this._caches?.storage?.get(address, key) | ||
if (storage === undefined) { | ||
return null | ||
} | ||
*/ | ||
async checkpoint(): Promise<void> { | ||
this._checkpoints.push(this._state) | ||
this._caches?.checkpoint() | ||
} | ||
/** | ||
*/ | ||
async commit(): Promise<void> { | ||
this._checkpoints.pop() | ||
this._caches?.commit() | ||
} | ||
// TODO | ||
async revert(): Promise<void> { | ||
// setup trie checkpointing | ||
this._checkpoints.pop() | ||
this._caches?.revert() | ||
} | ||
/** | ||
* Clears all underlying caches | ||
*/ | ||
clearCaches() { | ||
this._caches?.clear() | ||
} | ||
// TODO: Removing this causes a Kaustinen6 test in client to fail |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can fully drop the
CacheOpts
from this key, makes it nicer to digest/read and remains fully expressive.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(same for others of course)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done!