remix-project mirror
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
remix-project/libs/remix-simulator/src/vm-context.ts

162 lines
3.8 KiB

/* global ethereum */
'use strict'
import Web3 from 'web3'
import { rlp, keccak, bufferToHex } from 'ethereumjs-util'
import { vm as remixLibVm, execution } from '@remix-project/remix-lib'
import VM from '@ethereumjs/vm'
import Common from '@ethereumjs/common'
import StateManager from '@ethereumjs/vm/dist/state/stateManager'
import { StorageDump } from '@ethereumjs/vm/dist/state/interface'
/*
extend vm state manager and instanciate VM
*/
class StateManagerCommonStorageDump extends StateManager {
keyHashes: { [key: string]: string }
constructor () {
super()
this.keyHashes = {}
}
putContractStorage (address, key, value) {
this.keyHashes[keccak(key).toString('hex')] = bufferToHex(key)
return super.putContractStorage(address, key, value)
}
async dumpStorage (address): Promise<StorageDump> {
return new Promise((resolve, reject) => {
this._getStorageTrie(address)
.then((trie) => {
const storage = {}
const stream = trie.createReadStream()
stream.on('data', (val) => {
const value = rlp.decode(val.value)
storage['0x' + val.key.toString('hex')] = {
key: this.keyHashes[val.key.toString('hex')],
value: '0x' + value.toString('hex')
}
})
stream.on('end', () => {
resolve(storage)
})
})
.catch((e) => {
reject(e)
})
})
}
async getStateRoot (force = false) {
await this._cache.flush()
const stateRoot = this._trie.root
return stateRoot
}
async setStateRoot (stateRoot) {
if (this._checkpointCount !== 0) {
throw new Error('Cannot set state root with uncommitted checkpoints')
}
await this._cache.flush()
if (!stateRoot.equals(this._trie.EMPTY_TRIE_ROOT)) {
const hasRoot = await this._trie.checkRoot(stateRoot)
if (!hasRoot) {
throw new Error('State trie does not contain state root')
}
}
this._trie.root = stateRoot
this._cache.clear()
this._storageTries = {}
}
}
/*
trigger contextChanged, web3EndpointChanged
*/
export class VMContext {
currentFork: string
blockGasLimitDefault: number
blockGasLimit: number
customNetWorks
blocks
latestBlockNumber
txs
currentVm
web3vm
logsManager
exeResults
4 years ago
constructor (fork?) {
this.blockGasLimitDefault = 4300000
this.blockGasLimit = this.blockGasLimitDefault
this.currentFork = fork || 'london'
this.currentVm = this.createVm(this.currentFork)
this.blocks = {}
this.latestBlockNumber = 0
this.txs = {}
this.exeResults = {}
this.logsManager = new execution.LogsManager()
}
createVm (hardfork) {
const stateManager = new StateManagerCommonStorageDump()
const common = new Common({ chain: 'mainnet', hardfork })
const vm = new VM({
common,
activatePrecompiles: true,
stateManager,
allowUnlimitedContractSize: true
})
const web3vm = new remixLibVm.Web3VMProvider()
web3vm.setVM(vm)
return { vm, web3vm, stateManager, common }
}
getCurrentFork () {
return this.currentFork
}
web3 () {
return this.currentVm.web3vm
}
blankWeb3 () {
return new Web3()
}
vm () {
return this.currentVm.vm
}
vmObject () {
return this.currentVm
}
4 years ago
addBlock (block) {
let blockNumber = '0x' + block.header.number.toString('hex')
if (blockNumber === '0x') {
blockNumber = '0x0'
}
this.blocks['0x' + block.hash().toString('hex')] = block
this.blocks[blockNumber] = block
this.latestBlockNumber = blockNumber
this.logsManager.checkBlock(blockNumber, block, this.web3())
4 years ago
}
4 years ago
trackTx (tx, block) {
this.txs[tx] = block
}
trackExecResult (tx, execReult) {
this.exeResults[tx] = execReult
}
}