Commit 37cc11fa authored by yann300's avatar yann300

use last ethereumjs-vm for berlin fork

parent b5157238
...@@ -4,7 +4,7 @@ import * as packageJson from '../../../../../package.json' ...@@ -4,7 +4,7 @@ import * as packageJson from '../../../../../package.json'
import React from 'react' // eslint-disable-line import React from 'react' // eslint-disable-line
import ReactDOM from 'react-dom' import ReactDOM from 'react-dom'
import { Workspace } from '@remix-ui/workspace' // eslint-disable-line import { Workspace } from '@remix-ui/workspace' // eslint-disable-line
import * as ethutil from 'ethereumjs-util' import { bufferToHex, keccakFromString } from 'ethereumjs-util'
import { checkSpecialChars, checkSlash } from '../../lib/helper' import { checkSpecialChars, checkSlash } from '../../lib/helper'
var EventManager = require('../../lib/events') var EventManager = require('../../lib/events')
var { RemixdHandle } = require('../files/remixd-handle.js') var { RemixdHandle } = require('../files/remixd-handle.js')
...@@ -154,7 +154,7 @@ module.exports = class Filepanel extends ViewPlugin { ...@@ -154,7 +154,7 @@ module.exports = class Filepanel extends ViewPlugin {
try { try {
await this.processCreateWorkspace('code-sample') await this.processCreateWorkspace('code-sample')
this._deps.fileProviders.workspace.setWorkspace('code-sample') this._deps.fileProviders.workspace.setWorkspace('code-sample')
var hash = ethutil.bufferToHex(ethutil.keccak(params.code)) var hash = bufferToHex(keccakFromString(params.code))
const fileName = 'contract-' + hash.replace('0x', '').substring(0, 10) + '.sol' const fileName = 'contract-' + hash.replace('0x', '').substring(0, 10) + '.sol'
const path = fileName const path = fileName
await this._deps.fileProviders.workspace.set(path, atob(params.code)) await this._deps.fileProviders.workspace.set(path, atob(params.code))
......
...@@ -25,7 +25,7 @@ class Recorder { ...@@ -25,7 +25,7 @@ class Recorder {
var record = { value, parameters: payLoad.funArgs } var record = { value, parameters: payLoad.funArgs }
if (!to) { if (!to) {
var abi = payLoad.contractABI var abi = payLoad.contractABI
var keccak = ethutil.bufferToHex(ethutil.keccak(JSON.stringify(abi))) var keccak = ethutil.bufferToHex(ethutil.keccakFromString(JSON.stringify(abi)))
record.abi = keccak record.abi = keccak
record.contractName = payLoad.contractName record.contractName = payLoad.contractName
record.bytecode = payLoad.contractBytecode record.bytecode = payLoad.contractBytecode
......
...@@ -439,7 +439,7 @@ class Blockchain { ...@@ -439,7 +439,7 @@ class Blockchain {
function (error, result) { function (error, result) {
if (error) return next(error) if (error) return next(error)
const rawAddress = self.executionContext.isVM() ? result.result.createdAddress : result.result.contractAddress const rawAddress = self.executionContext.isVM() ? result.result.createdAddress.buf : result.result.contractAddress
const eventName = (tx.useCall ? 'callExecuted' : 'transactionExecuted') const eventName = (tx.useCall ? 'callExecuted' : 'transactionExecuted')
self.event.trigger(eventName, [error, tx.from, tx.to, tx.data, tx.useCall, result, timestamp, payLoad, rawAddress]) self.event.trigger(eventName, [error, tx.from, tx.to, tx.data, tx.useCall, result, timestamp, payLoad, rawAddress])
...@@ -470,7 +470,7 @@ class Blockchain { ...@@ -470,7 +470,7 @@ class Blockchain {
let address = null let address = null
let returnValue = null let returnValue = null
if (txResult && txResult.result) { if (txResult && txResult.result) {
address = isVM ? txResult.result.createdAddress : txResult.result.contractAddress address = isVM ? txResult.result.createdAddress.buf : txResult.result.contractAddress
// if it's not the VM, we don't have return value. We only have the transaction, and it does not contain the return value. // if it's not the VM, we don't have return value. We only have the transaction, and it does not contain the return value.
returnValue = (txResult.result.execResult && isVM) ? txResult.result.execResult.returnValue : txResult.result returnValue = (txResult.result.execResult && isVM) ? txResult.result.execResult.returnValue : txResult.result
} }
......
const Web3 = require('web3') const Web3 = require('web3')
const { stripHexPrefix, hashPersonalMessage } = require('ethereumjs-util') const { hashPersonalMessage } = require('ethereumjs-util')
class InjectedProvider { class InjectedProvider {
constructor (executionContext) { constructor (executionContext) {
...@@ -20,7 +20,6 @@ class InjectedProvider { ...@@ -20,7 +20,6 @@ class InjectedProvider {
} }
getBalanceInEther (address, cb) { getBalanceInEther (address, cb) {
address = stripHexPrefix(address)
this.executionContext.web3().eth.getBalance(address, (err, res) => { this.executionContext.web3().eth.getBalance(address, (err, res) => {
if (err) { if (err) {
return cb(err) return cb(err)
......
const Web3 = require('web3') const Web3 = require('web3')
const { stripHexPrefix, hashPersonalMessage } = require('ethereumjs-util') const { hashPersonalMessage } = require('ethereumjs-util')
const Personal = require('web3-eth-personal') const Personal = require('web3-eth-personal')
class NodeProvider { class NodeProvider {
...@@ -28,7 +28,6 @@ class NodeProvider { ...@@ -28,7 +28,6 @@ class NodeProvider {
} }
getBalanceInEther (address, cb) { getBalanceInEther (address, cb) {
address = stripHexPrefix(address)
this.executionContext.web3().eth.getBalance(address, (err, res) => { this.executionContext.web3().eth.getBalance(address, (err, res) => {
if (err) { if (err) {
return cb(err) return cb(err)
......
const Web3 = require('web3') const Web3 = require('web3')
const { BN, privateToAddress, stripHexPrefix, hashPersonalMessage } = require('ethereumjs-util') const { BN, privateToAddress, hashPersonalMessage } = require('ethereumjs-util')
const RemixSimulator = require('@remix-project/remix-simulator') const RemixSimulator = require('@remix-project/remix-simulator')
class VMProvider { class VMProvider {
...@@ -39,7 +39,6 @@ class VMProvider { ...@@ -39,7 +39,6 @@ class VMProvider {
} }
getBalanceInEther (address, cb) { getBalanceInEther (address, cb) {
address = stripHexPrefix(address)
this.web3.eth.getBalance(address, (err, res) => { this.web3.eth.getBalance(address, (err, res) => {
if (err) { if (err) {
return cb(err) return cb(err)
......
...@@ -21,9 +21,9 @@ ...@@ -21,9 +21,9 @@
"dependencies": { "dependencies": {
"@remix-project/remix-astwalker": "^0.0.26", "@remix-project/remix-astwalker": "^0.0.26",
"@remix-project/remix-lib": "^0.4.34", "@remix-project/remix-lib": "^0.4.34",
"ethereumjs-block": "^2.2.2", "@ethereumjs/vm": "^5.3.2",
"ethereumjs-tx": "^2.1.2", "@ethereumjs/block": "^3.2.1",
"ethereumjs-vm": "4.1.3" "@ethereumjs/tx": "^3.1.3"
}, },
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
......
...@@ -36,9 +36,9 @@ ...@@ -36,9 +36,9 @@
"dependencies": { "dependencies": {
"@remix-project/remix-lib": "^0.4.34", "@remix-project/remix-lib": "^0.4.34",
"@types/tape": "^4.2.33", "@types/tape": "^4.2.33",
"ethereumjs-block": "^2.2.2", "@ethereumjs/vm": "^5.3.2",
"ethereumjs-tx": "^2.1.2", "@ethereumjs/block": "^3.2.1",
"ethereumjs-vm": "4.1.3", "@ethereumjs/tx": "^3.1.3",
"nyc": "^13.3.0", "nyc": "^13.3.0",
"tape": "^4.10.1", "tape": "^4.10.1",
"ts-node": "^8.0.3", "ts-node": "^8.0.3",
......
...@@ -21,10 +21,10 @@ ...@@ -21,10 +21,10 @@
"@remix-project/remix-astwalker": "^0.0.26", "@remix-project/remix-astwalker": "^0.0.26",
"@remix-project/remix-lib": "^0.4.34", "@remix-project/remix-lib": "^0.4.34",
"commander": "^2.19.0", "commander": "^2.19.0",
"ethereumjs-block": "^2.2.2", "@ethereumjs/vm": "^5.3.2",
"ethereumjs-tx": "^2.1.2", "@ethereumjs/block": "^3.2.1",
"ethereumjs-util": "^6.2.0", "@ethereumjs/tx": "^3.1.3",
"ethereumjs-vm": "4.1.3", "ethereumjs-util": "^7.0.10",
"web3": "^1.2.4" "web3": "^1.2.4"
}, },
"devDependencies": { "devDependencies": {
......
...@@ -69,8 +69,7 @@ function getMappingLocation (key, position) { ...@@ -69,8 +69,7 @@ function getMappingLocation (key, position) {
let mappingP = intToBuffer(position) let mappingP = intToBuffer(position)
mappingP = setLengthLeft(mappingP, 32) mappingP = setLengthLeft(mappingP, 32)
const mappingKeyBuf = concatTypedArrays(mappingK, mappingP) const mappingKeyBuf = concatTypedArrays(mappingK, mappingP)
const mappingKeyPreimage: string = '0x' + mappingKeyBuf.toString('hex') const mappingStorageLocation: Buffer = keccak(mappingKeyBuf)
const mappingStorageLocation: Buffer = keccak(mappingKeyPreimage)
const mappingStorageLocationinBn: BN = new BN(mappingStorageLocation, 16) const mappingStorageLocationinBn: BN = new BN(mappingStorageLocation, 16)
return mappingStorageLocationinBn return mappingStorageLocationinBn
} }
......
'use strict' 'use strict'
import { BN, bufferToHex, unpad } from 'ethereumjs-util' import { BN, bufferToHex, unpadHexString } from 'ethereumjs-util'
export function decodeIntFromHex (value, byteLength, signed) { export function decodeIntFromHex (value, byteLength, signed) {
let bigNumber = new BN(value, 16) let bigNumber = new BN(value, 16)
...@@ -57,7 +57,7 @@ export function toBN (value) { ...@@ -57,7 +57,7 @@ export function toBN (value) {
if (value instanceof BN) { if (value instanceof BN) {
return value return value
} else if (value.match && value.match(/^(0x)?([a-f0-9]*)$/)) { } else if (value.match && value.match(/^(0x)?([a-f0-9]*)$/)) {
value = unpad(value.replace(/^(0x)/, '')) value = unpadHexString(value.replace(/^(0x)/, ''))
value = new BN(value === '' ? '0' : value, 16) value = new BN(value === '' ? '0' : value, 16)
} else if (!isNaN(value)) { } else if (!isNaN(value)) {
value = new BN(value) value = new BN(value)
......
...@@ -104,7 +104,7 @@ export class TraceCache { ...@@ -104,7 +104,7 @@ export class TraceCache {
address: address, address: address,
key: key, key: key,
value: value, value: value,
hashedKey: sha3_256(key) hashedKey: key && sha3_256(key)
} }
this.storageChanges.push(index) this.storageChanges.push(index)
} }
......
'use strict' 'use strict'
var utileth = require('ethereumjs-util') var utileth = require('ethereumjs-util')
var Tx = require('ethereumjs-tx').Transaction var Tx = require('@ethereumjs/tx').Transaction
var Block = require('ethereumjs-block') import { Block, BlockHeader } from '@ethereumjs/block'
var BN = require('ethereumjs-util').BN var BN = require('ethereumjs-util').BN
var remixLib = require('@remix-project/remix-lib') var remixLib = require('@remix-project/remix-lib')
var EthJSVM = require('ethereumjs-vm').default import VM from '@ethereumjs/vm'
import Common from '@ethereumjs/common'
export function sendTx (vm, from, to, value, data, cb) { export function sendTx (vm, from, to, value, data, cb) {
var tx = new Tx({ var tx = new Tx({
...@@ -16,14 +17,14 @@ export function sendTx (vm, from, to, value, data, cb) { ...@@ -16,14 +17,14 @@ export function sendTx (vm, from, to, value, data, cb) {
data: Buffer.from(data, 'hex') data: Buffer.from(data, 'hex')
}) })
tx.sign(from.privateKey) tx.sign(from.privateKey)
var block = new Block({
header: { var header = BlockHeader.fromHeaderData({
timestamp: new Date().getTime() / 1000 | 0, timestamp: new Date().getTime() / 1000 | 0,
number: 0 number: 0
},
transactions: [],
uncleHeaders: []
}) })
var block = new Block(header, [], [])
try { try {
vm.runTx({block: block, tx: tx, skipBalance: true, skipNonce: true}).then(function (result) { vm.runTx({block: block, tx: tx, skipBalance: true, skipNonce: true}).then(function (result) {
setTimeout(() => { setTimeout(() => {
...@@ -39,13 +40,9 @@ export function sendTx (vm, from, to, value, data, cb) { ...@@ -39,13 +40,9 @@ export function sendTx (vm, from, to, value, data, cb) {
} }
function createVm (hardfork) { function createVm (hardfork) {
// const stateManager = new StateManagerCommonStorageDump({}) const common = new Common({ chain: 'mainnet', hardfork })
// stateManager.checkpoint(() => {}) const vm = new VM({ common })
const vm = new EthJSVM({ // vm.blockchain.validate = false
activatePrecompiles: true,
hardfork
})
vm.blockchain.validate = false
return { vm, stateManager: vm.stateManager } return { vm, stateManager: vm.stateManager }
} }
...@@ -53,17 +50,18 @@ function createVm (hardfork) { ...@@ -53,17 +50,18 @@ function createVm (hardfork) {
Init VM / Send Transaction Init VM / Send Transaction
*/ */
export function initVM (st, privateKey) { export function initVM (st, privateKey) {
var VM = createVm('muirGlacier') var VM = createVm('berlin')
const vm = VM.vm const vm = VM.vm
var address = utileth.privateToAddress(privateKey) var address = utileth.privateToAddress(privateKey)
vm.stateManager.getAccount(address, (error, account) => { vm.stateManager.getAccount(address).then((account) => {
if (error) return console.log(error) account.balance = new BN('f00000000000000001', 16)
account.balance = '0xf00000000000000001' vm.stateManager.putAccount(address, account).catch((error) => {
vm.stateManager.putAccount(address, account, function cb (error) { console.log(error)
if (error) console.log(error)
}) })
}).catch((error) => {
console.log(error)
}) })
var web3Provider = new remixLib.vm.Web3VMProvider() var web3Provider = new remixLib.vm.Web3VMProvider()
......
'use strict' 'use strict'
import { Block, BlockHeader } from '@ethereumjs/block'
import VM from '@ethereumjs/vm'
var utileth = require('ethereumjs-util') var utileth = require('ethereumjs-util')
var Tx = require('ethereumjs-tx').Transaction var Tx = require('@ethereumjs/tx').Transaction
var Block = require('ethereumjs-block')
var BN = require('ethereumjs-util').BN var BN = require('ethereumjs-util').BN
var remixLib = require('@remix-project/remix-lib') var remixLib = require('@remix-project/remix-lib')
...@@ -15,14 +16,13 @@ function sendTx (vm, from, to, value, data, cb) { ...@@ -15,14 +16,13 @@ function sendTx (vm, from, to, value, data, cb) {
data: Buffer.from(data, 'hex') data: Buffer.from(data, 'hex')
}) })
tx.sign(from.privateKey) tx.sign(from.privateKey)
var block = new Block({
header: { var header = BlockHeader.fromHeaderData({
timestamp: new Date().getTime() / 1000 | 0, timestamp: new Date().getTime() / 1000 | 0,
number: 0 number: 0
},
transactions: [],
uncleHeaders: []
}) })
var block = new Block(header, [], [])
vm.runTx({block: block, tx: tx, skipBalance: true, skipNonce: true}).then(function (result) { vm.runTx({block: block, tx: tx, skipBalance: true, skipNonce: true}).then(function (result) {
setTimeout(() => { setTimeout(() => {
cb(null, utileth.bufferToHex(tx.hash())) cb(null, utileth.bufferToHex(tx.hash()))
...@@ -37,19 +37,18 @@ function sendTx (vm, from, to, value, data, cb) { ...@@ -37,19 +37,18 @@ function sendTx (vm, from, to, value, data, cb) {
Init VM / Send Transaction Init VM / Send Transaction
*/ */
function initVM (privateKey) { function initVM (privateKey) {
var VM = require('ethereumjs-vm').default
var address = utileth.privateToAddress(privateKey) var address = utileth.privateToAddress(privateKey)
var vm = new VM({ var vm = new VM({
enableHomestead: true,
activatePrecompiles: true activatePrecompiles: true
}) })
vm.stateManager.getAccount(address, (error, account) => { vm.stateManager.getAccount(address).then((account) => {
if (error) return console.log(error) account.balance = new BN('f00000000000000001', 16)
account.balance = '0xf00000000000000001' vm.stateManager.putAccount(address, account).catch((error) => {
vm.stateManager.putAccount(address, account, function cb (error) { console.log(error)
if (error) console.log(error)
}) })
}).catch((error) => {
console.log(error)
}) })
var web3Provider = new remixLib.vm.Web3VMProvider() var web3Provider = new remixLib.vm.Web3VMProvider()
......
...@@ -15,10 +15,9 @@ ...@@ -15,10 +15,9 @@
"main": "src/index.js", "main": "src/index.js",
"dependencies": { "dependencies": {
"async": "^2.1.2", "async": "^2.1.2",
"ethereumjs-block": "^2.2.2", "@ethereumjs/block": "^3.2.1",
"ethereumjs-tx": "^2.1.2", "@ethereumjs/tx": "^3.1.3",
"ethereumjs-util": "^6.2.0", "ethereumjs-util": "^7.0.10",
"ethereumjs-vm": "4.1.3",
"ethers": "^4.0.40", "ethers": "^4.0.40",
"events": "^3.0.0", "events": "^3.0.0",
"solc": "^0.7.4", "solc": "^0.7.4",
......
...@@ -5,8 +5,10 @@ import { EventManager } from '../eventManager' ...@@ -5,8 +5,10 @@ import { EventManager } from '../eventManager'
import { rlp, keccak, bufferToHex } from 'ethereumjs-util' import { rlp, keccak, bufferToHex } from 'ethereumjs-util'
import { Web3VmProvider } from '../web3Provider/web3VmProvider' import { Web3VmProvider } from '../web3Provider/web3VmProvider'
import { LogsManager } from './logsManager' import { LogsManager } from './logsManager'
const EthJSVM = require('ethereumjs-vm').default import VM from '@ethereumjs/vm'
const StateManager = require('ethereumjs-vm/dist/state/stateManager').default import Common from '@ethereumjs/common'
import StateManager from '@ethereumjs/vm/dist/state/stateManager'
import { StorageDump } from '@ethereumjs/vm/dist/state/interface'
declare let ethereum: any declare let ethereum: any
let web3 let web3
...@@ -23,21 +25,21 @@ if (typeof window !== 'undefined' && typeof window['ethereum'] !== 'undefined') ...@@ -23,21 +25,21 @@ if (typeof window !== 'undefined' && typeof window['ethereum'] !== 'undefined')
*/ */
class StateManagerCommonStorageDump extends StateManager { class StateManagerCommonStorageDump extends StateManager {
constructor (arg) { keyHashes
super(arg) constructor () {
super()
this.keyHashes = {} this.keyHashes = {}
} }
putContractStorage (address, key, value, cb) { S
this.keyHashes[keccak(key).toString('hex')] = bufferToHex(key) putContractStorage (address, key, value) {
super.putContractStorage(address, key, value, cb) this.keyHashes[keccak(key).toString('hex')] = bufferToHex(key)
} return super.putContractStorage(address, key, value)
}
dumpStorage (address, cb) { dumpStorage (address) {
this._getStorageTrie(address, (err, trie) => { return new Promise<StorageDump>((resolve, reject) => {
if (err) { this._getStorageTrie(address).then((trie) => {
return cb(err)
}
const storage = {} const storage = {}
const stream = trie.createReadStream() const stream = trie.createReadStream()
stream.on('data', (val) => { stream.on('data', (val) => {
...@@ -48,28 +50,52 @@ class StateManagerCommonStorageDump extends StateManager { ...@@ -48,28 +50,52 @@ class StateManagerCommonStorageDump extends StateManager {
} }
}) })
stream.on('end', function () { stream.on('end', function () {
cb(storage) resolve(storage)
}) })
}).catch((error) => {
reject(error)
}) })
})
}
async getStateRoot (force: boolean = false): Promise<Buffer> {
if (!force && this._checkpointCount !== 0) {
// throw new Error('Cannot get state root with uncommitted checkpoints')
} }
getStateRoot (cb) { try {
const checkpoint = this._checkpointCount await this._cache.flush()
this._checkpointCount = 0 } catch (e) {
super.getStateRoot((err, stateRoot) => { console.error(e)
this._checkpointCount = checkpoint
cb(err, stateRoot)
})
} }
setStateRoot (stateRoot, cb) { const stateRoot = this._trie.root
const checkpoint = this._checkpointCount return stateRoot
this._checkpointCount = 0 }
super.setStateRoot(stateRoot, (err) => {
this._checkpointCount = checkpoint async setStateRoot (stateRoot: Buffer): Promise<void> {
cb(err) if (this._checkpointCount !== 0) {
}) // throw new Error('Cannot set state root with uncommitted checkpoints')
} }
await this._cache.flush()
if (stateRoot === this._trie.EMPTY_TRIE_ROOT) {
this._trie.root = stateRoot
this._cache.clear()
this._storageTries = {}
return
}
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 = {}
}
} }
/* /*
...@@ -96,7 +122,7 @@ export class ExecutionContext { ...@@ -96,7 +122,7 @@ export class ExecutionContext {
this.executionContext = null this.executionContext = null
this.blockGasLimitDefault = 4300000 this.blockGasLimitDefault = 4300000
this.blockGasLimit = this.blockGasLimitDefault this.blockGasLimit = this.blockGasLimitDefault
this.currentFork = 'muirGlacier' this.currentFork = 'berlin'
this.vms = { this.vms = {
/* /*
byzantium: createVm('byzantium'), byzantium: createVm('byzantium'),
...@@ -104,7 +130,7 @@ export class ExecutionContext { ...@@ -104,7 +130,7 @@ export class ExecutionContext {
petersburg: createVm('petersburg'), petersburg: createVm('petersburg'),
istanbul: createVm('istanbul'), istanbul: createVm('istanbul'),
*/ */
muirGlacier: this.createVm('muirGlacier') berlin: this.createVm('berlin')
} }
this.mainNetGenesisHash = '0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3' this.mainNetGenesisHash = '0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3'
this.customNetWorks = {} this.customNetWorks = {}
...@@ -123,18 +149,18 @@ export class ExecutionContext { ...@@ -123,18 +149,18 @@ export class ExecutionContext {
} }
createVm (hardfork) { createVm (hardfork) {
const stateManager = new StateManagerCommonStorageDump({}) const stateManager = new StateManagerCommonStorageDump()
stateManager.checkpoint(() => {}) stateManager.checkpoint()
const vm = new EthJSVM({ const common = new Common({ chain: 'mainnet', hardfork })
const vm = new VM({
common,
activatePrecompiles: true, activatePrecompiles: true,
blockchain: stateManager.blockchain, stateManager: stateManager
stateManager: stateManager,
hardfork: hardfork
}) })
vm.blockchain.validate = false
const web3vm = new Web3VmProvider() const web3vm = new Web3VmProvider()
web3vm.setVM(vm) web3vm.setVM(vm)
return { vm, web3vm, stateManager } return { vm, web3vm, stateManager, common }
} }
askPermission () { askPermission () {
...@@ -210,6 +236,10 @@ export class ExecutionContext { ...@@ -210,6 +236,10 @@ export class ExecutionContext {
return this.vms[this.currentFork].vm return this.vms[this.currentFork].vm
} }
vmObject () {
return this.vms[this.currentFork]
}
setContext (context, endPointUrl, confirmCb, infoCb) { setContext (context, endPointUrl, confirmCb, infoCb) {
this.executionContext = context this.executionContext = context
this.executionContextChange(context, endPointUrl, confirmCb, infoCb, null) this.executionContextChange(context, endPointUrl, confirmCb, infoCb, null)
...@@ -221,8 +251,8 @@ export class ExecutionContext { ...@@ -221,8 +251,8 @@ export class ExecutionContext {
if (!infoCb) infoCb = () => {} if (!infoCb) infoCb = () => {}
if (context === 'vm') { if (context === 'vm') {
this.executionContext = context this.executionContext = context
this.vms[this.currentFork].stateManager.revert(() => { this.vms[this.currentFork].stateManager.revert().then(() => {
this.vms[this.currentFork].stateManager.checkpoint(() => {}) this.vms[this.currentFork].stateManager.checkpoint()
}) })
this.event.trigger('contextChanged', ['vm']) this.event.trigger('contextChanged', ['vm'])
return cb() return cb()
......
'use strict' 'use strict'
import { Transaction } from 'ethereumjs-tx' import { Transaction } from '@ethereumjs/tx'
import Block from 'ethereumjs-block' import { Block, BlockHeader } from '@ethereumjs/block'
import { BN, bufferToHex } from 'ethereumjs-util' import { BN, bufferToHex, Address } from 'ethereumjs-util'
import { ExecutionContext } from './execution-context' import { ExecutionContext } from './execution-context'
import { EventManager } from '../eventManager' import { EventManager } from '../eventManager'
...@@ -15,11 +15,13 @@ export class TxRunner { ...@@ -15,11 +15,13 @@ export class TxRunner {
vmaccounts vmaccounts
queusTxs queusTxs
blocks blocks
commonContext
constructor (vmaccounts, api, executionContext) { constructor (vmaccounts, api, executionContext) {
this.event = new EventManager() this.event = new EventManager()
// has a default for now for backwards compatability // has a default for now for backwards compatability
this.executionContext = executionContext || new ExecutionContext() this.executionContext = executionContext || new ExecutionContext()
this.commonContext = this.executionContext.vmObject().common
this._api = api this._api = api
this.blockNumber = 0 this.blockNumber = 0
this.runAsync = true this.runAsync = true
...@@ -109,48 +111,45 @@ export class TxRunner { ...@@ -109,48 +111,45 @@ export class TxRunner {
return callback('Invalid account selected') return callback('Invalid account selected')
} }
this.executionContext.vm().stateManager.getAccount(Buffer.from(from.replace('0x', ''), 'hex'), (err, res) => { this.executionContext.vm().stateManager.getAccount(Address.fromString(from)).then((res) => {
if (err) { // See https://github.com/ethereumjs/ethereumjs-tx/blob/master/docs/classes/transaction.md#constructor
callback('Account not found') // for initialization fields and their types
value = value ? parseInt(value) : 0
const tx = Transaction.fromTxData({
nonce: new BN(res.nonce),
gasPrice: '0x1',
gasLimit: gasLimit,
to: to,
value: value,
data: Buffer.from(data.slice(2), 'hex')
}, { common: this.commonContext }).sign(account.privateKey)
const coinbases = ['0x0e9281e9c6a0808672eaba6bd1220e144c9bb07a', '0x8945a1288dc78a6d8952a92c77aee6730b414778', '0x94d76e24f818426ae84aa404140e8d5f60e10e7e']
const difficulties = [new BN('69762765929000', 10), new BN('70762765929000', 10), new BN('71762765929000', 10)]
const header: BlockHeader = BlockHeader.fromHeaderData({
timestamp: timestamp || (new Date().getTime() / 1000 | 0),
number: self.blockNumber,
coinbase: coinbases[self.blockNumber % coinbases.length],
difficulty: difficulties[self.blockNumber % difficulties.length],
gasLimit: new BN(gasLimit.replace('0x', ''), 16).imuln(2)
}, { common: this.commonContext })
const block = new Block(header, [tx], [])
if (!useCall) {
++self.blockNumber
this.runBlockInVm(tx, block, callback)
} else { } else {
// See https://github.com/ethereumjs/ethereumjs-tx/blob/master/docs/classes/transaction.md#constructor this.executionContext.vm().stateManager.checkpoint().then(() => {
// for initialization fields and their types this.runBlockInVm(tx, block, (err, result) => {
value = value ? parseInt(value) : 0 this.executionContext.vm().stateManager.revert().then(() => {
const tx = new Transaction({ callback(err, result)
nonce: new BN(res.nonce),
gasPrice: '0x1',
gasLimit: gasLimit,
to: to,
value: value,
data: Buffer.from(data.slice(2), 'hex')
})
tx.sign(account.privateKey)
const coinbases = ['0x0e9281e9c6a0808672eaba6bd1220e144c9bb07a', '0x8945a1288dc78a6d8952a92c77aee6730b414778', '0x94d76e24f818426ae84aa404140e8d5f60e10e7e']
const difficulties = [new BN('69762765929000', 10), new BN('70762765929000', 10), new BN('71762765929000', 10)]
const block = new Block({
header: {
timestamp: timestamp || (new Date().getTime() / 1000 | 0),
number: self.blockNumber,
coinbase: coinbases[self.blockNumber % coinbases.length],
difficulty: difficulties[self.blockNumber % difficulties.length],
gasLimit: new BN(gasLimit, 10).imuln(2)
},
transactions: [tx],
uncleHeaders: []
})
if (!useCall) {
++self.blockNumber
this.runBlockInVm(tx, block, callback)
} else {
this.executionContext.vm().stateManager.checkpoint(() => {
this.runBlockInVm(tx, block, (err, result) => {
this.executionContext.vm().stateManager.revert(() => {
callback(err, result)
})
}) })
}) })
} })
} }
}).catch(() => {
callback('Account not found')
}) })
} }
...@@ -167,7 +166,7 @@ export class TxRunner { ...@@ -167,7 +166,7 @@ export class TxRunner {
result: result, result: result,
transactionHash: bufferToHex(Buffer.from(tx.hash())) transactionHash: bufferToHex(Buffer.from(tx.hash()))
}) })
}).catch(function (err) { }).catch((err) => {
callback(err) callback(err)
}) })
} }
......
import { waterfall } from 'async' import { waterfall } from 'async'
import { BN, privateToAddress, isValidPrivate, toChecksumAddress } from 'ethereumjs-util' import { BN, privateToAddress, isValidPrivate, toChecksumAddress, Address } from 'ethereumjs-util'
import { stripHexPrefix } from 'ethjs-util'
import { randomBytes } from 'crypto' import { randomBytes } from 'crypto'
import { EventEmitter } from 'events' import { EventEmitter } from 'events'
import { TxRunner } from './execution/txRunner' import { TxRunner } from './execution/txRunner'
...@@ -124,12 +123,13 @@ export class UniversalDApp { ...@@ -124,12 +123,13 @@ export class UniversalDApp {
// FIXME: we don't care about the callback, but we should still make this proper // FIXME: we don't care about the callback, but we should still make this proper
const stateManager = this.executionContext.vm().stateManager const stateManager = this.executionContext.vm().stateManager
stateManager.getAccount(address, (error, account) => { stateManager.getAccount(address).then((account) => {
if (error) return console.log(error) account.balance = new BN(balance.replace('0x', '') || 'f00000000000000001', 16)
account.balance = balance || '0xf00000000000000001' stateManager.putAccount(address, account).catch((error) => {
stateManager.putAccount(address, account, function cb (error) { console.log(error)
if (error) console.log(error)
}) })
}).catch((error) => {
console.log(error)
}) })
this.accounts[toChecksumAddress('0x' + address.toString('hex'))] = { privateKey, nonce: 0 } this.accounts[toChecksumAddress('0x' + address.toString('hex'))] = { privateKey, nonce: 0 }
...@@ -177,8 +177,6 @@ export class UniversalDApp { ...@@ -177,8 +177,6 @@ export class UniversalDApp {
/** Get the balance of an address */ /** Get the balance of an address */
getBalance (address, cb) { getBalance (address, cb) {
address = stripHexPrefix(address)
if (!this.executionContext.isVM()) { if (!this.executionContext.isVM()) {
return this.executionContext.web3().eth.getBalance(address, (err, res) => { return this.executionContext.web3().eth.getBalance(address, (err, res) => {
if (err) { if (err) {
...@@ -191,11 +189,10 @@ export class UniversalDApp { ...@@ -191,11 +189,10 @@ export class UniversalDApp {
return cb('No accounts?') return cb('No accounts?')
} }
this.executionContext.vm().stateManager.getAccount(Buffer.from(address, 'hex'), (err, res) => { this.executionContext.vm().stateManager.getAccount(Address.fromString(address)).then((res) => {
if (err) {
return cb('Account not found')
}
cb(null, new BN(res.balance).toString(10)) cb(null, new BN(res.balance).toString(10))
}).catch(() => {
cb('Account not found')
}) })
} }
......
...@@ -168,8 +168,7 @@ export function sha3_256 (value) { ...@@ -168,8 +168,7 @@ export function sha3_256 (value) {
if (typeof value === 'string' && value.indexOf('0x') !== 0) { if (typeof value === 'string' && value.indexOf('0x') !== 0) {
value = '0x' + value value = '0x' + value
} }
const ret: string = bufferToHex(setLengthLeft(value, 32)) const retInBuffer: Buffer = keccak(setLengthLeft(Buffer.from(value.replace('0x', ''), 'hex'), 32))
const retInBuffer: Buffer = keccak(ret)
return bufferToHex(retInBuffer) return bufferToHex(retInBuffer)
} }
......
import { hexConvert, hexListFromBNs, formatMemory } from '../util' import { hexConvert, hexListFromBNs, formatMemory } from '../util'
import { normalizeHexAddress } from '../helpers/uiHelper' import { normalizeHexAddress } from '../helpers/uiHelper'
import { toChecksumAddress, BN, toBuffer } from 'ethereumjs-util' import { toChecksumAddress, BN, toBuffer, Address } from 'ethereumjs-util'
import Web3 from 'web3' import Web3 from 'web3'
export class Web3VmProvider { export class Web3VmProvider {
...@@ -101,23 +101,23 @@ export class Web3VmProvider { ...@@ -101,23 +101,23 @@ export class Web3VmProvider {
} }
const tx = {} const tx = {}
tx['hash'] = this.processingHash tx['hash'] = this.processingHash
tx['from'] = toChecksumAddress(hexConvert(data.getSenderAddress())) tx['from'] = toChecksumAddress(hexConvert(data.getSenderAddress().buf))
if (data.to && data.to.length) { if (data.to && data.to.length) {
tx['to'] = toChecksumAddress(hexConvert(data.to)) tx['to'] = toChecksumAddress(hexConvert(data.to.buf))
} }
this.processingAddress = tx['to'] this.processingAddress = tx['to']
tx['data'] = hexConvert(data.data) // tx['data'] = hexConvert(data.data)
tx['input'] = hexConvert(data.input) tx['input'] = hexConvert(data.data)
tx['gas'] = (new BN(hexConvert(data.gas).replace('0x', ''), 16)).toString(10) tx['gas'] = data.gasLimit.toString(10)
if (data.value) { if (data.value) {
tx['value'] = hexConvert(data.value) tx['value'] = data.value.toString(10)
} }
this.txs[this.processingHash] = tx this.txs[this.processingHash] = tx
this.txsReceipt[this.processingHash] = tx this.txsReceipt[this.processingHash] = tx
this.storageCache[this.processingHash] = {} this.storageCache[this.processingHash] = {}
if (tx['to']) { if (tx['to']) {
const account = toBuffer(tx['to']) const account = toBuffer(tx['to'])
this.vm.stateManager.dumpStorage(account, (storage) => { this.vm.stateManager.dumpStorage(account).then((storage) => {
this.storageCache[this.processingHash][tx['to']] = storage this.storageCache[this.processingHash][tx['to']] = storage
this.lastProcessedStorageTxHash[tx['to']] = this.processingHash this.lastProcessedStorageTxHash[tx['to']] = this.processingHash
}) })
...@@ -155,8 +155,8 @@ export class Web3VmProvider { ...@@ -155,8 +155,8 @@ export class Web3VmProvider {
const status = data.execResult.exceptionError ? 0 : 1 const status = data.execResult.exceptionError ? 0 : 1
this.txsReceipt[this.processingHash].status = `0x${status}` this.txsReceipt[this.processingHash].status = `0x${status}`
if (data.createdAddress) { if (data.createdAddress && data.createdAddress.buf) {
const address = hexConvert(data.createdAddress) const address = hexConvert(data.createdAddress.buf)
this.vmTraces[this.processingHash].return = toChecksumAddress(address) this.vmTraces[this.processingHash].return = toChecksumAddress(address)
this.txsReceipt[this.processingHash].contractAddress = toChecksumAddress(address) this.txsReceipt[this.processingHash].contractAddress = toChecksumAddress(address)
} else if (data.execResult.returnValue) { } else if (data.execResult.returnValue) {
...@@ -206,7 +206,7 @@ export class Web3VmProvider { ...@@ -206,7 +206,7 @@ export class Web3VmProvider {
this.processingAddress = toChecksumAddress(this.processingAddress) this.processingAddress = toChecksumAddress(this.processingAddress)
if (!this.storageCache[this.processingHash][this.processingAddress]) { if (!this.storageCache[this.processingHash][this.processingAddress]) {
const account = toBuffer(this.processingAddress) const account = toBuffer(this.processingAddress)
this.vm.stateManager.dumpStorage(account, (storage) => { this.vm.stateManager.dumpStorage(account).then((storage) => {
this.storageCache[this.processingHash][this.processingAddress] = storage this.storageCache[this.processingHash][this.processingAddress] = storage
this.lastProcessedStorageTxHash[this.processingAddress] = this.processingHash this.lastProcessedStorageTxHash[this.processingAddress] = this.processingHash
}) })
...@@ -227,9 +227,10 @@ export class Web3VmProvider { ...@@ -227,9 +227,10 @@ export class Web3VmProvider {
getCode (address, cb) { getCode (address, cb) {
address = toChecksumAddress(address) address = toChecksumAddress(address)
const account = toBuffer(address) this.vm.stateManager.getContractCode(Address.fromString(address)).then((result) => {
this.vm.stateManager.getContractCode(account, (error, result) => { cb(null, hexConvert(result))
cb(error, hexConvert(result)) }).catch((error) => {
cb(error)
}) })
} }
......
...@@ -21,10 +21,10 @@ ...@@ -21,10 +21,10 @@
"color-support": "^1.1.3", "color-support": "^1.1.3",
"commander": "^2.19.0", "commander": "^2.19.0",
"cors": "^2.8.5", "cors": "^2.8.5",
"ethereumjs-block": "^2.2.2", "@ethereumjs/vm": "^5.3.2",
"ethereumjs-tx": "^2.1.2", "@ethereumjs/block": "^3.2.1",
"ethereumjs-util": "^6.2.0", "@ethereumjs/tx": "^3.1.3",
"ethereumjs-vm": "4.1.3", "ethereumjs-util": "^7.0.10",
"express": "^4.16.3", "express": "^4.16.3",
"express-ws": "^4.0.0", "express-ws": "^4.0.0",
"merge": "^1.2.0", "merge": "^1.2.0",
......
import EthJSBlock from 'ethereumjs-block' import { Block, BlockHeader } from '@ethereumjs/block'
import { BN } from 'ethereumjs-util' import { BN } from 'ethereumjs-util'
export function generateBlock (executionContext) { export function generateBlock (executionContext) {
const block: EthJSBlock = new EthJSBlock({ const header: BlockHeader = BlockHeader.fromHeaderData({
header: { timestamp: (new Date().getTime() / 1000 | 0),
timestamp: (new Date().getTime() / 1000 | 0), number: 0,
number: 0, coinbase: '0x0e9281e9c6a0808672eaba6bd1220e144c9bb07a',
coinbase: '0x0e9281e9c6a0808672eaba6bd1220e144c9bb07a', difficulty: new BN('69762765929000', 10),
difficulty: (new BN('69762765929000', 10)), gasLimit: new BN('8000000').imuln(1)
gasLimit: new BN('8000000').imuln(1)
},
transactions: [],
uncleHeaders: []
}) })
const block: Block = new Block(header, [], [])
executionContext.vm().runBlock({ block: block, generate: true, skipBlockValidation: true, skipBalance: false }).then(() => { executionContext.vm().runBlock({ block: block, generate: true, skipBlockValidation: true, skipBalance: false }).then(() => {
executionContext.addBlock(block) executionContext.addBlock(block)
......
import { BN, privateToAddress, toChecksumAddress, isValidPrivate } from 'ethereumjs-util' import { BN, privateToAddress, toChecksumAddress, isValidPrivate, Address } from 'ethereumjs-util'
import { stripHexPrefix } from 'ethjs-util'
import Web3 from 'web3' import Web3 from 'web3'
import * as crypto from 'crypto' import * as crypto from 'crypto'
...@@ -44,19 +43,21 @@ export class Accounts { ...@@ -44,19 +43,21 @@ export class Accounts {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
privateKey = Buffer.from(privateKey, 'hex') privateKey = Buffer.from(privateKey, 'hex')
const address: Buffer = privateToAddress(privateKey) const address: Buffer = privateToAddress(privateKey)
const addressStr = toChecksumAddress('0x' + address.toString('hex'))
this.accounts[toChecksumAddress('0x' + address.toString('hex'))] = { privateKey, nonce: 0 } this.accounts[addressStr] = { privateKey, nonce: 0 }
this.accountsKeys[toChecksumAddress('0x' + address.toString('hex'))] = '0x' + privateKey.toString('hex') this.accountsKeys[addressStr] = '0x' + privateKey.toString('hex')
const stateManager = this.executionContext.vm().stateManager const stateManager = this.executionContext.vm().stateManager
stateManager.getAccount(address, (error, account) => { stateManager.getAccount(Address.fromString(addressStr)).then((account) => {
if (error) { account.balance = new BN(balance.replace('0x', '') || 'f00000000000000001', 16)
console.log(error) stateManager.putAccount(Address.fromString(addressStr), account).catch((error) => {
reject(error) reject(error)
return }).then(() => {
} resolve({})
account.balance = balance || '0xf00000000000000001' })
resolve() }).catch((error) => {
reject(error)
return
}) })
}) })
} }
...@@ -84,13 +85,12 @@ export class Accounts { ...@@ -84,13 +85,12 @@ export class Accounts {
eth_getBalance (payload, cb) { eth_getBalance (payload, cb) {
let address = payload.params[0] let address = payload.params[0]
address = stripHexPrefix(address)
this.executionContext.vm().stateManager.getAccount(Buffer.from(address, 'hex'), (err, account) => { this.executionContext.vm().stateManager.getAccount(Address.fromString(address)).then((account) => {
if (err) {
return cb(err)
}
cb(null, new BN(account.balance).toString(10)) cb(null, new BN(account.balance).toString(10))
}).catch((error) => {
cb(error)
}) })
} }
......
import Web3 from 'web3' import Web3 from 'web3'
import { toChecksumAddress, BN } from 'ethereumjs-util' import { toChecksumAddress, BN, Address } from 'ethereumjs-util'
import { processTx } from './txProcess' import { processTx } from './txProcess'
export class Transactions { export class Transactions {
...@@ -98,12 +98,11 @@ export class Transactions { ...@@ -98,12 +98,11 @@ export class Transactions {
eth_getTransactionCount (payload, cb) { eth_getTransactionCount (payload, cb) {
const address = payload.params[0] const address = payload.params[0]
this.executionContext.vm().stateManager.getAccount(address, (err, account) => { this.executionContext.vm().stateManager.getAccount(Address.fromString(address)).then((account) => {
if (err) {
return cb(err)
}
const nonce = new BN(account.nonce).toString(10) const nonce = new BN(account.nonce).toString(10)
cb(null, nonce) cb(null, nonce)
}).catch((error) => {
cb(error)
}) })
} }
......
...@@ -17,9 +17,9 @@ ...@@ -17,9 +17,9 @@
"dependencies": { "dependencies": {
"@remix-project/remix-lib": "^0.4.34", "@remix-project/remix-lib": "^0.4.34",
"eslint-scope": "^5.0.0", "eslint-scope": "^5.0.0",
"ethereumjs-block": "^2.2.2", "@ethereumjs/vm": "^5.3.2",
"ethereumjs-tx": "^2.1.2", "@ethereumjs/block": "^3.2.1",
"ethereumjs-vm": "4.1.3", "@ethereumjs/tx": "^3.1.3",
"solc": "^0.7.4", "solc": "^0.7.4",
"webworkify-webpack": "^2.1.5" "webworkify-webpack": "^2.1.5"
}, },
......
...@@ -150,7 +150,7 @@ export interface CompilerInputOptions { ...@@ -150,7 +150,7 @@ export interface CompilerInputOptions {
language?: Language language?: Language
} }
export type EVMVersion = 'homestead' | 'tangerineWhistle' | 'spuriousDragon' | 'byzantium' | 'constantinople' | 'petersburg' | 'istanbul' | 'muirGlacier' | null export type EVMVersion = 'homestead' | 'tangerineWhistle' | 'spuriousDragon' | 'byzantium' | 'constantinople' | 'petersburg' | 'istanbul' | 'muirGlacier' | 'berlin' | null
export type Language = 'Solidity' | 'Yul' export type Language = 'Solidity' | 'Yul'
......
...@@ -45,9 +45,9 @@ ...@@ -45,9 +45,9 @@
"color-support": "^1.1.3", "color-support": "^1.1.3",
"colors": "^1.1.2", "colors": "^1.1.2",
"commander": "^2.13.0", "commander": "^2.13.0",
"ethereumjs-block": "^2.2.2", "@ethereumjs/vm": "^5.3.2",
"ethereumjs-tx": "^2.1.2", "@ethereumjs/block": "^3.2.1",
"ethereumjs-vm": "4.1.3", "@ethereumjs/tx": "^3.1.3",
"express-ws": "^4.0.0", "express-ws": "^4.0.0",
"merge": "^1.2.0", "merge": "^1.2.0",
"signale": "^1.4.0", "signale": "^1.4.0",
......
This diff is collapsed.
...@@ -130,6 +130,10 @@ ...@@ -130,6 +130,10 @@
}, },
"dependencies": { "dependencies": {
"@erebos/bzz-node": "^0.13.0", "@erebos/bzz-node": "^0.13.0",
"@ethereumjs/block": "^3.2.1",
"@ethereumjs/common": "^2.2.0",
"@ethereumjs/tx": "^3.1.3",
"@ethereumjs/vm": "^5.3.2",
"@remixproject/engine": "^0.3.11", "@remixproject/engine": "^0.3.11",
"@remixproject/engine-web": "^0.3.11", "@remixproject/engine-web": "^0.3.11",
"@remixproject/plugin": "^0.3.11", "@remixproject/plugin": "^0.3.11",
...@@ -147,10 +151,7 @@ ...@@ -147,10 +151,7 @@
"commander": "^2.20.3", "commander": "^2.20.3",
"deep-equal": "^1.0.1", "deep-equal": "^1.0.1",
"document-register-element": "1.13.1", "document-register-element": "1.13.1",
"ethereumjs-block": "^2.2.2", "ethereumjs-util": "^7.0.10",
"ethereumjs-tx": "^2.1.2",
"ethereumjs-util": "^6.2.0",
"ethereumjs-vm": "4.1.3",
"ethers": "^5.1.4", "ethers": "^5.1.4",
"express-ws": "^4.0.0", "express-ws": "^4.0.0",
"fs-extra": "^3.0.1", "fs-extra": "^3.0.1",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment