mirror of https://github.com/embarklabs/embark.git
cherry-pick whisper fixes
This commit is contained in:
parent
3fe5b93a1f
commit
c849d8a777
|
@ -1,11 +1,12 @@
|
||||||
{
|
{
|
||||||
"default": {
|
"default": {
|
||||||
"enabled": true,
|
"client": "geth",
|
||||||
"provider": "whisper",
|
"provider": "whisper",
|
||||||
|
"enabled": true,
|
||||||
"available_providers": ["whisper"],
|
"available_providers": ["whisper"],
|
||||||
"connection": {
|
"connection": {
|
||||||
"host": "localhost",
|
"host": "localhost",
|
||||||
"port": 8546,
|
"port": 3777,
|
||||||
"type": "ws"
|
"type": "ws"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,446 @@
|
||||||
|
import { __ } from 'embark-i18n';
|
||||||
|
const fs = require('fs-extra');
|
||||||
|
const async = require('async');
|
||||||
|
const {spawn, exec} = require('child_process');
|
||||||
|
const path = require('path');
|
||||||
|
const constants = require('embark-core/constants');
|
||||||
|
const GethClient = require('./gethClient.js');
|
||||||
|
const ParityClient = require('./parityClient.js');
|
||||||
|
import { IPC } from 'embark-core';
|
||||||
|
|
||||||
|
import { compact, dappPath, defaultHost, dockerHostSwap, embarkPath} from 'embark-utils';
|
||||||
|
const Logger = require('embark-logger');
|
||||||
|
|
||||||
|
// time between IPC connection attempts (in ms)
|
||||||
|
const IPC_CONNECT_INTERVAL = 2000;
|
||||||
|
|
||||||
|
/*eslint complexity: ["error", 50]*/
|
||||||
|
var Blockchain = function(userConfig, clientClass) {
|
||||||
|
this.userConfig = userConfig;
|
||||||
|
this.env = userConfig.env || 'development';
|
||||||
|
this.isDev = userConfig.isDev;
|
||||||
|
this.onReadyCallback = userConfig.onReadyCallback || (() => {});
|
||||||
|
this.onExitCallback = userConfig.onExitCallback;
|
||||||
|
this.logger = userConfig.logger || new Logger({logLevel: 'debug', context: constants.contexts.blockchain}); // do not pass in events as we don't want any log events emitted
|
||||||
|
this.events = userConfig.events;
|
||||||
|
this.isStandalone = userConfig.isStandalone;
|
||||||
|
this.certOptions = userConfig.certOptions;
|
||||||
|
|
||||||
|
|
||||||
|
let defaultWsApi = clientClass.DEFAULTS.WS_API;
|
||||||
|
if (this.isDev) defaultWsApi = clientClass.DEFAULTS.DEV_WS_API;
|
||||||
|
|
||||||
|
this.config = {
|
||||||
|
silent: this.userConfig.silent,
|
||||||
|
client: this.userConfig.client,
|
||||||
|
ethereumClientBin: this.userConfig.ethereumClientBin || this.userConfig.client,
|
||||||
|
networkType: this.userConfig.networkType || clientClass.DEFAULTS.NETWORK_TYPE,
|
||||||
|
networkId: this.userConfig.networkId || clientClass.DEFAULTS.NETWORK_ID,
|
||||||
|
genesisBlock: this.userConfig.genesisBlock || false,
|
||||||
|
datadir: this.userConfig.datadir,
|
||||||
|
mineWhenNeeded: this.userConfig.mineWhenNeeded || false,
|
||||||
|
rpcHost: dockerHostSwap(this.userConfig.rpcHost) || defaultHost,
|
||||||
|
rpcPort: this.userConfig.rpcPort || 8545,
|
||||||
|
rpcCorsDomain: this.userConfig.rpcCorsDomain || false,
|
||||||
|
rpcApi: this.userConfig.rpcApi || clientClass.DEFAULTS.RPC_API,
|
||||||
|
port: this.userConfig.port || 30303,
|
||||||
|
nodiscover: this.userConfig.nodiscover || false,
|
||||||
|
mine: this.userConfig.mine || false,
|
||||||
|
account: {},
|
||||||
|
whisper: (this.userConfig.whisper !== false),
|
||||||
|
maxpeers: ((this.userConfig.maxpeers === 0) ? 0 : (this.userConfig.maxpeers || 25)),
|
||||||
|
bootnodes: this.userConfig.bootnodes || "",
|
||||||
|
wsRPC: (this.userConfig.wsRPC !== false),
|
||||||
|
wsHost: dockerHostSwap(this.userConfig.wsHost) || defaultHost,
|
||||||
|
wsPort: this.userConfig.wsPort || 8546,
|
||||||
|
wsOrigins: this.userConfig.wsOrigins || false,
|
||||||
|
wsApi: this.userConfig.wsApi || defaultWsApi,
|
||||||
|
vmdebug: this.userConfig.vmdebug || false,
|
||||||
|
targetGasLimit: this.userConfig.targetGasLimit || false,
|
||||||
|
syncMode: this.userConfig.syncMode || this.userConfig.syncmode,
|
||||||
|
verbosity: this.userConfig.verbosity
|
||||||
|
};
|
||||||
|
|
||||||
|
this.devFunds = null;
|
||||||
|
|
||||||
|
if (this.userConfig.accounts) {
|
||||||
|
const nodeAccounts = this.userConfig.accounts.find(account => account.nodeAccounts);
|
||||||
|
if (nodeAccounts) {
|
||||||
|
this.config.account = {
|
||||||
|
numAccounts: nodeAccounts.numAddresses || 1,
|
||||||
|
password: nodeAccounts.password,
|
||||||
|
balance: nodeAccounts.balance
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.userConfig === {} || this.userConfig.default || JSON.stringify(this.userConfig) === '{"client":"geth"}') {
|
||||||
|
if (this.env === 'development') {
|
||||||
|
this.isDev = true;
|
||||||
|
} else {
|
||||||
|
this.config.genesisBlock = embarkPath("templates/boilerplate/config/privatenet/genesis.json");
|
||||||
|
}
|
||||||
|
this.config.datadir = dappPath(".embark/development/datadir");
|
||||||
|
this.config.wsOrigins = this.config.wsOrigins || "http://localhost:8000";
|
||||||
|
this.config.rpcCorsDomain = this.config.rpcCorsDomain || "http://localhost:8000";
|
||||||
|
this.config.targetGasLimit = 8000000;
|
||||||
|
}
|
||||||
|
this.config.account.devPassword = path.join(this.config.datadir, "devPassword");
|
||||||
|
|
||||||
|
const spaceMessage = 'The path for %s in blockchain config contains spaces, please remove them';
|
||||||
|
if (this.config.datadir && this.config.datadir.indexOf(' ') > 0) {
|
||||||
|
this.logger.error(__(spaceMessage, 'datadir'));
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
if (this.config.account.password && this.config.account.password.indexOf(' ') > 0) {
|
||||||
|
this.logger.error(__(spaceMessage, 'accounts.password'));
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
if (this.config.genesisBlock && this.config.genesisBlock.indexOf(' ') > 0) {
|
||||||
|
this.logger.error(__(spaceMessage, 'genesisBlock'));
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
this.client = new clientClass({config: this.config, env: this.env, isDev: this.isDev});
|
||||||
|
|
||||||
|
this.initStandaloneProcess();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Polls for a connection to an IPC server (generally this is set up
|
||||||
|
* in the Embark process). Once connected, any logs logged to the
|
||||||
|
* Logger will be shipped off to the IPC server. In the case of `embark
|
||||||
|
* run`, the BlockchainListener module is listening for these logs.
|
||||||
|
*
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
Blockchain.prototype.initStandaloneProcess = function () {
|
||||||
|
if (this.isStandalone) {
|
||||||
|
let logQueue = [];
|
||||||
|
|
||||||
|
// on every log logged in logger (say that 3x fast), send the log
|
||||||
|
// to the IPC serve listening (only if we're connected of course)
|
||||||
|
this.logger.events.on('log', (logLevel, message) => {
|
||||||
|
if (this.ipc.connected) {
|
||||||
|
this.ipc.request('blockchain:log', {logLevel, message});
|
||||||
|
} else {
|
||||||
|
logQueue.push({logLevel, message});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.ipc = new IPC({ipcRole: 'client'});
|
||||||
|
|
||||||
|
// Wait for an IPC server to start (ie `embark run`) by polling `.connect()`.
|
||||||
|
// Do not kill this interval as the IPC server may restart (ie restart
|
||||||
|
// `embark run` without restarting `embark blockchain`)
|
||||||
|
setInterval(() => {
|
||||||
|
if (!this.ipc.connected) {
|
||||||
|
this.ipc.connect(() => {
|
||||||
|
if (this.ipc.connected) {
|
||||||
|
logQueue.forEach(message => { this.ipc.request('blockchain:log', message); });
|
||||||
|
logQueue = [];
|
||||||
|
this.ipc.client.on('process:blockchain:stop', () => {
|
||||||
|
this.kill();
|
||||||
|
process.exit(0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, IPC_CONNECT_INTERVAL);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Blockchain.prototype.runCommand = function (cmd, options, callback) {
|
||||||
|
this.logger.info(__("running: %s", cmd.underline).green);
|
||||||
|
if (this.config.silent) {
|
||||||
|
options.silent = true;
|
||||||
|
}
|
||||||
|
return exec(cmd, options, callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
Blockchain.prototype.run = function () {
|
||||||
|
var self = this;
|
||||||
|
this.logger.info("===============================================================================".magenta);
|
||||||
|
this.logger.info("===============================================================================".magenta);
|
||||||
|
this.logger.info(__("Embark Blockchain using %s", self.client.prettyName.underline).magenta);
|
||||||
|
this.logger.info("===============================================================================".magenta);
|
||||||
|
this.logger.info("===============================================================================".magenta);
|
||||||
|
|
||||||
|
if (self.client.name === constants.blockchain.clients.geth) this.checkPathLength();
|
||||||
|
|
||||||
|
let address = '';
|
||||||
|
async.waterfall([
|
||||||
|
function checkInstallation(next) {
|
||||||
|
self.isClientInstalled((err) => {
|
||||||
|
if (err) {
|
||||||
|
return next({message: err});
|
||||||
|
}
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function init(next) {
|
||||||
|
if (self.isDev) {
|
||||||
|
return self.initDevChain((err) => {
|
||||||
|
next(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return self.initChainAndGetAddress((err, addr) => {
|
||||||
|
address = addr;
|
||||||
|
next(err);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function getMainCommand(next) {
|
||||||
|
self.client.mainCommand(address, function (cmd, args) {
|
||||||
|
next(null, cmd, args);
|
||||||
|
}, true);
|
||||||
|
}
|
||||||
|
], function(err, cmd, args) {
|
||||||
|
if (err) {
|
||||||
|
self.logger.error(err.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
args = compact(args);
|
||||||
|
|
||||||
|
let full_cmd = cmd + " " + args.join(' ');
|
||||||
|
self.logger.info(__(">>>>>>>>>>>>>>>>> running: %s", full_cmd.underline).green);
|
||||||
|
self.child = spawn(cmd, args, {cwd: process.cwd()});
|
||||||
|
|
||||||
|
self.child.on('error', (err) => {
|
||||||
|
err = err.toString();
|
||||||
|
self.logger.error('Blockchain error: ', err);
|
||||||
|
if (self.env === 'development' && err.indexOf('Failed to unlock') > 0) {
|
||||||
|
self.logger.error('\n' + __('Development blockchain has changed to use the --dev option.').yellow);
|
||||||
|
self.logger.error(__('You can reset your workspace to fix the problem with').yellow + ' embark reset'.cyan);
|
||||||
|
self.logger.error(__('Otherwise, you can change your data directory in blockchain.json (datadir)').yellow);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// TOCHECK I don't understand why stderr and stdout are reverted.
|
||||||
|
// This happens with Geth and Parity, so it does not seems a client problem
|
||||||
|
self.child.stdout.on('data', (data) => {
|
||||||
|
self.logger.info(`${self.client.name} error: ${data}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
self.child.stderr.on('data', async (data) => {
|
||||||
|
data = data.toString();
|
||||||
|
if (!self.readyCalled && self.client.isReady(data)) {
|
||||||
|
self.readyCalled = true;
|
||||||
|
self.readyCallback();
|
||||||
|
}
|
||||||
|
self.logger.info(`${self.client.name}: ${data}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
self.child.on('exit', (code) => {
|
||||||
|
let strCode;
|
||||||
|
if (code) {
|
||||||
|
strCode = 'with error code ' + code;
|
||||||
|
} else {
|
||||||
|
strCode = 'with no error code (manually killed?)';
|
||||||
|
}
|
||||||
|
self.logger.error(self.client.name + ' exited ' + strCode);
|
||||||
|
if (self.onExitCallback) {
|
||||||
|
self.onExitCallback();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
self.child.on('uncaughtException', (err) => {
|
||||||
|
self.logger.error('Uncaught ' + self.client.name + ' exception', err);
|
||||||
|
if (self.onExitCallback) {
|
||||||
|
self.onExitCallback();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Blockchain.prototype.readyCallback = function () {
|
||||||
|
if (this.onReadyCallback) {
|
||||||
|
this.onReadyCallback();
|
||||||
|
}
|
||||||
|
if (this.config.mineWhenNeeded && !this.isDev) {
|
||||||
|
this.miner = this.client.getMiner();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Blockchain.prototype.kill = function () {
|
||||||
|
if (this.child) {
|
||||||
|
this.child.kill();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Blockchain.prototype.checkPathLength = function () {
|
||||||
|
let _dappPath = dappPath('');
|
||||||
|
if (_dappPath.length > 66) {
|
||||||
|
// this.logger.error is captured and sent to the console output regardless of silent setting
|
||||||
|
this.logger.error("===============================================================================".yellow);
|
||||||
|
this.logger.error("===========> ".yellow + __('WARNING! ÐApp path length is too long: ').yellow + _dappPath.yellow);
|
||||||
|
this.logger.error("===========> ".yellow + __('This is known to cause issues with starting geth, please consider reducing your ÐApp path\'s length to 66 characters or less.').yellow);
|
||||||
|
this.logger.error("===============================================================================".yellow);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Blockchain.prototype.isClientInstalled = function (callback) {
|
||||||
|
let versionCmd = this.client.determineVersionCommand();
|
||||||
|
this.runCommand(versionCmd, {}, (err, stdout, stderr) => {
|
||||||
|
if (err || !stdout || stderr.indexOf("not found") >= 0 || stdout.indexOf("not found") >= 0) {
|
||||||
|
return callback(__('Ethereum client bin not found:') + ' ' + this.client.getBinaryPath());
|
||||||
|
}
|
||||||
|
const parsedVersion = this.client.parseVersion(stdout);
|
||||||
|
const supported = this.client.isSupportedVersion(parsedVersion);
|
||||||
|
if (supported === undefined) {
|
||||||
|
this.logger.error((__('WARNING! Ethereum client version could not be determined or compared with version range') + ' ' + this.client.versSupported + __(', for best results please use a supported version')).yellow);
|
||||||
|
} else if (!supported) {
|
||||||
|
this.logger.error((__('WARNING! Ethereum client version unsupported, for best results please use a version in range') + ' ' + this.client.versSupported).yellow);
|
||||||
|
}
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Blockchain.prototype.initDevChain = function(callback) {
|
||||||
|
const self = this;
|
||||||
|
const ACCOUNTS_ALREADY_PRESENT = 'accounts_already_present';
|
||||||
|
// Init the dev chain
|
||||||
|
self.client.initDevChain(self.config.datadir, (err) => {
|
||||||
|
if (err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
const accountsToCreate = self.config.account && self.config.account.numAccounts;
|
||||||
|
if (!accountsToCreate) return callback();
|
||||||
|
|
||||||
|
// Create other accounts
|
||||||
|
async.waterfall([
|
||||||
|
function listAccounts(next) {
|
||||||
|
self.runCommand(self.client.listAccountsCommand(), {}, (err, stdout, _stderr) => {
|
||||||
|
if (err || stdout === undefined || stdout.indexOf("Fatal") >= 0) {
|
||||||
|
console.log(__("no accounts found").green);
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
// List current addresses
|
||||||
|
self.config.unlockAddressList = self.client.parseListAccountsCommandResultToAddressList(stdout);
|
||||||
|
// Count current addresses and remove the default account from the count (because password can be different)
|
||||||
|
let addressCount = self.config.unlockAddressList.length;
|
||||||
|
if (addressCount < accountsToCreate) {
|
||||||
|
next(null, accountsToCreate - addressCount);
|
||||||
|
} else {
|
||||||
|
next(ACCOUNTS_ALREADY_PRESENT);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function newAccounts(accountsToCreate, next) {
|
||||||
|
var accountNumber = 0;
|
||||||
|
async.whilst(
|
||||||
|
function() {
|
||||||
|
return accountNumber < accountsToCreate;
|
||||||
|
},
|
||||||
|
function(callback) {
|
||||||
|
accountNumber++;
|
||||||
|
self.runCommand(self.client.newAccountCommand(), {}, (err, stdout, _stderr) => {
|
||||||
|
if (err) {
|
||||||
|
return callback(err, accountNumber);
|
||||||
|
}
|
||||||
|
self.config.unlockAddressList.push(self.client.parseNewAccountCommandResultToAddress(stdout));
|
||||||
|
callback(null, accountNumber);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function(err) {
|
||||||
|
next(err);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
], (err) => {
|
||||||
|
if (err && err !== ACCOUNTS_ALREADY_PRESENT) {
|
||||||
|
console.log(err);
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Blockchain.prototype.initChainAndGetAddress = function (callback) {
|
||||||
|
const self = this;
|
||||||
|
let address = null;
|
||||||
|
const ALREADY_INITIALIZED = 'already';
|
||||||
|
|
||||||
|
// ensure datadir exists, bypassing the interactive liabilities prompt.
|
||||||
|
self.datadir = self.config.datadir;
|
||||||
|
|
||||||
|
async.waterfall([
|
||||||
|
function makeDir(next) {
|
||||||
|
fs.mkdirp(self.datadir, (err, _result) => {
|
||||||
|
next(err);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function listAccounts(next) {
|
||||||
|
self.runCommand(self.client.listAccountsCommand(), {}, (err, stdout, _stderr) => {
|
||||||
|
if (err || stdout === undefined || stdout.indexOf("Fatal") >= 0) {
|
||||||
|
self.logger.info(__("no accounts found").green);
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
let firstAccountFound = self.client.parseListAccountsCommandResultToAddress(stdout);
|
||||||
|
if (firstAccountFound === undefined || firstAccountFound === "") {
|
||||||
|
console.log(__("no accounts found").green);
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
self.logger.info(__("already initialized").green);
|
||||||
|
address = firstAccountFound;
|
||||||
|
next(ALREADY_INITIALIZED);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function genesisBlock(next) {
|
||||||
|
//There's no genesis init with Parity. Custom network are set in the chain property at startup
|
||||||
|
if (!self.config.genesisBlock || self.client.name === constants.blockchain.clients.parity) {
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
self.logger.info(__("initializing genesis block").green);
|
||||||
|
self.runCommand(self.client.initGenesisCommmand(), {}, (err, _stdout, _stderr) => {
|
||||||
|
next(err);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function newAccount(next) {
|
||||||
|
self.runCommand(self.client.newAccountCommand(), {}, (err, stdout, _stderr) => {
|
||||||
|
if (err) {
|
||||||
|
return next(err);
|
||||||
|
}
|
||||||
|
address = self.client.parseNewAccountCommandResultToAddress(stdout);
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
], (err) => {
|
||||||
|
if (err === ALREADY_INITIALIZED) {
|
||||||
|
err = null;
|
||||||
|
}
|
||||||
|
callback(err, address);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export function BlockchainClient(userConfig, options) {
|
||||||
|
if ((userConfig === {} || JSON.stringify(userConfig) === '{"enabled":true}') && options.env !== 'development') {
|
||||||
|
options.logger.info("===> " + __("warning: running default config on a non-development environment"));
|
||||||
|
}
|
||||||
|
// if client is not set in preferences, default is geth
|
||||||
|
if (!userConfig.client) userConfig.client = constants.blockchain.clients.geth;
|
||||||
|
// if clientName is set, it overrides preferences
|
||||||
|
if (options.clientName) userConfig.client = options.clientName;
|
||||||
|
// Choose correct client instance based on clientName
|
||||||
|
let clientClass;
|
||||||
|
switch (userConfig.client) {
|
||||||
|
case constants.blockchain.clients.geth:
|
||||||
|
clientClass = GethClient;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case constants.blockchain.clients.parity:
|
||||||
|
clientClass = ParityClient;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.error(__('Unknown client "%s". Please use one of the following: %s', userConfig.client, Object.keys(constants.blockchain.clients).join(', ')));
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
userConfig.isDev = (userConfig.isDev || userConfig.default);
|
||||||
|
userConfig.env = options.env;
|
||||||
|
userConfig.onReadyCallback = options.onReadyCallback;
|
||||||
|
userConfig.onExitCallback = options.onExitCallback;
|
||||||
|
userConfig.logger = options.logger;
|
||||||
|
userConfig.certOptions = options.certOptions;
|
||||||
|
userConfig.isStandalone = options.isStandalone;
|
||||||
|
return new Blockchain(userConfig, clientClass);
|
||||||
|
}
|
|
@ -0,0 +1,116 @@
|
||||||
|
import { __ } from 'embark-i18n';
|
||||||
|
import {dappPath, canonicalHost, defaultHost} from 'embark-utils';
|
||||||
|
let Web3 = require('web3');
|
||||||
|
const constants = require('embark-core/constants');
|
||||||
|
const API = require('./api.js');
|
||||||
|
|
||||||
|
class Whisper {
|
||||||
|
constructor(embark, _options) {
|
||||||
|
this.logger = embark.logger;
|
||||||
|
this.events = embark.events;
|
||||||
|
this.fs = embark.fs;
|
||||||
|
this.communicationConfig = embark.config.communicationConfig;
|
||||||
|
this.embarkConfig = embark.config.embarkConfig;
|
||||||
|
this.web3 = new Web3();
|
||||||
|
this.embark = embark;
|
||||||
|
this.web3Ready = false;
|
||||||
|
this.webSocketsChannels = {};
|
||||||
|
this.modulesPath = dappPath(embark.config.embarkConfig.generationDir, constants.dappArtifacts.symlinkDir);
|
||||||
|
|
||||||
|
this.whisperNodes = {};
|
||||||
|
|
||||||
|
this.events.setCommandHandler("whisper:node:register", (clientName, startCb) => {
|
||||||
|
this.whisperNodes[clientName] = startCb;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.events.request("communication:node:register", "whisper", (readyCb) => {
|
||||||
|
let clientName = this.communicationConfig.client;
|
||||||
|
let registerCb = this.whisperNodes[clientName];
|
||||||
|
registerCb.apply(registerCb, [readyCb]);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.events.request("runcode:whitelist", 'embarkjs', () => { });
|
||||||
|
this.events.request("runcode:whitelist", 'embarkjs-whisper', () => { });
|
||||||
|
|
||||||
|
this.events.on("communication:started", () => {
|
||||||
|
this.setWhisperProvider();
|
||||||
|
this.api = new API(embark, this.web3);
|
||||||
|
this.api.registerAPICalls();
|
||||||
|
this.connectEmbarkJSProvider.bind(this)
|
||||||
|
});
|
||||||
|
|
||||||
|
this.embark.registerActionForEvent("pipeline:generateAll:before", this.addEmbarkJSWhisperArtifact.bind(this));
|
||||||
|
this.registerEmbarkJSCommunication()
|
||||||
|
}
|
||||||
|
|
||||||
|
setWhisperProvider() {
|
||||||
|
let {host, port} = this.communicationConfig.connection;
|
||||||
|
let web3Endpoint = 'ws://' + host + ':' + port;
|
||||||
|
// Note: dont't pass to the provider things like {headers: {Origin: "embark"}}. Origin header is for browser to fill
|
||||||
|
// to protect user, it has no meaning if it is used server-side. See here for more details: https://github.com/ethereum/go-ethereum/issues/16608
|
||||||
|
// Moreover, Parity reject origins that are not urls so if you try to connect with Origin: "embark" it gives the followin error:
|
||||||
|
// << Blocked connection to WebSockets server from untrusted origin: Some("embark") >>
|
||||||
|
// The best choice is to use void origin, BUT Geth rejects void origin, so to keep both clients happy we can use http://embark
|
||||||
|
this.web3.setProvider(new Web3.providers.WebsocketProvider(web3Endpoint, {headers: {Origin: constants.embarkResourceOrigin}}));
|
||||||
|
}
|
||||||
|
|
||||||
|
async addEmbarkJSWhisperArtifact(params, cb) {
|
||||||
|
let connection = this.communicationConfig.connection || {};
|
||||||
|
const config = {
|
||||||
|
server: canonicalHost(connection.host || defaultHost),
|
||||||
|
port: connection.port || '8546',
|
||||||
|
type: connection.type || 'ws'
|
||||||
|
};
|
||||||
|
|
||||||
|
const code = `
|
||||||
|
var EmbarkJS;
|
||||||
|
if (typeof EmbarkJS === 'undefined') {
|
||||||
|
EmbarkJS = require('embarkjs');
|
||||||
|
}
|
||||||
|
const __embarkWhisper = require('embarkjs-whisper');
|
||||||
|
EmbarkJS.Messages.registerProvider('whisper', __embarkWhisper.default || __embarkWhisper);
|
||||||
|
EmbarkJS.Messages.setProvider('whisper', ${JSON.stringify(config)});
|
||||||
|
`;
|
||||||
|
this.events.request("pipeline:register", {
|
||||||
|
path: [this.embarkConfig.generationDir, 'storage'],
|
||||||
|
file: 'init.js',
|
||||||
|
format: 'js',
|
||||||
|
content: code
|
||||||
|
}, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
async registerEmbarkJSCommunication() {
|
||||||
|
let checkEmbarkJS = `
|
||||||
|
return (typeof EmbarkJS === 'undefined');
|
||||||
|
`;
|
||||||
|
let EmbarkJSNotDefined = await this.events.request2('runcode:eval', checkEmbarkJS);
|
||||||
|
|
||||||
|
if (EmbarkJSNotDefined) {
|
||||||
|
await this.events.request2("runcode:register", 'EmbarkJS', require('embarkjs'));
|
||||||
|
}
|
||||||
|
|
||||||
|
const registerProviderCode = `
|
||||||
|
const __embarkWhisper = require('embarkjs-whisper');
|
||||||
|
EmbarkJS.Messages.registerProvider('whisper', __embarkWhisper.default || __embarkWhisper);
|
||||||
|
`;
|
||||||
|
|
||||||
|
await this.events.request2('runcode:eval', registerProviderCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
async connectEmbarkJSProvider() {
|
||||||
|
let connection = this.communicationConfig.connection || {};
|
||||||
|
const config = {
|
||||||
|
server: canonicalHost(connection.host || defaultHost),
|
||||||
|
port: connection.port || '8546',
|
||||||
|
type: connection.type || 'ws'
|
||||||
|
};
|
||||||
|
const code = `
|
||||||
|
EmbarkJS.Messages.setProvider('whisper', ${JSON.stringify(config)});
|
||||||
|
`;
|
||||||
|
|
||||||
|
await this.events.request2('runcode:eval', code);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Whisper;
|
|
@ -161,7 +161,6 @@ simulator(options) {
|
||||||
engine.registerModuleGroup("webserver");
|
engine.registerModuleGroup("webserver");
|
||||||
engine.registerModuleGroup("filewatcher");
|
engine.registerModuleGroup("filewatcher");
|
||||||
engine.registerModuleGroup("storage");
|
engine.registerModuleGroup("storage");
|
||||||
engine.registerModuleGroup("communication");
|
|
||||||
engine.registerModuleGroup("cockpit");
|
engine.registerModuleGroup("cockpit");
|
||||||
engine.registerModulePackage('embark-deploy-tracker', {plugins: engine.plugins});
|
engine.registerModulePackage('embark-deploy-tracker', {plugins: engine.plugins});
|
||||||
|
|
||||||
|
@ -169,10 +168,14 @@ simulator(options) {
|
||||||
plugin.registerActionForEvent("embark:engine:started", async (_params, cb) => {
|
plugin.registerActionForEvent("embark:engine:started", async (_params, cb) => {
|
||||||
try {
|
try {
|
||||||
await engine.events.request2("blockchain:node:start", engine.config.blockchainConfig);
|
await engine.events.request2("blockchain:node:start", engine.config.blockchainConfig);
|
||||||
|
await Promise.all([
|
||||||
|
engine.events.request2("storage:node:start", engine.config.storageConfig),
|
||||||
|
engine.events.request2("communication:node:start", engine.config.communicationConfig),
|
||||||
|
engine.events.request2("namesystem:node:start", engine.config.namesystemConfig)
|
||||||
|
]);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return cb(e);
|
return cb(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
cb();
|
cb();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ const {spawn, exec} = require('child_process');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const constants = require('embark-core/constants');
|
const constants = require('embark-core/constants');
|
||||||
const GethClient = require('./gethClient.js');
|
const GethClient = require('./gethClient.js');
|
||||||
|
const WhisperGethClient = require('./whisperClient.js');
|
||||||
// const ParityClient = require('./parityClient.js');
|
// const ParityClient = require('./parityClient.js');
|
||||||
import { IPC } from 'embark-core';
|
import { IPC } from 'embark-core';
|
||||||
|
|
||||||
|
@ -15,7 +16,7 @@ const Logger = require('embark-logger');
|
||||||
const IPC_CONNECT_INTERVAL = 2000;
|
const IPC_CONNECT_INTERVAL = 2000;
|
||||||
|
|
||||||
/*eslint complexity: ["error", 50]*/
|
/*eslint complexity: ["error", 50]*/
|
||||||
var Blockchain = function(userConfig, clientClass) {
|
var Blockchain = function(userConfig, clientClass, communicationConfig) {
|
||||||
this.userConfig = userConfig;
|
this.userConfig = userConfig;
|
||||||
this.env = userConfig.env || 'development';
|
this.env = userConfig.env || 'development';
|
||||||
this.isDev = userConfig.isDev;
|
this.isDev = userConfig.isDev;
|
||||||
|
@ -203,7 +204,7 @@ Blockchain.prototype.run = function () {
|
||||||
args = compact(args);
|
args = compact(args);
|
||||||
|
|
||||||
let full_cmd = cmd + " " + args.join(' ');
|
let full_cmd = cmd + " " + args.join(' ');
|
||||||
self.logger.info(__("running: %s", full_cmd.underline).green);
|
self.logger.info(__(">>>>>>>>>>>>>>>> running: %s", full_cmd.underline).green);
|
||||||
self.child = spawn(cmd, args, {cwd: process.cwd()});
|
self.child = spawn(cmd, args, {cwd: process.cwd()});
|
||||||
|
|
||||||
self.child.on('error', (err) => {
|
self.child.on('error', (err) => {
|
||||||
|
@ -415,7 +416,7 @@ Blockchain.prototype.initChainAndGetAddress = function (callback) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export function BlockchainClient(userConfig, options) {
|
export function BlockchainClient(userConfig, options, communicationConfig) {
|
||||||
if ((userConfig === {} || JSON.stringify(userConfig) === '{"enabled":true}') && options.env !== 'development') {
|
if ((userConfig === {} || JSON.stringify(userConfig) === '{"enabled":true}') && options.env !== 'development') {
|
||||||
options.logger.info("===> " + __("warning: running default config on a non-development environment"));
|
options.logger.info("===> " + __("warning: running default config on a non-development environment"));
|
||||||
}
|
}
|
||||||
|
@ -425,18 +426,13 @@ export function BlockchainClient(userConfig, options) {
|
||||||
if (options.clientName) userConfig.client = options.clientName;
|
if (options.clientName) userConfig.client = options.clientName;
|
||||||
// Choose correct client instance based on clientName
|
// Choose correct client instance based on clientName
|
||||||
let clientClass;
|
let clientClass;
|
||||||
switch (userConfig.client) {
|
|
||||||
case constants.blockchain.clients.geth:
|
|
||||||
clientClass = GethClient;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// case constants.blockchain.clients.parity:
|
if (communicationConfig) {
|
||||||
// clientClass = ParityClient;
|
clientClass = WhisperGethClient
|
||||||
// break;
|
} else {
|
||||||
default:
|
clientClass = GethClient;
|
||||||
console.error(__('Unknown client "%s". Please use one of the following: %s', userConfig.client, Object.keys(constants.blockchain.clients).join(', ')));
|
|
||||||
process.exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
userConfig.isDev = (userConfig.isDev || userConfig.default);
|
userConfig.isDev = (userConfig.isDev || userConfig.default);
|
||||||
userConfig.env = options.env;
|
userConfig.env = options.env;
|
||||||
userConfig.onReadyCallback = options.onReadyCallback;
|
userConfig.onReadyCallback = options.onReadyCallback;
|
||||||
|
@ -444,5 +440,5 @@ export function BlockchainClient(userConfig, options) {
|
||||||
userConfig.logger = options.logger;
|
userConfig.logger = options.logger;
|
||||||
userConfig.certOptions = options.certOptions;
|
userConfig.certOptions = options.certOptions;
|
||||||
userConfig.isStandalone = options.isStandalone;
|
userConfig.isStandalone = options.isStandalone;
|
||||||
return new Blockchain(userConfig, clientClass);
|
return new Blockchain(userConfig, clientClass, communicationConfig);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ class BlockchainProcess extends ProcessWrapper {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
super();
|
super();
|
||||||
this.blockchainConfig = options.blockchainConfig;
|
this.blockchainConfig = options.blockchainConfig;
|
||||||
|
this.communicationConfig = options.communicationConfig;
|
||||||
this.client = options.client;
|
this.client = options.client;
|
||||||
this.env = options.env;
|
this.env = options.env;
|
||||||
this.isDev = options.isDev;
|
this.isDev = options.isDev;
|
||||||
|
@ -26,7 +27,8 @@ class BlockchainProcess extends ProcessWrapper {
|
||||||
onReadyCallback: this.blockchainReady.bind(this),
|
onReadyCallback: this.blockchainReady.bind(this),
|
||||||
onExitCallback: this.blockchainExit.bind(this),
|
onExitCallback: this.blockchainExit.bind(this),
|
||||||
logger: console
|
logger: console
|
||||||
}
|
},
|
||||||
|
this.communicationConfig
|
||||||
);
|
);
|
||||||
|
|
||||||
this.blockchain.run();
|
this.blockchain.run();
|
||||||
|
|
|
@ -10,6 +10,7 @@ export class BlockchainProcessLauncher {
|
||||||
this.logger = options.logger;
|
this.logger = options.logger;
|
||||||
this.normalizeInput = options.normalizeInput;
|
this.normalizeInput = options.normalizeInput;
|
||||||
this.blockchainConfig = options.blockchainConfig;
|
this.blockchainConfig = options.blockchainConfig;
|
||||||
|
this.communicationConfig = options.communicationConfig;
|
||||||
this.locale = options.locale;
|
this.locale = options.locale;
|
||||||
this.isDev = options.isDev;
|
this.isDev = options.isDev;
|
||||||
this.client = options.client;
|
this.client = options.client;
|
||||||
|
@ -35,6 +36,7 @@ export class BlockchainProcessLauncher {
|
||||||
this.blockchainProcess.send({
|
this.blockchainProcess.send({
|
||||||
action: constants.blockchain.init, options: {
|
action: constants.blockchain.init, options: {
|
||||||
blockchainConfig: this.blockchainConfig,
|
blockchainConfig: this.blockchainConfig,
|
||||||
|
communicationConfig: this.communicationConfig,
|
||||||
client: this.client,
|
client: this.client,
|
||||||
env: this.env,
|
env: this.env,
|
||||||
isDev: this.isDev,
|
isDev: this.isDev,
|
||||||
|
|
|
@ -11,6 +11,7 @@ class Geth {
|
||||||
this.embark = embark;
|
this.embark = embark;
|
||||||
this.embarkConfig = embark.config.embarkConfig;
|
this.embarkConfig = embark.config.embarkConfig;
|
||||||
this.blockchainConfig = embark.config.blockchainConfig;
|
this.blockchainConfig = embark.config.blockchainConfig;
|
||||||
|
this.communicationConfig = embark.config.communicationConfig;
|
||||||
this.locale = options.locale;
|
this.locale = options.locale;
|
||||||
this.logger = embark.logger;
|
this.logger = embark.logger;
|
||||||
this.client = options.client;
|
this.client = options.client;
|
||||||
|
@ -25,7 +26,6 @@ class Geth {
|
||||||
this.events.request("blockchain:node:register", constants.blockchain.clients.geth, (readyCb) => {
|
this.events.request("blockchain:node:register", constants.blockchain.clients.geth, (readyCb) => {
|
||||||
this.events.request('processes:register', 'blockchain', {
|
this.events.request('processes:register', 'blockchain', {
|
||||||
launchFn: (cb) => {
|
launchFn: (cb) => {
|
||||||
// this.startBlockchainNode(readyCb);
|
|
||||||
this.startBlockchainNode(cb);
|
this.startBlockchainNode(cb);
|
||||||
},
|
},
|
||||||
stopFn: (cb) => {
|
stopFn: (cb) => {
|
||||||
|
@ -40,6 +40,24 @@ class Geth {
|
||||||
});
|
});
|
||||||
this.registerServiceCheck();
|
this.registerServiceCheck();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.events.request("whisper:node:register", constants.blockchain.clients.geth, readyCb => {
|
||||||
|
this.events.request('processes:register', 'communication', {
|
||||||
|
launchFn: cb => {
|
||||||
|
this.startWhisperNode(cb);
|
||||||
|
},
|
||||||
|
stopFn: cb => {
|
||||||
|
this.stopWhisperNode(cb);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.events.request("processes:launch", "communication", (err) => {
|
||||||
|
if (err) {
|
||||||
|
this.logger.error(`Error launching whisper process: ${err.message || err}`);
|
||||||
|
}
|
||||||
|
readyCb();
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldInit() {
|
shouldInit() {
|
||||||
|
@ -96,6 +114,31 @@ class Geth {
|
||||||
this.blockchainProcess.startBlockchainNode(callback);
|
this.blockchainProcess.startBlockchainNode(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
startWhisperNode(callback) {
|
||||||
|
this.whisperProcess = new BlockchainProcessLauncher({
|
||||||
|
events: this.events,
|
||||||
|
logger: this.logger,
|
||||||
|
normalizeInput,
|
||||||
|
blockchainConfig: this.blockchainConfig,
|
||||||
|
communicationConfig: this.communicationConfig,
|
||||||
|
locale: this.locale,
|
||||||
|
client: this.client,
|
||||||
|
isDev: this.isDev,
|
||||||
|
embark: this.embark
|
||||||
|
});
|
||||||
|
this.whisperProcess.startBlockchainNode(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
stopWhisperNode(cb) {
|
||||||
|
if (!this.whisperProcess) {
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
this.whisperProcess.stopBlockchainNode(() => {
|
||||||
|
this.logger.info(`The whisper process has been stopped.`);
|
||||||
|
cb();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
stopBlockchainNode(cb) {
|
stopBlockchainNode(cb) {
|
||||||
const message = __(`The blockchain process has been stopped. It can be restarted by running ${"service blockchain on".bold} in the Embark console.`);
|
const message = __(`The blockchain process has been stopped. It can be restarted by running ${"service blockchain on".bold} in the Embark console.`);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,261 @@
|
||||||
|
import { __ } from 'embark-i18n';
|
||||||
|
import { dappPath, ipcPath } from 'embark-utils';
|
||||||
|
const async = require('async');
|
||||||
|
const {exec, spawn} = require('child_process');
|
||||||
|
const path = require('path');
|
||||||
|
const GethMiner = require('./miner');
|
||||||
|
const semver = require('semver');
|
||||||
|
const constants = require('embark-core/constants');
|
||||||
|
|
||||||
|
const DEFAULTS = {
|
||||||
|
"BIN": "geth",
|
||||||
|
"VERSIONS_SUPPORTED": ">=1.8.14",
|
||||||
|
"NETWORK_TYPE": "custom",
|
||||||
|
"NETWORK_ID": 1337,
|
||||||
|
"RPC_API": ['eth', 'web3', 'net', 'debug', 'personal'],
|
||||||
|
"WS_API": ['eth', 'web3', 'net', 'shh', 'debug', 'pubsub', 'personal'],
|
||||||
|
"DEV_WS_API": ['eth', 'web3', 'net', 'shh', 'debug', 'pubsub', 'personal'],
|
||||||
|
"TARGET_GAS_LIMIT": 8000000
|
||||||
|
};
|
||||||
|
|
||||||
|
class WhisperGethClient {
|
||||||
|
|
||||||
|
static get DEFAULTS() {
|
||||||
|
return DEFAULTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(options) {
|
||||||
|
this.config = options && options.hasOwnProperty('config') ? options.config : {};
|
||||||
|
this.communicationConfig = options.communicationConfig;
|
||||||
|
this.env = options && options.hasOwnProperty('env') ? options.env : 'development';
|
||||||
|
this.isDev = options && options.hasOwnProperty('isDev') ? options.isDev : (this.env === 'development');
|
||||||
|
this.name = constants.blockchain.clients.geth;
|
||||||
|
this.prettyName = "Go-Ethereum (https://github.com/ethereum/go-ethereum)";
|
||||||
|
this.bin = this.config.ethereumClientBin || DEFAULTS.BIN;
|
||||||
|
this.versSupported = DEFAULTS.VERSIONS_SUPPORTED;
|
||||||
|
this.httpReady = false;
|
||||||
|
this.wsReady = !this.config.wsRPC;
|
||||||
|
}
|
||||||
|
|
||||||
|
isReady(data) {
|
||||||
|
if (data.indexOf('WebSocket endpoint opened') > -1) {
|
||||||
|
this.wsReady = true;
|
||||||
|
}
|
||||||
|
return this.wsReady;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the client needs some sort of 'keep alive' transactions to avoid freezing by inactivity
|
||||||
|
* @returns {boolean} if keep alive is needed
|
||||||
|
*/
|
||||||
|
needKeepAlive() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
commonOptions() {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
getMiner() {
|
||||||
|
return new GethMiner({datadir: this.config.datadir});
|
||||||
|
}
|
||||||
|
|
||||||
|
getBinaryPath() {
|
||||||
|
return this.bin;
|
||||||
|
}
|
||||||
|
|
||||||
|
determineVersionCommand() {
|
||||||
|
return this.bin + " version";
|
||||||
|
}
|
||||||
|
|
||||||
|
parseVersion(rawVersionOutput) {
|
||||||
|
let parsed;
|
||||||
|
const match = rawVersionOutput.match(/Version: (.*)/);
|
||||||
|
if (match) {
|
||||||
|
parsed = match[1].trim();
|
||||||
|
}
|
||||||
|
return parsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
isSupportedVersion(parsedVersion) {
|
||||||
|
let test;
|
||||||
|
try {
|
||||||
|
let v = semver(parsedVersion);
|
||||||
|
v = `${v.major}.${v.minor}.${v.patch}`;
|
||||||
|
test = semver.Range(this.versSupported).test(semver(v));
|
||||||
|
if (typeof test !== 'boolean') {
|
||||||
|
test = undefined;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
// eslint-disable-next-line no-unsafe-finally
|
||||||
|
return test;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
determineNetworkType(config) {
|
||||||
|
let cmd;
|
||||||
|
if (config.networkType === 'testnet') {
|
||||||
|
cmd = "--testnet";
|
||||||
|
} else if (config.networkType === 'rinkeby') {
|
||||||
|
cmd = "--rinkeby";
|
||||||
|
} else if (config.networkType === 'custom') {
|
||||||
|
cmd = "--networkid=" + config.networkId;
|
||||||
|
}
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
runAsArchival(config) {
|
||||||
|
return config.networkId === 1337 || config.archivalMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
initGenesisCommmand() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
newAccountCommand() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
parseNewAccountCommandResultToAddress(data = "") {
|
||||||
|
if (data.match(/{(\w+)}/)) return "0x" + data.match(/{(\w+)}/)[1];
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
listAccountsCommand() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
parseListAccountsCommandResultToAddress(data = "") {
|
||||||
|
if (data.match(/{(\w+)}/)) return "0x" + data.match(/{(\w+)}/)[1];
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
parseListAccountsCommandResultToAddressList(data = "") {
|
||||||
|
const regex = RegExp(/{(\w+)}/g);
|
||||||
|
let match;
|
||||||
|
const accounts = [];
|
||||||
|
while ((match = regex.exec(data)) !== null) {
|
||||||
|
accounts.push('0x' + match[1]);
|
||||||
|
}
|
||||||
|
return accounts;
|
||||||
|
}
|
||||||
|
|
||||||
|
parseListAccountsCommandResultToAddressCount(data = "") {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
determineRpcOptions(config) {
|
||||||
|
let cmd = [];
|
||||||
|
cmd.push("--port=30304");
|
||||||
|
cmd.push("--rpc");
|
||||||
|
cmd.push("--rpcport=9998");
|
||||||
|
cmd.push("--rpcaddr=" + config.rpcHost);
|
||||||
|
|
||||||
|
if (config.rpcCorsDomain) {
|
||||||
|
if (config.rpcCorsDomain === '*') {
|
||||||
|
console.warn('==================================');
|
||||||
|
console.warn(__('rpcCorsDomain set to *'));
|
||||||
|
console.warn(__('make sure you know what you are doing'));
|
||||||
|
console.warn('==================================');
|
||||||
|
}
|
||||||
|
cmd.push("--rpccorsdomain=" + config.rpcCorsDomain);
|
||||||
|
} else {
|
||||||
|
console.warn('==================================');
|
||||||
|
console.warn(__('warning: cors is not set'));
|
||||||
|
console.warn('==================================');
|
||||||
|
}
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
determineWsOptions(config, communicationConfig) {
|
||||||
|
let cmd = [];
|
||||||
|
if (config.wsRPC) {
|
||||||
|
cmd.push("--ws");
|
||||||
|
|
||||||
|
cmd.push(`--wsport=${communicationConfig.connection.port || config.wsPost++}`);
|
||||||
|
cmd.push(`--wsaddr=${communicationConfig.connection.host || config.wsHost++}`);
|
||||||
|
|
||||||
|
if (config.wsOrigins) {
|
||||||
|
if (config.wsOrigins === '*') {
|
||||||
|
console.warn('==================================');
|
||||||
|
console.warn(__('wsOrigins set to *'));
|
||||||
|
console.warn(__('make sure you know what you are doing'));
|
||||||
|
console.warn('==================================');
|
||||||
|
}
|
||||||
|
cmd.push("--wsorigins=" + config.wsOrigins);
|
||||||
|
} else {
|
||||||
|
console.warn('==================================');
|
||||||
|
console.warn(__('warning: wsOrigins is not set'));
|
||||||
|
console.warn('==================================');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
initDevChain(datadir, callback) {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
mainCommand(address, done) {
|
||||||
|
let self = this;
|
||||||
|
let config = this.config;
|
||||||
|
let rpc_api = this.config.rpcApi;
|
||||||
|
let ws_api = this.config.wsApi;
|
||||||
|
let args = [];
|
||||||
|
async.series([
|
||||||
|
function commonOptions(callback) {
|
||||||
|
let cmd = self.commonOptions();
|
||||||
|
args = args.concat(cmd);
|
||||||
|
callback(null, cmd);
|
||||||
|
},
|
||||||
|
function wsOptions(callback) {
|
||||||
|
let cmd = self.determineWsOptions(self.config, self.communicationConfig);
|
||||||
|
args = args.concat(cmd);
|
||||||
|
callback(null, cmd);
|
||||||
|
},
|
||||||
|
function dontGetPeers(callback) {
|
||||||
|
if (config.nodiscover) {
|
||||||
|
args.push("--nodiscover");
|
||||||
|
return callback(null, "--nodiscover");
|
||||||
|
}
|
||||||
|
callback(null, "");
|
||||||
|
},
|
||||||
|
function maxPeers(callback) {
|
||||||
|
let cmd = "--maxpeers=" + config.maxpeers;
|
||||||
|
args.push(cmd);
|
||||||
|
callback(null, cmd);
|
||||||
|
},
|
||||||
|
function bootnodes(callback) {
|
||||||
|
if (config.bootnodes && config.bootnodes !== "" && config.bootnodes !== []) {
|
||||||
|
args.push("--bootnodes=" + config.bootnodes);
|
||||||
|
return callback(null, "--bootnodes=" + config.bootnodes);
|
||||||
|
}
|
||||||
|
callback("");
|
||||||
|
},
|
||||||
|
function whisper(callback) {
|
||||||
|
rpc_api.push('shh');
|
||||||
|
if (ws_api.indexOf('shh') === -1) {
|
||||||
|
ws_api.push('shh');
|
||||||
|
}
|
||||||
|
args.push("--shh");
|
||||||
|
return callback(null, "--shh ");
|
||||||
|
},
|
||||||
|
function rpcApi(callback) {
|
||||||
|
args.push('--rpcapi=' + rpc_api.join(','));
|
||||||
|
callback(null, '--rpcapi=' + rpc_api.join(','));
|
||||||
|
},
|
||||||
|
function wsApi(callback) {
|
||||||
|
args.push('--wsapi=' + ws_api.join(','));
|
||||||
|
callback(null, '--wsapi=' + ws_api.join(','));
|
||||||
|
}
|
||||||
|
], function(err) {
|
||||||
|
if (err) {
|
||||||
|
throw new Error(err.message);
|
||||||
|
}
|
||||||
|
return done(self.bin, args);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = WhisperGethClient;
|
||||||
|
|
|
@ -118,6 +118,7 @@ class ENS {
|
||||||
this.enabled = true;
|
this.enabled = true;
|
||||||
this.doSetENSProvider = this.config.namesystemConfig.provider === 'ens';
|
this.doSetENSProvider = this.config.namesystemConfig.provider === 'ens';
|
||||||
|
|
||||||
|
this.registerEmbarkJSNaming();
|
||||||
this.registerEvents();
|
this.registerEvents();
|
||||||
this.registerConsoleCommands();
|
this.registerConsoleCommands();
|
||||||
this.events.request2("runcode:whitelist", 'eth-ens-namehash');
|
this.events.request2("runcode:whitelist", 'eth-ens-namehash');
|
||||||
|
|
Loading…
Reference in New Issue