Merge pull request #888 from ethereum/add_remix_simulator

Add remix simulator to main branch
pull/7/head
Iuri Matias 6 years ago committed by GitHub
commit 2cffd838a2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      remix-debug/index.js
  2. 2
      remix-simulator/README.md
  3. 4
      remix-simulator/bin/ethsim
  4. 5
      remix-simulator/index.js
  5. 86
      remix-simulator/package.json
  6. 22
      remix-simulator/src/methods/accounts.js
  7. 42
      remix-simulator/src/methods/blocks.js
  8. 16
      remix-simulator/src/methods/misc.js
  9. 63
      remix-simulator/src/methods/transactions.js
  10. 96
      remix-simulator/src/methods/txProcess.js
  11. 15
      remix-simulator/src/methods/whisper.js
  12. 41
      remix-simulator/src/provider.js
  13. 25
      remix-simulator/src/server.js
  14. 81
      remix-simulator/src/utils/logs.js

@ -30,6 +30,7 @@ module.exports = {
storage: {
StorageViewer: StorageViewer,
StorageResolver: StorageResolver
}
},
SolidityDecoder: SolidityDecoder
}

@ -0,0 +1,2 @@
# `remix-simulator`

@ -0,0 +1,4 @@
#!/usr/bin/env node
require('../src/server');

@ -0,0 +1,5 @@
var Provider = require('./src/provider')
module.exports = {
Provider: Provider
}

@ -0,0 +1,86 @@
{
"name": "remix-simulator",
"version": "0.0.3",
"description": "Ethereum IDE and tools for the web",
"contributors": [
{
"name": "Iuri Matias",
"email": "iuri@ethereum.org"
},
{
"name": "Yann Levreau",
"email": "yann@ethdev.com"
}
],
"main": "./index.js",
"dependencies": {
"ansi-gray": "^0.1.1",
"babel-plugin-transform-object-assign": "^6.22.0",
"babel-preset-es2017": "^6.24.1",
"babelify": "^7.3.0",
"body-parser": "^1.18.2",
"color-support": "^1.1.3",
"express": "^4.16.3",
"fast-async": "^6.3.7",
"merge": "^1.2.0",
"remix-lib": "^0.2.5",
"standard": "^10.0.3",
"time-stamp": "^2.0.0",
"web3": "1.0.0-beta.27"
},
"scripts": {
"test": "standard"
},
"bin": {
"ethsim": "./bin/ethsim",
"remix-simulator": "./bin/ethsim"
},
"standard": {
"ignore": [
"node_modules/*"
],
"parser": "babel-eslint"
},
"repository": {
"type": "git",
"url": "git+https://github.com/ethereum/remix.git"
},
"author": "remix team",
"license": "MIT",
"bugs": {
"url": "https://github.com/ethereum/remix/issues"
},
"homepage": "https://github.com/ethereum/remix#readme",
"browserify": {
"transform": [
[
"babelify",
{
"plugins": [
[
"fast-async",
{
"runtimePatten": null,
"compiler": {
"promises": true,
"es7": true,
"noRuntime": true,
"wrapAwait": true
}
}
],
"transform-object-assign"
]
}
],
[
"babelify",
{
"presets": [
"es2017"
]
}
]
]
}
}

@ -0,0 +1,22 @@
var Web3 = require('web3')
var Accounts = function () {
this.web3 = new Web3()
// TODO: make it random and/or use remix-libs
this.accounts = [this.web3.eth.accounts.create(['abcd'])]
this.accounts[this.accounts[0].address.toLowerCase()] = this.accounts[0]
this.accounts[this.accounts[0].address.toLowerCase()].privateKey = Buffer.from(this.accounts[this.accounts[0].address.toLowerCase()].privateKey.slice(2), 'hex')
}
Accounts.prototype.methods = function () {
return {
eth_accounts: this.eth_accounts.bind(this)
}
}
Accounts.prototype.eth_accounts = function (payload, cb) {
return cb(null, this.accounts.map((x) => x.address))
}
module.exports = Accounts

@ -0,0 +1,42 @@
var Blocks = function () {
}
Blocks.prototype.methods = function () {
return {
eth_getBlockByNumber: this.eth_getBlockByNumber.bind(this),
eth_gasPrice: this.eth_gasPrice.bind(this)
}
}
Blocks.prototype.eth_getBlockByNumber = function (payload, cb) {
let b = {
'difficulty': '0x0',
'extraData': '0x',
'gasLimit': '0x7a1200',
'gasUsed': '0x0',
'hash': '0xdb731f3622ef37b4da8db36903de029220dba74c41185f8429f916058b86559f',
'logsBloom': '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
'miner': '0x3333333333333333333333333333333333333333',
'mixHash': '0x0000000000000000000000000000000000000000000000000000000000000000',
'nonce': '0x0000000000000042',
'number': '0x0',
'parentHash': '0x0000000000000000000000000000000000000000000000000000000000000000',
'receiptsRoot': '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
'sha3Uncles': '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347',
'size': '0x1f8',
'stateRoot': '0xb7917653f92e62394d2207d0f39a1320ff1cb93d1cee80d3c492627e00b219ff',
'timestamp': '0x0',
'totalDifficulty': '0x0',
'transactions': [],
'transactionsRoot': '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
'uncles': []
}
cb(null, b)
}
Blocks.prototype.eth_gasPrice = function (payload, cb) {
cb(null, 1)
}
module.exports = Blocks

@ -0,0 +1,16 @@
var version = require('../../package.json').version
var Misc = function () {
}
Misc.prototype.methods = function () {
return {
web3_clientVersion: this.web3_clientVersion.bind(this)
}
}
Misc.prototype.web3_clientVersion = function (payload, cb) {
cb(null, 'Remix Simulator/' + version)
}
module.exports = Misc

@ -0,0 +1,63 @@
var RemixLib = require('remix-lib')
var executionContext = RemixLib.execution.executionContext
var processTx = require('./txProcess.js')
var Transactions = function (accounts) {
this.accounts = accounts
// TODO: fix me; this is a temporary and very hackish thing just to get the getCode working for now
this.deployedContracts = {}
}
Transactions.prototype.methods = function () {
return {
eth_sendTransaction: this.eth_sendTransaction.bind(this),
eth_getTransactionReceipt: this.eth_getTransactionReceipt.bind(this),
eth_getCode: this.eth_getCode.bind(this),
eth_call: this.eth_call.bind(this),
eth_estimateGas: this.eth_estimateGas.bind(this)
}
}
Transactions.prototype.eth_sendTransaction = function (payload, cb) {
processTx(this.accounts, payload, false, cb)
}
Transactions.prototype.eth_getTransactionReceipt = function (payload, cb) {
const self = this
executionContext.web3().eth.getTransactionReceipt(payload.params[0], (error, receipt) => {
if (error) {
return cb(error)
}
self.deployedContracts[receipt.contractAddress] = receipt.data
var r = {
'transactionHash': receipt.hash,
'transactionIndex': '0x00',
'blockHash': '0x766d18646a06cf74faeabf38597314f84a82c3851859d9da9d94fc8d037269e5',
'blockNumber': '0x06',
'gasUsed': '0x06345f',
'cumulativeGasUsed': '0x06345f',
'contractAddress': receipt.contractAddress,
'logs': receipt.logs,
'status': 1
}
cb(null, r)
})
}
Transactions.prototype.eth_estimateGas = function (payload, cb) {
cb(null, 3000000)
}
Transactions.prototype.eth_getCode = function (payload, cb) {
let address = payload.params[0]
cb(null, this.deployedContracts[address] || '0x')
}
Transactions.prototype.eth_call = function (payload, cb) {
processTx(this.accounts, payload, true, cb)
}
module.exports = Transactions

@ -0,0 +1,96 @@
var RemixLib = require('remix-lib')
var TxExecution = RemixLib.execution.txExecution
var TxRunner = RemixLib.execution.txRunner
var executionContext = RemixLib.execution.executionContext
function runCall (payload, from, to, data, value, gasLimit, txRunner, callbacks, callback) {
let finalCallback = function (err, result) {
if (err) {
return callback(err)
}
let toReturn = '0x' + result.result.vm.return.toString('hex')
if (toReturn === '0x') {
toReturn = '0x0'
}
return callback(null, toReturn)
}
TxExecution.callFunction(from, to, data, value, gasLimit, null, txRunner, callbacks, finalCallback, true)
}
function runTx (payload, from, to, data, value, gasLimit, txRunner, callbacks, callback) {
let finalCallback = function (err, result) {
if (err) {
return callback(err)
}
callback(null, result.transactionHash)
}
TxExecution.callFunction(from, to, data, value, gasLimit, null, txRunner, callbacks, finalCallback, false)
}
function createContract (payload, from, data, value, gasLimit, txRunner, callbacks, callback) {
let finalCallback = function (err, result) {
if (err) {
return callback(err)
}
callback(null, result.transactionHash)
}
TxExecution.createContract(from, data, value, gasLimit, txRunner, callbacks, finalCallback)
}
function processTx (accounts, payload, isCall, callback) {
let api = {
logMessage: (msg) => {
},
logHtmlMessage: (msg) => {
},
config: {
getUnpersistedProperty: (key) => {
return true
},
get: () => {
return true
}
},
detectNetwork: (cb) => {
cb()
},
personalMode: () => {
return false
}
}
executionContext.init(api.config)
let txRunner = new TxRunner(accounts, api)
let { from, to, data, value, gas } = payload.params[0]
gas = gas || 3000000
let callbacks = {
confirmationCb: (network, tx, gasEstimation, continueTxExecution, cancelCb) => {
continueTxExecution(null)
},
gasEstimationForceSend: (error, continueTxExecution, cancelCb) => {
if (error) {
continueTxExecution(error)
}
continueTxExecution()
},
promptCb: (okCb, cancelCb) => {
okCb()
}
}
if (isCall) {
runCall(payload, from, to, data, value, gas, txRunner, callbacks, callback)
} else if (to) {
runTx(payload, from, to, data, value, gas, txRunner, callbacks, callback)
} else {
createContract(payload, from, data, value, gas, txRunner, callbacks, callback)
}
}
module.exports = processTx

@ -0,0 +1,15 @@
var Whisper = function () {
}
Whisper.prototype.methods = function () {
return {
shh_version: this.shh_version.bind(this)
}
}
Whisper.prototype.shh_version = function (payload, cb) {
cb(null, 5)
}
module.exports = Whisper

@ -0,0 +1,41 @@
const log = require('./utils/logs.js')
const merge = require('merge')
const Accounts = require('./methods/accounts.js')
const Blocks = require('./methods/blocks.js')
const Misc = require('./methods/misc.js')
const Transactions = require('./methods/transactions.js')
const Whisper = require('./methods/whisper.js')
var Provider = function () {
this.Accounts = new Accounts()
this.methods = {}
this.methods = merge(this.methods, this.Accounts.methods())
this.methods = merge(this.methods, (new Blocks()).methods())
this.methods = merge(this.methods, (new Misc()).methods())
this.methods = merge(this.methods, (new Transactions(this.Accounts.accounts)).methods())
this.methods = merge(this.methods, (new Whisper()).methods())
}
Provider.prototype.sendAsync = function (payload, callback) {
log.info('payload method is ', payload.method)
let method = this.methods[payload.method]
if (method) {
return method.call(method, payload, (err, result) => {
if (err) {
return callback(err)
}
let response = {'id': payload.id, 'jsonrpc': '2.0', 'result': result}
callback(null, response)
})
}
callback(new Error('unknown method ' + payload.method))
}
Provider.prototype.isConnected = function () {
return true
}
module.exports = Provider

@ -0,0 +1,25 @@
const express = require('express')
const bodyParser = require('body-parser')
const app = express()
const Provider = require('./provider')
const log = require('./utils/logs.js')
var provider = new Provider()
app.use(bodyParser.urlencoded({extended: true}))
app.use(bodyParser.json())
app.get('/', (req, res) => {
res.send('Welcome to remix-simulator')
})
app.use(function (req, res) {
provider.sendAsync(req.body, (err, jsonResponse) => {
if (err) {
res.send({error: err})
}
res.send(jsonResponse)
})
})
app.listen(8545, () => log('Remix Simulator listening on port 8545!'))

@ -0,0 +1,81 @@
'use strict';
var gray = require('ansi-gray');
var timestamp = require('time-stamp');
var supportsColor = require('color-support');
function hasFlag(flag) {
return ((typeof(process) !== 'undefined') && (process.argv.indexOf('--' + flag) !== -1));
}
function addColor(str) {
if (hasFlag('no-color')) {
return str;
}
if (hasFlag('color')) {
return gray(str);
}
if (supportsColor()) {
return gray(str);
}
return str;
}
let logger = {
stdout: function(arg) {
if (typeof(process) === 'undefined' || !process.stdout) return;
process.stdout.write(arg);
},
stderr: function(arg) {
if (typeof(process) === 'undefined' || process.stderr) return;
process.stderr.write(arg);
},
};
function getTimestamp(){
return '['+addColor(timestamp('HH:mm:ss'))+']';
}
function log(){
var time = getTimestamp();
logger.stdout(time + ' ');
console.log.apply(console, arguments);
return this;
}
function info(){
var time = getTimestamp();
logger.stdout(time + ' ');
console.info.apply(console, arguments);
return this;
}
function dir(){
var time = getTimestamp();
logger.stdout(time + ' ');
console.dir.apply(console, arguments);
return this;
}
function warn(){
var time = getTimestamp();
logger.stderr(time + ' ');
console.warn.apply(console, arguments);
return this;
}
function error(){
var time = getTimestamp();
logger.stderr(time + ' ');
console.error.apply(console, arguments);
return this;
}
module.exports = log;
module.exports.info = info;
module.exports.dir = dir;
module.exports.warn = warn;
module.exports.error = error;
Loading…
Cancel
Save