Skip to content

Commit

Permalink
Merge branch 'master' into get-contract-storage-no-error-non-existing
Browse files Browse the repository at this point in the history
  • Loading branch information
jochem-brouwer committed Jul 26, 2024
2 parents acd01d3 + 91270f5 commit 07b3b8a
Show file tree
Hide file tree
Showing 59 changed files with 556 additions and 617 deletions.
4 changes: 2 additions & 2 deletions packages/client/src/rpc/modules/eth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -738,7 +738,7 @@ export class Eth {
await vm.stateManager.setStateRoot(block.header.stateRoot)

const address = Address.fromString(addressHex)
const code = await vm.stateManager.getContractCode(address)
const code = await vm.stateManager.getCode(address)
return bytesToHex(code)
}

Expand Down Expand Up @@ -780,7 +780,7 @@ export class Eth {

const address = Address.fromString(addressHex)
const key = setLengthLeft(hexToBytes(keyHex), 32)
const storage = await vm.stateManager.getContractStorage(address, key)
const storage = await vm.stateManager.getStorage(address, key)
return storage !== null && storage !== undefined
? bytesToHex(setLengthLeft(Uint8Array.from(storage) as Uint8Array, 32))
: EMPTY_SLOT
Expand Down
31 changes: 19 additions & 12 deletions packages/common/src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,31 +148,38 @@ export interface AccessWitnessInterface {
*
*/
export interface StateManagerInterface {
// Account methods
getAccount(address: Address): Promise<Account | undefined>
putAccount(address: Address, account?: Account): Promise<void>
deleteAccount(address: Address): Promise<void>
modifyAccountFields(address: Address, accountFields: AccountFields): Promise<void>
putContractCode(address: Address, value: Uint8Array): Promise<void>
getContractCode(address: Address): Promise<Uint8Array>
getContractCodeSize?(address: Address): Promise<number>
getContractStorage(address: Address, key: Uint8Array): Promise<Uint8Array>
putContractStorage(address: Address, key: Uint8Array, value: Uint8Array): Promise<void>
clearContractStorage(address: Address): Promise<void>

// Code methods
putCode(address: Address, value: Uint8Array): Promise<void>
getCode(address: Address): Promise<Uint8Array>
getCodeSize(address: Address): Promise<number>

// Storage methods
getStorage(address: Address, key: Uint8Array): Promise<Uint8Array>
putStorage(address: Address, key: Uint8Array, value: Uint8Array): Promise<void>
clearStorage(address: Address): Promise<void>

// Checkpointing methods
checkpoint(): Promise<void>
commit(): Promise<void>
revert(): Promise<void>

// State root methods
getStateRoot(): Promise<Uint8Array>
setStateRoot(stateRoot: Uint8Array, clearCache?: boolean): Promise<void>
getProof?(address: Address, storageSlots: Uint8Array[]): Promise<Proof>
hasStateRoot(root: Uint8Array): Promise<boolean> // only used in client

// Other
getProof?(address: Address, storageSlots: Uint8Array[]): Promise<Proof>
shallowCopy(downlevelCaches?: boolean): StateManagerInterface
getAppliedKey?(address: Uint8Array): Uint8Array

/*
* The following optional methods are Verkle related
*
* Experimental (do not implement)
*/
// Verkle (experimental)
checkChunkWitnessPresent?(contract: Address, programCounter: number): Promise<boolean>
}

Expand Down
17 changes: 14 additions & 3 deletions packages/evm/src/evm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,17 @@ export class EVM implements EVMInterface {
this.blockchain = opts.blockchain!
this.stateManager = opts.stateManager!

if (this.common.isActivatedEIP(6800)) {
const mandatory = ['checkChunkWitnessPresent']
for (const m of mandatory) {
if (!(m in this.stateManager)) {
throw new Error(
`State manager used must implement ${m} if Verkle (EIP-6800) is activated`,
)
}
}
}

this._bn128 = bn128
this.events = new AsyncEventEmitter()
this._optsCached = opts
Expand Down Expand Up @@ -470,7 +481,7 @@ export class EVM implements EVMInterface {
}

await this.journal.putAccount(message.to, toAccount)
await this.stateManager.clearContractStorage(message.to)
await this.stateManager.clearStorage(message.to)

const newContractEvent = {
address: message.to,
Expand Down Expand Up @@ -676,7 +687,7 @@ export class EVM implements EVMInterface {
}
}

await this.stateManager.putContractCode(message.to, result.returnValue)
await this.stateManager.putCode(message.to, result.returnValue)
if (this.DEBUG) {
debug(`Code saved on new contract creation`)
}
Expand Down Expand Up @@ -999,7 +1010,7 @@ export class EVM implements EVMInterface {
message.code = precompile
message.isCompiled = true
} else {
message.code = await this.stateManager.getContractCode(message.codeAddress)
message.code = await this.stateManager.getCode(message.codeAddress)
message.isCompiled = false
message.chargeCodeAccesses = true
}
Expand Down
4 changes: 2 additions & 2 deletions packages/evm/src/interpreter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -601,7 +601,7 @@ export class Interpreter {
* Store 256-bit a value in memory to persistent storage.
*/
async storageStore(key: Uint8Array, value: Uint8Array): Promise<void> {
await this._stateManager.putContractStorage(this._env.address, key, value)
await this._stateManager.putStorage(this._env.address, key, value)
const account = await this._stateManager.getAccount(this._env.address)
if (!account) {
throw new Error('could not read account while persisting memory')
Expand All @@ -618,7 +618,7 @@ export class Interpreter {
if (original) {
return this._stateManager.originalStorageCache.get(this._env.address, key)
} else {
return this._stateManager.getContractStorage(this._env.address, key)
return this._stateManager.getStorage(this._env.address, key)
}
}

Expand Down
28 changes: 8 additions & 20 deletions packages/evm/src/opcodes/functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -524,26 +524,16 @@ export const handlers: Map<number, OpHandler> = new Map([
const addressBigInt = runState.stack.pop()
const address = new Address(addresstoBytes(addressBigInt))
// EOF check
const code = await runState.stateManager.getContractCode(address)
const code = await runState.stateManager.getCode(address)
if (isEOF(code)) {
// In legacy code, the target code is treated as to be "EOFBYTES" code
runState.stack.push(BigInt(EOFBYTES.length))
return
}

let size
if (typeof runState.stateManager.getContractCodeSize === 'function') {
size = BigInt(
await runState.stateManager.getContractCodeSize(
new Address(addresstoBytes(addressBigInt)),
),
)
} else {
size = BigInt(
(await runState.stateManager.getContractCode(new Address(addresstoBytes(addressBigInt))))
.length,
)
}
const size = BigInt(
await runState.stateManager.getCodeSize(new Address(addresstoBytes(addressBigInt))),
)

runState.stack.push(size)
},
Expand All @@ -555,9 +545,7 @@ export const handlers: Map<number, OpHandler> = new Map([
const [addressBigInt, memOffset, codeOffset, dataLength] = runState.stack.popN(4)

if (dataLength !== BIGINT_0) {
let code = await runState.stateManager.getContractCode(
new Address(addresstoBytes(addressBigInt)),
)
let code = await runState.stateManager.getCode(new Address(addresstoBytes(addressBigInt)))

if (isEOF(code)) {
// In legacy code, the target code is treated as to be "EOFBYTES" code
Expand All @@ -579,7 +567,7 @@ export const handlers: Map<number, OpHandler> = new Map([
const address = new Address(addresstoBytes(addressBigInt))

// EOF check
const code = await runState.stateManager.getContractCode(address)
const code = await runState.stateManager.getCode(address)
if (isEOF(code)) {
// In legacy code, the target code is treated as to be "EOFBYTES" code
// Therefore, push the hash of EOFBYTES to the stack
Expand Down Expand Up @@ -665,7 +653,7 @@ export const handlers: Map<number, OpHandler> = new Map([
)
runState.interpreter.useGas(statelessGas, `BLOCKHASH`)
}
const storage = await runState.stateManager.getContractStorage(historyAddress, key)
const storage = await runState.stateManager.getStorage(historyAddress, key)

runState.stack.push(bytesToBigInt(storage))
} else {
Expand Down Expand Up @@ -1674,7 +1662,7 @@ export const handlers: Map<number, OpHandler> = new Map([

const toAddress = new Address(addresstoBytes(toAddr))

const code = await runState.stateManager.getContractCode(toAddress)
const code = await runState.stateManager.getCode(toAddress)

if (!isEOF(code)) {
// EXTDELEGATECALL cannot call legacy contracts
Expand Down
2 changes: 1 addition & 1 deletion packages/evm/src/opcodes/gas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ export const dynamicGasHandlers: Map<number, AsyncDynamicGasHandler | SyncDynami

if (common.isActivatedEIP(6800)) {
let codeEnd = _codeOffset + dataLength
const codeSize = BigInt((await runState.stateManager.getContractCode(address)).length)
const codeSize = BigInt((await runState.stateManager.getCode(address)).length)
if (codeEnd > codeSize) {
codeEnd = codeSize
}
Expand Down
4 changes: 2 additions & 2 deletions packages/evm/test/blobVersionedHashes.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ describe(`BLOBHASH: access blobVersionedHashes within contract calls`, () => {

const getBlobHasIndexCode = '0x60004960005260206000F3'
const contractAddress = new Address(hexToBytes('0x00000000000000000000000000000000000000ff')) // contract address
await evm.stateManager.putContractCode(contractAddress, hexToBytes(getBlobHasIndexCode)) // setup the contract code
await evm.stateManager.putCode(contractAddress, hexToBytes(getBlobHasIndexCode)) // setup the contract code

const caller = new Address(hexToBytes('0x00000000000000000000000000000000000000ee')) // caller address
await evm.stateManager.putAccount(caller, new Account(BigInt(0), BigInt(0x11111111))) // give the calling account a big balance so we don't run out of funds
Expand Down Expand Up @@ -132,7 +132,7 @@ describe(`BLOBHASH: access blobVersionedHashes in a CREATE/CREATE2 frame`, () =>
const res = await evm.runCall(runCallArgs)

const address = Address.fromString(bytesToHex(res.execResult.returnValue.slice(12)))
const code = await evm.stateManager.getContractCode(address)
const code = await evm.stateManager.getCode(address)

assert.equal(
bytesToHex(code),
Expand Down
19 changes: 8 additions & 11 deletions packages/evm/test/eips/eip-3860.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ describe('EIP 3860 tests', () => {
'0x7f600a80600080396000f3000000000000000000000000000000000000000000006000526000355a8160006000f05a8203600a55806000556001600155505050',
)

await evm.stateManager.putContractCode(contractFactory, factoryCode)
await evmWithout3860.stateManager.putContractCode(contractFactory, factoryCode)
await evm.stateManager.putCode(contractFactory, factoryCode)
await evmWithout3860.stateManager.putCode(contractFactory, factoryCode)
const data = hexToBytes('0x000000000000000000000000000000000000000000000000000000000000c000')
const runCallArgs = {
from: caller,
Expand Down Expand Up @@ -112,8 +112,8 @@ describe('EIP 3860 tests', () => {
'0x7f600a80600080396000f3000000000000000000000000000000000000000000006000526000355a60008260006000f55a8203600a55806000556001600155505050',
)

await evm.stateManager.putContractCode(contractFactory, factoryCode)
await evmWithout3860.stateManager.putContractCode(contractFactory, factoryCode)
await evm.stateManager.putCode(contractFactory, factoryCode)
await evmWithout3860.stateManager.putCode(contractFactory, factoryCode)
const data = hexToBytes('0x000000000000000000000000000000000000000000000000000000000000c000')
const runCallArgs = {
from: caller,
Expand Down Expand Up @@ -190,8 +190,8 @@ describe('EIP 3860 tests', () => {
// This is either the contract address if it was succesful, or 0 in case of error
const factoryCode = hexToBytes(`0x600060003560006000${code}600055`)

await evm.stateManager.putContractCode(contractFactory, factoryCode)
await evmDisabled.stateManager.putContractCode(contractFactory, factoryCode)
await evm.stateManager.putCode(contractFactory, factoryCode)
await evmDisabled.stateManager.putCode(contractFactory, factoryCode)

const runCallArgs = {
from: caller,
Expand All @@ -204,11 +204,8 @@ describe('EIP 3860 tests', () => {
await evmDisabled.runCall(runCallArgs)

const key0 = hexToBytes(`0x${'00'.repeat(32)}`)
const storageActive = await evm.stateManager.getContractStorage(contractFactory, key0)
const storageInactive = await evmDisabled.stateManager.getContractStorage(
contractFactory,
key0,
)
const storageActive = await evm.stateManager.getStorage(contractFactory, key0)
const storageInactive = await evmDisabled.stateManager.getStorage(contractFactory, key0)

assert.ok(
!equalsBytes(storageActive, new Uint8Array()),
Expand Down
2 changes: 1 addition & 1 deletion packages/evm/test/eips/eof-runner.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ describe('EOF: should run a simple contract', async () => {
const caller = new Address(hexToBytes('0x00000000000000000000000000000000000000ee')) // caller address
const contractAddress = new Address(hexToBytes('0x00000000000000000000000000000000000000ff')) // contract address

await evm.stateManager.putContractCode(contractAddress, code)
await evm.stateManager.putCode(contractAddress, code)
await evm.stateManager.putAccount(caller, new Account(BigInt(0), BigInt(0x11111111)))

const runCallArgs = {
Expand Down
2 changes: 1 addition & 1 deletion packages/evm/test/precompiles/09-blake2f.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ describe('Precompiles: BLAKE2F', () => {
// -> Calls Blake2F with this data (so, with the calldata)
// -> Returns the data from Blake2F
const code = `0x366000602037600080366020600060095AF1593D6000593E3D90F3`
await evm.stateManager.putContractCode(addr, hexToBytes(code))
await evm.stateManager.putCode(addr, hexToBytes(code))

const res = await evm.runCall({
data: hexToBytes(calldata),
Expand Down
Loading

0 comments on commit 07b3b8a

Please sign in to comment.