From c8c0a5c42f24a024b2f9b22e236db91ef47ef94d Mon Sep 17 00:00:00 2001 From: Jonathan Rainville Date: Fri, 15 Jun 2018 14:35:50 -0400 Subject: [PATCH] enable websocket provider --- lib/contracts/blockchain.js | 135 ++++++++++++++++++++---------------- lib/contracts/provider.js | 22 ++++-- package-lock.json | 42 ++++------- package.json | 4 +- 4 files changed, 109 insertions(+), 94 deletions(-) diff --git a/lib/contracts/blockchain.js b/lib/contracts/blockchain.js index 9f19b9e1b..3b647b327 100644 --- a/lib/contracts/blockchain.js +++ b/lib/contracts/blockchain.js @@ -1,7 +1,7 @@ const Web3 = require('web3'); const async = require('async'); const Provider = require('./provider.js'); -const request = require('request'); +const http = require('http'); const BlockchainProcessLauncher = require('../processes/blockchainProcessLauncher'); const utils = require('../utils/utils'); const constants = require('../constants'); @@ -41,50 +41,56 @@ class Blockchain { } const self = this; this.web3 = new Web3(); - if (this.contractsConfig.deployment.type === "rpc") { - let provider; - this.web3Endpoint = 'http://' + this.contractsConfig.deployment.host + ':' + this.contractsConfig.deployment.port; - const providerOptions = { - web3: this.web3, - accountsConfig: this.contractsConfig.deployment.accounts, - logger: this.logger, - isDev: this.isDev, - web3Endpoint: self.web3Endpoint - }; - provider = new Provider(providerOptions); - - async.waterfall([ - function startProvider(next) { - provider.startWeb3Provider(next); - }, - function checkNode(next) { - self.assertNodeConnection(true, (err) => { - if (err && self.web3StartedInProcess) { - // Already started blockchain in another node, we really have a node problem - self.logger.error(__('Unable to start the blockchain process. Is Geth installed?').red); - return next(err); - } - if (!err) { - self.isWeb3Ready = true; - self.events.emit(WEB3_READY); - return next(); - } - self.web3StartedInProcess = true; - self.startBlockchainNode(() => { - // Need to re-initialize web3 to connect to the new blockchain node - provider.stop(); - self.initWeb3(cb); - }); - }); - }, - function fundAccountsIfNeeded(next) { - provider.fundAccounts(next); - } - ], cb); - } else { - throw new Error(__("contracts config error: unknown deployment type %s", this.contractsConfig.deployment.type)); + if (this.contractsConfig.deployment.type !== "rpc" && this.contractsConfig.deployment.type !== "ws") { + const message = __("contracts config error: unknown deployment type %s", this.contractsConfig.deployment.type); + this.logger.error(message); + return cb(message); } + + const protocol = (this.contractsConfig.deployment.type === "rpc") ? 'http' : 'ws'; + let provider; + this.web3Endpoint = `${protocol}://${this.contractsConfig.deployment.host}:${this.contractsConfig.deployment.port}`; + + const providerOptions = { + web3: this.web3, + accountsConfig: this.contractsConfig.deployment.accounts, + blockchainConfig: this.blockchainConfig, + logger: this.logger, + isDev: this.isDev, + type: this.contractsConfig.deployment.type, + web3Endpoint: self.web3Endpoint + }; + provider = new Provider(providerOptions); + + async.waterfall([ + function checkNode(next) { + self.assertNodeConnection(true, (err) => { + if (err && self.web3StartedInProcess) { + // Already started blockchain in another node, we really have a node problem + self.logger.error(__('Unable to start the blockchain process. Is Geth installed?').red); + return next(err); + } + if (!err) { + self.isWeb3Ready = true; + self.events.emit(WEB3_READY); + return next(); + } + self.web3StartedInProcess = true; + self.startBlockchainNode(() => { + // Need to re-initialize web3 to connect to the new blockchain node + provider.stop(); + self.initWeb3(cb); + }); + }); + }, + function startProvider(next) { + provider.startWeb3Provider(next); + }, + function fundAccountsIfNeeded(next) { + provider.fundAccounts(next); + } + ], cb); } onReady(callback) { @@ -245,24 +251,37 @@ class Blockchain { next(); }, function pingEndpoint(next) { - if (!self.web3Endpoint) { - return next(); + const origin = self.blockchainConfig.wsOrigins.split(',')[0]; + const options = { + protocolVersion: 13, + perMessageDeflate: true, + origin: origin, + host: self.contractsConfig.deployment.host, + port: self.contractsConfig.deployment.port + }; + if (self.contractsConfig.deployment.type === 'ws') { + options.headers = { + 'Sec-WebSocket-Version': 13, + 'Sec-WebSocket-Key': 'h1wEoI9sbNmg4FR0OWRpKw==', + Connection: 'Upgrade', + Upgrade: 'websocket', + 'Sec-WebSocket-Extensions': 'permessage-deflate; client_max_window_bits', + Origin: origin + }; } - request.get(self.web3Endpoint, function (err, _response, _body) { - if (err) { - return next(NO_NODE_ERROR); - } + + const req = http.get(options); + + req.on('error', (err) => { + next(err); + }); + + req.on('response', (_response) => { next(); }); - }, - function checkAccounts(next) { - self.getAccounts(function(err, accounts) { - if (err) { - return next(NO_NODE_ERROR); - } - self.web3.defaultAccount = accounts[0]; - self.registerWeb3Object(); - return next(); + + req.on('upgrade', (_res, _socket, _head) => { + next(); }); } ], function (err) { diff --git a/lib/contracts/provider.js b/lib/contracts/provider.js index 0e60ee86a..80de9088b 100644 --- a/lib/contracts/provider.js +++ b/lib/contracts/provider.js @@ -1,5 +1,6 @@ const ProviderEngine = require('web3-provider-engine'); -const RpcSubprovider = require('web3-provider-engine/subproviders/rpc.js'); +const RpcSubprovider = require('web3-provider-engine/subproviders/rpc'); +const WsSubprovider = require('web3-provider-engine/subproviders/websocket'); const async = require('async'); const AccountParser = require('./accountParser'); const fundAccount = require('./fundAccount'); @@ -10,6 +11,8 @@ class Provider { constructor(options) { this.web3 = options.web3; this.accountsConfig = options.accountsConfig; + this.blockchainConfig = options.blockchainConfig; + this.type = options.type; this.web3Endpoint = options.web3Endpoint; this.logger = options.logger; this.isDev = options.isDev; @@ -19,9 +22,20 @@ class Provider { startWeb3Provider(callback) { const self = this; - self.engine.addProvider(new RpcSubprovider({ - rpcUrl: self.web3Endpoint - })); + + if (this.type === 'rpc') { + self.engine.addProvider(new RpcSubprovider({ + rpcUrl: self.web3Endpoint + })); + } else if (this.type === 'ws') { + self.engine.addProvider(new WsSubprovider({ + rpcUrl: self.web3Endpoint, + origin: this.blockchainConfig.wsOrigins.split(',')[0] + })); + } else { + return callback(__("contracts config error: unknown deployment type %s", this.type)); + } + // network connectivity error self.engine.on('error', (err) => { diff --git a/package-lock.json b/package-lock.json index bfe121dd8..61dff80af 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1164,7 +1164,7 @@ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", "requires": { - "caniuse-lite": "1.0.30000853", + "caniuse-lite": "1.0.30000856", "electron-to-chromium": "1.3.48" } } @@ -1890,9 +1890,9 @@ "integrity": "sha1-MpAafWuTqH1Z8Iqu5H6o/27JD98=" }, "caniuse-lite": { - "version": "1.0.30000853", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000853.tgz", - "integrity": "sha512-vMrE8BED4MJC9IhDJKP8ok6bJUfn5+YHvxwXMYfiPqQOJ3r2B9ihcArlUnXu6yPWf7b3jHqiEBwXZEbrbiFUqg==" + "version": "1.0.30000856", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000856.tgz", + "integrity": "sha512-x3mYcApHMQemyaHuH/RyqtKCGIYTgEA63fdi+VBvDz8xUSmRiVWTLeyKcoGQCGG6UPR9/+4qG4OKrTa6aSQRKg==" }, "caseless": { "version": "0.8.0", @@ -3508,6 +3508,13 @@ "ethereumjs-util": "5.2.0" }, "dependencies": { + "ethereumjs-abi": { + "version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#4ea2fdfed09e8f99117d9362d17c6b01b64a2bcf", + "requires": { + "bn.js": "4.11.8", + "ethereumjs-util": "5.2.0" + } + }, "ethereumjs-util": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", @@ -3647,29 +3654,6 @@ "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.0.18.tgz", "integrity": "sha1-L9w1dvIykDNYl26znaeDIT/5Uj8=" }, - "ethereumjs-abi": { - "version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#4ea2fdfed09e8f99117d9362d17c6b01b64a2bcf", - "requires": { - "bn.js": "4.11.8", - "ethereumjs-util": "5.2.0" - }, - "dependencies": { - "ethereumjs-util": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", - "integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==", - "requires": { - "bn.js": "4.11.8", - "create-hash": "1.2.0", - "ethjs-util": "0.1.6", - "keccak": "1.4.0", - "rlp": "2.0.0", - "safe-buffer": "5.1.2", - "secp256k1": "3.5.0" - } - } - } - }, "ethereumjs-account": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz", @@ -13183,9 +13167,7 @@ } }, "web3-provider-engine": { - "version": "14.0.6", - "resolved": "https://registry.npmjs.org/web3-provider-engine/-/web3-provider-engine-14.0.6.tgz", - "integrity": "sha512-tr5cGSyxfSC/JqiUpBlJtfZpwQf1yAA8L/zy1C6fDFm0ntR974pobJ4v4676atpZne4Ze5VFy3kPPahHe9gQiQ==", + "version": "git://github.com/jrainville/provider-engine.git#902a0dd6fad946e571024810e0f15df0d3ff7236", "requires": { "async": "2.6.1", "backoff": "2.5.0", diff --git a/package.json b/package.json index ee2705586..3e703df3e 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,6 @@ "babel-preset-es2017": "6.24.1", "babel-preset-react": "^6.24.1", "bip39": "^2.5.0", - "neo-blessed": "^0.2.0", "chokidar": "^2.0.3", "clone-deep": "^4.0.0", "colors": "^1.1.2", @@ -55,6 +54,7 @@ "ipfs-api": "17.2.4", "live-plugin-manager-git-fix": "^0.12.1", "merge": "^1.2.0", + "neo-blessed": "^0.2.0", "node-http-proxy": "^0.2.3", "node-ipc": "^9.1.1", "os-locale": "^2.1.0", @@ -77,7 +77,7 @@ "uuid": "^3.2.1", "viz.js": "^1.8.1", "web3": "1.0.0-beta.34", - "web3-provider-engine": "^14.0.5", + "web3-provider-engine": "git://github.com/jrainville/provider-engine.git#origin-fix", "webpack": "^3.10.0", "window-size": "^1.1.0" },