parent
704e108d2f
commit
e66bbba396
@ -0,0 +1,227 @@ |
|||||||
|
'use strict' |
||||||
|
var Web3 = require('web3') |
||||||
|
var remixLib = require('remix-lib') |
||||||
|
var EventManager = remixLib.EventManager |
||||||
|
var EthJSVM = require('ethereumjs-vm') |
||||||
|
var ethUtil = require('ethereumjs-util') |
||||||
|
var StateManager = require('ethereumjs-vm/lib/stateManager') |
||||||
|
var Web3VMProvider = remixLib.vm.Web3VMProvider |
||||||
|
var rlp = ethUtil.rlp |
||||||
|
|
||||||
|
var injectedProvider |
||||||
|
|
||||||
|
var web3 |
||||||
|
if (typeof window.web3 !== 'undefined') { |
||||||
|
injectedProvider = window.web3.currentProvider |
||||||
|
web3 = new Web3(injectedProvider) |
||||||
|
} else { |
||||||
|
web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')) |
||||||
|
} |
||||||
|
|
||||||
|
var blankWeb3 = new Web3() |
||||||
|
|
||||||
|
/* |
||||||
|
extend vm state manager and instanciate VM |
||||||
|
*/ |
||||||
|
|
||||||
|
class StateManagerCommonStorageDump extends StateManager { |
||||||
|
constructor (arg) { |
||||||
|
super(arg) |
||||||
|
this.keyHashes = {} |
||||||
|
} |
||||||
|
|
||||||
|
putContractStorage (address, key, value, cb) { |
||||||
|
this.keyHashes[ethUtil.sha3(key).toString('hex')] = ethUtil.bufferToHex(key) |
||||||
|
super.putContractStorage(address, key, value, cb) |
||||||
|
} |
||||||
|
|
||||||
|
dumpStorage (address, cb) { |
||||||
|
var self = this |
||||||
|
this._getStorageTrie(address, function (err, trie) { |
||||||
|
if (err) { |
||||||
|
return cb(err) |
||||||
|
} |
||||||
|
var storage = {} |
||||||
|
var stream = trie.createReadStream() |
||||||
|
stream.on('data', function (val) { |
||||||
|
var value = rlp.decode(val.value) |
||||||
|
storage['0x' + val.key.toString('hex')] = { |
||||||
|
key: self.keyHashes[val.key.toString('hex')], |
||||||
|
value: '0x' + value.toString('hex') |
||||||
|
} |
||||||
|
}) |
||||||
|
stream.on('end', function () { |
||||||
|
cb(storage) |
||||||
|
}) |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
var stateManager = new StateManagerCommonStorageDump({}) |
||||||
|
var vm = new EthJSVM({ |
||||||
|
enableHomestead: true, |
||||||
|
activatePrecompiles: true |
||||||
|
}) |
||||||
|
|
||||||
|
// FIXME: move state manager in EthJSVM ctr
|
||||||
|
vm.stateManager = stateManager |
||||||
|
vm.blockchain = stateManager.blockchain |
||||||
|
vm.trie = stateManager.trie |
||||||
|
vm.stateManager.checkpoint() |
||||||
|
|
||||||
|
var web3VM = new Web3VMProvider() |
||||||
|
web3VM.setVM(vm) |
||||||
|
|
||||||
|
var mainNetGenesisHash = '0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3' |
||||||
|
|
||||||
|
/* |
||||||
|
trigger contextChanged, web3EndpointChanged |
||||||
|
*/ |
||||||
|
function ExecutionContext () { |
||||||
|
var self = this |
||||||
|
this.event = new EventManager() |
||||||
|
|
||||||
|
var executionContext = null |
||||||
|
|
||||||
|
this.init = function (config) { |
||||||
|
if (config.get('settings/always-use-vm')) { |
||||||
|
executionContext = 'vm' |
||||||
|
} else { |
||||||
|
executionContext = injectedProvider ? 'injected' : 'vm' |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
this.getProvider = function () { |
||||||
|
return executionContext |
||||||
|
} |
||||||
|
|
||||||
|
this.isVM = function () { |
||||||
|
return executionContext === 'vm' |
||||||
|
} |
||||||
|
|
||||||
|
this.web3 = function () { |
||||||
|
return this.isVM() ? web3VM : web3 |
||||||
|
} |
||||||
|
|
||||||
|
this.detectNetwork = function (callback) { |
||||||
|
if (this.isVM()) { |
||||||
|
callback(null, { id: '-', name: 'VM' }) |
||||||
|
} else { |
||||||
|
this.web3().version.getNetwork((err, id) => { |
||||||
|
var name = null |
||||||
|
if (err) name = 'Unknown' |
||||||
|
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md
|
||||||
|
else if (id === '1') name = 'Main' |
||||||
|
else if (id === '2') name = 'Morden (deprecated)' |
||||||
|
else if (id === '3') name = 'Ropsten' |
||||||
|
else if (id === '4') name = 'Rinkeby' |
||||||
|
else if (id === '42') name = 'Kovan' |
||||||
|
else name = 'Custom' |
||||||
|
|
||||||
|
if (id === '1') { |
||||||
|
this.web3().eth.getBlock(0, (error, block) => { |
||||||
|
if (error) console.log('cant query first block') |
||||||
|
if (block && block.hash !== mainNetGenesisHash) name = 'Custom' |
||||||
|
callback(err, { id, name }) |
||||||
|
}) |
||||||
|
} else { |
||||||
|
callback(err, { id, name }) |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
this.internalWeb3 = function () { |
||||||
|
return web3 |
||||||
|
} |
||||||
|
|
||||||
|
this.blankWeb3 = function () { |
||||||
|
return blankWeb3 |
||||||
|
} |
||||||
|
|
||||||
|
this.vm = function () { |
||||||
|
return vm |
||||||
|
} |
||||||
|
|
||||||
|
this.setContext = function (context, endPointUrl, confirmCb, infoCb) { |
||||||
|
executionContext = context |
||||||
|
this.executionContextChange(context, endPointUrl, confirmCb, infoCb) |
||||||
|
} |
||||||
|
|
||||||
|
this.executionContextChange = function (context, endPointUrl, confirmCb, infoCb, cb) { |
||||||
|
if (!cb) cb = () => {} |
||||||
|
|
||||||
|
if (context === 'vm') { |
||||||
|
executionContext = context |
||||||
|
vm.stateManager.revert(function () { |
||||||
|
vm.stateManager.checkpoint() |
||||||
|
}) |
||||||
|
self.event.trigger('contextChanged', ['vm']) |
||||||
|
return cb() |
||||||
|
} |
||||||
|
|
||||||
|
if (context === 'injected') { |
||||||
|
if (injectedProvider === undefined) { |
||||||
|
var alertMsg = 'No injected Web3 provider found. ' |
||||||
|
alertMsg += 'Make sure your provider (e.g. MetaMask) is active and running ' |
||||||
|
alertMsg += '(when recently activated you may have to reload the page).' |
||||||
|
infoCb(alertMsg) |
||||||
|
return cb() |
||||||
|
} else { |
||||||
|
executionContext = context |
||||||
|
web3.setProvider(injectedProvider) |
||||||
|
self.event.trigger('contextChanged', ['injected']) |
||||||
|
return cb() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (context === 'web3') { |
||||||
|
confirmCb(cb) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
this.currentblockGasLimit = function () { |
||||||
|
return this.blockGasLimit |
||||||
|
} |
||||||
|
|
||||||
|
this.blockGasLimitDefault = 4300000 |
||||||
|
this.blockGasLimit = this.blockGasLimitDefault |
||||||
|
setInterval(() => { |
||||||
|
if (this.getProvider() !== 'vm') { |
||||||
|
web3.eth.getBlock('latest', (err, block) => { |
||||||
|
if (!err) { |
||||||
|
// we can't use the blockGasLimit cause the next blocks could have a lower limit : https://github.com/ethereum/remix/issues/506
|
||||||
|
this.blockGasLimit = (block && block.gasLimit) ? Math.floor(block.gasLimit - (5 * block.gasLimit) / 1024) : this.blockGasLimitDefault |
||||||
|
} else { |
||||||
|
this.blockGasLimit = this.blockGasLimitDefault |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
}, 15000) |
||||||
|
|
||||||
|
// TODO: not used here anymore and needs to be moved
|
||||||
|
function setProviderFromEndpoint (endpoint, context, cb) { |
||||||
|
var oldProvider = web3.currentProvider |
||||||
|
|
||||||
|
if (endpoint === 'ipc') { |
||||||
|
web3.setProvider(new web3.providers.IpcProvider()) |
||||||
|
} else { |
||||||
|
web3.setProvider(new web3.providers.HttpProvider(endpoint)) |
||||||
|
} |
||||||
|
if (web3.isConnected()) { |
||||||
|
executionContext = context |
||||||
|
self.event.trigger('contextChanged', ['web3']) |
||||||
|
self.event.trigger('web3EndpointChanged') |
||||||
|
cb() |
||||||
|
} else { |
||||||
|
web3.setProvider(oldProvider) |
||||||
|
var alertMsg = 'Not possible to connect to the Web3 provider. ' |
||||||
|
alertMsg += 'Make sure the provider is running and a connection is open (via IPC or RPC).' |
||||||
|
cb(alertMsg) |
||||||
|
} |
||||||
|
} |
||||||
|
this.setProviderFromEndpoint = setProviderFromEndpoint |
||||||
|
} |
||||||
|
|
||||||
|
module.exports = new ExecutionContext() |
||||||
|
|
Loading…
Reference in new issue