Commit 88e0ec4e authored by Pavel Ševčík's avatar Pavel Ševčík
Browse files

Merge branch 'feat_dojo_rpc_client' into 'develop'

Transition from bitcoind-rpc-client to rpc-bitcoin

See merge request !231
parents d5dcafd5 f90301f8
......@@ -7,7 +7,7 @@
'use strict'
const Logger = require('../lib/logger')
const RpcClient = require('../lib/bitcoind-rpc/rpc-client')
const { waitForBitcoindRpcApi } = require('../lib/bitcoind-rpc/rpc-client')
const network = require('../lib/bitcoin/network')
const keys = require('../keys')[network.key]
const db = require('../lib/db/mysql-db-wrapper')
......@@ -31,10 +31,10 @@
*/
Logger.info('API : Process ID: ' + process.pid)
Logger.info('API : Preparing the REST API')
// Wait for Bitcoind RPC API
// being ready to process requests
await RpcClient.waitForBitcoindRpcApi()
await waitForBitcoindRpcApi()
// Initialize the db wrapper
const dbConfig = {
......
......@@ -9,16 +9,14 @@ const bodyParser = require('body-parser')
const errors = require('../lib/errors')
const network = require('../lib/bitcoin/network')
const Logger = require('../lib/logger')
const db = require('../lib/db/mysql-db-wrapper')
const hdaHelper = require('../lib/bitcoin/hd-accounts-helper')
const hdaService = require('../lib/bitcoin/hd-accounts-service')
const RpcClient = require('../lib/bitcoind-rpc/rpc-client')
const HdAccountInfo = require('../lib/wallet/hd-account-info')
const authMgr = require('../lib/auth/authorizations-manager')
const HttpServer = require('../lib/http-server/http-server')
const remoteImporter = require('../lib/remote-importer/remote-importer')
const debugApi = !!(process.argv.indexOf('api-debug') > -1)
const debugApi = process.argv.indexOf('api-debug') > -1
const gap = require('../keys/')[network.key].gap
......@@ -34,9 +32,6 @@ class XPubRestApi {
constructor(httpServer) {
this.httpServer = httpServer
// Initialize the rpc client
this.rpcClient = new RpcClient()
// Establish routes
const urlencodedParser = bodyParser.urlencoded({ extended: true })
......
......@@ -9,7 +9,7 @@ const errors = require('../errors')
const Logger = require('../logger')
const network = require('../bitcoin/network')
const keys = require('../../keys')[network.key]
const RpcClient = require('./rpc-client')
const { createRpcClient } = require('./rpc-client')
const latestBlock = require('./latest-block')
......@@ -27,7 +27,7 @@ class Fees {
this.fees = {}
this.feeType = keys.bitcoind.feeType
this.rpcClient = new RpcClient()
this.rpcClient = createRpcClient()
this.refresh()
}
......@@ -55,7 +55,7 @@ class Fees {
async refresh() {
await util.parallelCall(this.targets, async tgt => {
try {
const level = await this.rpcClient.cmd('estimatesmartfee', tgt, this.feeType)
const level = await this.rpcClient.estimatesmartfee({ conf_target: tgt, estimate_mode: this.feeType })
this.fees[tgt] = (level.errors && level.errors.length > 0) ? 0 : Math.round(level.feerate * 1e5)
} catch(e) {
Logger.error(e, 'Bitcoind RPC : Fees.refresh()')
......
......@@ -6,11 +6,11 @@
const LRU = require('lru-cache')
const errors = require('../errors')
const RpcClient = require('./rpc-client')
const { createRpcClient } = require('./rpc-client')
/**
* A singleton providing information about block headers
* A singleton providing information about block headers
*/
class Headers {
......@@ -29,7 +29,7 @@ class Headers {
})
// Initialize the rpc client
this.rpcClient = new RpcClient()
this.rpcClient = createRpcClient()
}
/**
......@@ -40,9 +40,9 @@ class Headers {
async getHeader(hash) {
if (this.headers.has(hash))
return this.headers.get(hash)
try {
const header = await this.rpcClient.getblockheader(hash, true)
const header = await this.rpcClient.getblockheader({ blockhash: hash, verbose: true })
const fmtHeader = JSON.stringify(header, null, 2)
this.headers.set(hash, fmtHeader)
return fmtHeader
......@@ -50,7 +50,7 @@ class Headers {
return Promise.reject(errors.generic.GEN)
}
}
}
module.exports = new Headers()
......@@ -9,7 +9,7 @@ const Logger = require('../logger')
const util = require('../util')
const network = require('../bitcoin/network')
const keys = require('../../keys')[network.key]
const RpcClient = require('./rpc-client')
const { createRpcClient } = require('./rpc-client')
/**
......@@ -27,8 +27,8 @@ class LatestBlock {
this.diff = null
// Initialize the rpc client
this.rpcClient = new RpcClient()
this.rpcClient = createRpcClient()
// Gets the latest block from bitcoind
this.rpcClient.getbestblockhash().then(hash => this.onBlockHash(hash))
......@@ -54,7 +54,7 @@ class LatestBlock {
* @returns {Promise}
*/
async onBlockHash(hash) {
const header = await this.rpcClient.getblockheader(hash)
const header = await this.rpcClient.getblockheader({ blockhash: hash })
this.height = header.height
this.hash = hash
......
......@@ -4,7 +4,7 @@
*/
'use strict'
const rpc = require('bitcoind-rpc-client')
const {RPCClient} = require('rpc-bitcoin');
const network = require('../bitcoin/network')
const keys = require('../../keys')[network.key]
const util = require('../util')
......@@ -14,77 +14,51 @@ const Logger = require('../logger')
/**
* Wrapper for bitcoind rpc client
*/
class RpcClient {
/**
* Constructor
*/
constructor() {
// Initiliaze the rpc client
this.client = new rpc({
host: keys.bitcoind.rpc.host,
port: keys.bitcoind.rpc.port
})
this.client.set('user', keys.bitcoind.rpc.user)
this.client.set('pass', keys.bitcoind.rpc.pass)
// Initialize a proxy postprocessing api calls
return new Proxy(this, {
get: function(target, name, receiver) {
const origMethod = target.client[name]
return async function(...args) {
const result = await origMethod.apply(target.client, args)
if (Array.isArray(result)) {
return result
} else if (result.result) {
return result.result
} else if (result.error) {
throw result.error
} else {
throw 'A problem was met with a request sent to bitcoind RPC API'
}
}
}
const createRpcClient = () => {
return new RPCClient({
url: `http://${keys.bitcoind.rpc.host}`,
port: keys.bitcoind.rpc.port,
user: keys.bitcoind.rpc.user,
pass: keys.bitcoind.rpc.pass
})
}
}
/**
* Check if an error returned by bitcoin-rpc-client
* is a connection error.
* @param {string} err - error message
* @returns {boolean} returns true if message related to a connection error
*/
static isConnectionError(err) {
/**
* Check if an error returned by bitcoin-rpc-client
* is a connection error.
* @param {string} err - error message
* @returns {boolean} returns true if message related to a connection error
*/
const isConnectionError = (err) => {
if (typeof err != 'string')
return false
return false
const isTimeoutError = (err.indexOf('connect ETIMEDOUT') != -1)
const isConnRejected = (err.indexOf('Connection Rejected') != -1)
const isTimeoutError = (err.indexOf('connect ETIMEDOUT') !== -1)
const isConnRejected = (err.indexOf('Connection Rejected') !== -1)
return (isTimeoutError || isConnRejected)
}
}
/**
* Check if the rpc api is ready to process requests
* @returns {Promise}
*/
static async waitForBitcoindRpcApi() {
let client = new RpcClient()
/**
* Check if the rpc api is ready to process requests
* @returns {Promise}
*/
const waitForBitcoindRpcApi = async () => {
let client = createRpcClient()
try {
await client.getblockchaininfo()
} catch(e) {
client = null
Logger.info('Bitcoind RPC : API is still unreachable. New attempt in 20s.')
return util.delay(20000).then(() => {
return RpcClient.waitForBitcoindRpcApi()
})
await client.getblockchaininfo()
} catch (e) {
client = null
Logger.info('Bitcoind RPC : API is still unreachable. New attempt in 20s.')
return util.delay(20000).then(() => {
return waitForBitcoindRpcApi()
})
}
}
}
module.exports = RpcClient
module.exports = {
createRpcClient,
isConnectionError,
waitForBitcoindRpcApi
}
......@@ -9,7 +9,7 @@ const LRU = require('lru-cache')
const errors = require('../errors')
const Logger = require('../logger')
const util = require('../util')
const RpcClient = require('./rpc-client')
const { createRpcClient } = require('./rpc-client')
const rpcLatestBlock = require('./latest-block')
......@@ -34,7 +34,7 @@ class Transactions {
// Initialize the rpc client
this.rpcClient = new RpcClient()
this.rpcClient = createRpcClient()
}
/**
......@@ -47,8 +47,11 @@ class Transactions {
try {
const rpcCalls = txids.map(txid => {
return {
'method': 'getrawtransaction',
'params': [txid, true]
method: 'getrawtransaction',
params: {
txid,
verbose: true
}
}
})
......@@ -77,7 +80,7 @@ class Transactions {
*/
async getTransaction(txid, fees) {
try {
const tx = await this.rpcClient.getrawtransaction(txid, true)
const tx = await this.rpcClient.getrawtransaction({ txid, verbose: true })
return this._prepareTxResult(tx, fees)
} catch(e) {
Logger.error(e, 'Bitcoind RPC : Transaction.getTransaction()')
......@@ -177,7 +180,7 @@ class Transactions {
if (this.prevCache.has(inTxid)) {
ptx = this.prevCache.get(inTxid)
} else {
ptx = await this.rpcClient.getrawtransaction(inTxid, true)
ptx = await this.rpcClient.getrawtransaction({ txid: inTxid, verbose: true })
this.prevCache.set(inTxid, ptx)
}
......
......@@ -5,7 +5,7 @@
'use strict'
const bitcoin = require('bitcoinjs-lib')
const RpcClient = require('../bitcoind-rpc/rpc-client')
const { createRpcClient } = require('../bitcoind-rpc/rpc-client')
const rpcLatestBlock = require('../bitcoind-rpc/latest-block')
const Logger = require('../logger')
const addrHelper = require('../bitcoin/addresses-helper')
......@@ -25,7 +25,7 @@ class BitcoindWrapper extends Wrapper {
constructor() {
super(null, null)
// RPC client
this.client = new RpcClient()
this.client = createRpcClient()
}
/**
......@@ -35,7 +35,7 @@ class BitcoindWrapper extends Wrapper {
* @returns {Promise}
*/
async _get(descriptors) {
return this.client.cmd('scantxoutset', 'start', descriptors)
return await this.client.scantxoutset({ action: 'start', scanobjects: descriptors })
}
/**
......
This diff is collapsed.
......@@ -8,7 +8,7 @@
const Logger = require('../lib/logger')
const db = require('../lib/db/mysql-db-wrapper')
const RpcClient = require('../lib/bitcoind-rpc/rpc-client')
const { waitForBitcoindRpcApi } = require('../lib/bitcoind-rpc/rpc-client')
const network = require('../lib/bitcoin/network')
const keys = require('../keys')[network.key]
const Orchestrator = require('./orchestrator')
......@@ -23,7 +23,7 @@
// Wait for Bitcoind RPC API
// being ready to process requests
await RpcClient.waitForBitcoindRpcApi()
await waitForBitcoindRpcApi()
// Initialize the db wrapper
const dbConfig = {
......
......@@ -8,7 +8,7 @@
const Logger = require('../lib/logger')
const db = require('../lib/db/mysql-db-wrapper')
const RpcClient = require('../lib/bitcoind-rpc/rpc-client')
const { waitForBitcoindRpcApi } = require('../lib/bitcoind-rpc/rpc-client')
const network = require('../lib/bitcoin/network')
const keys = require('../keys')[network.key]
const HttpServer = require('../lib/http-server/http-server')
......@@ -24,7 +24,7 @@
// Wait for Bitcoind RPC API
// being ready to process requests
await RpcClient.waitForBitcoindRpcApi()
await waitForBitcoindRpcApi()
// Initialize the db wrapper
const dbConfig = {
......
......@@ -8,7 +8,7 @@ const zmq = require('zeromq')
const Sema = require('async-sema')
const Logger = require('../lib/logger')
const db = require('../lib/db/mysql-db-wrapper')
const RpcClient = require('../lib/bitcoind-rpc/rpc-client')
const { createRpcClient, isConnectionError } = require('../lib/bitcoind-rpc/rpc-client')
const network = require('../lib/bitcoin/network')
const keys = require('../keys')[network.key]
const pushTxProcessor = require('./pushtx-processor')
......@@ -24,7 +24,7 @@ class Orchestrator {
*/
constructor() {
// RPC client
this.rpcClient = new RpcClient()
this.rpcClient = createRpcClient()
// ZeroMQ socket for bitcoind blocks messages
this.blkSock = null
// Initialize a semaphor protecting the onBlockHash() method
......@@ -77,7 +77,7 @@ class Orchestrator {
// Retrieve the block height
const blockHash = buf.toString('hex')
const header = await this.rpcClient.getblockheader(blockHash, true)
const header = await this.rpcClient.getblockheader({ blockhash: blockHash, verbose: true })
const height = header.height
Logger.info(`Orchestrator : Block ${height} ${blockHash}`)
......@@ -100,7 +100,7 @@ class Orchestrator {
// Check if previous transaction has been confirmed
if (hasParentTx) {
try {
parentTx = await this.rpcClient.getrawtransaction(tx.schParentTxid, true)
parentTx = await this.rpcClient.getrawtransaction({ txid: tx.schParentTxid, verbose: true })
} catch(e) {
Logger.error(e, 'Orchestrator : Transaction.getTransaction()')
}
......@@ -116,7 +116,7 @@ class Orchestrator {
Logger.error(e, `Orchestrator : Orchestrator.onBlockHash() : ${msg}`)
// Check if it's an issue with the connection to the RPC API
// (=> immediately stop the loop)
if (RpcClient.isConnectionError(e)) {
if (isConnectionError(e)) {
Logger.info('Orchestrator : Connection issue')
rpcConnOk = false
break
......
......@@ -9,7 +9,7 @@ const zmq = require('zeromq')
const Logger = require('../lib/logger')
const errors = require('../lib/errors')
const db = require('../lib/db/mysql-db-wrapper')
const RpcClient = require('../lib/bitcoind-rpc/rpc-client')
const { createRpcClient } = require('../lib/bitcoind-rpc/rpc-client')
const addrHelper = require('../lib/bitcoin/addresses-helper')
const network = require('../lib/bitcoin/network')
const activeNet = network.network
......@@ -37,7 +37,7 @@ class PushTxProcessor {
this.notifSock = null
this.sources = new Sources()
// Initialize the rpc client
this.rpcClient = new RpcClient()
this.rpcClient = createRpcClient()
}
/**
......@@ -109,7 +109,7 @@ class PushTxProcessor {
// At this point, the raw hex parses as a legitimate transaction.
// Attempt to send via RPC to the bitcoind instance
try {
const txid = await this.rpcClient.sendrawtransaction(rawtx)
const txid = await this.rpcClient.sendrawtransaction({ hexstring: rawtx })
Logger.info('PushTx : Pushed!')
// Update the stats
status.updateStats(value)
......
......@@ -10,7 +10,7 @@ const Logger = require('../lib/logger')
const db = require('../lib/db/mysql-db-wrapper')
const network = require('../lib/bitcoin/network')
const keys = require('../keys')[network.key]
const RpcClient = require('../lib/bitcoind-rpc/rpc-client')
const { createRpcClient } = require('../lib/bitcoind-rpc/rpc-client')
/**
......@@ -49,7 +49,7 @@ class Status {
amount: 0,
count: 0
}
this.rpcClient = new RpcClient()
this.rpcClient = createRpcClient()
}
/**
......@@ -106,7 +106,7 @@ class Status {
* Refresh network info
*/
async _refreshNetworkInfo() {
const info = await this.rpcClient.getNetworkInfo()
const info = await this.rpcClient.getnetworkinfo()
this.status.bitcoind.conn = info.connections
this.status.bitcoind.version = info.version
this.status.bitcoind.protocolversion = info.protocolversion
......@@ -117,9 +117,9 @@ class Status {
* Refresh blockchain info
*/
async _refreshBlockchainInfo() {
const info = await this.rpcClient.getBlockchainInfo()
const info = await this.rpcClient.getblockchaininfo()
this.status.bitcoind.blocks = info.blocks
this.status.bitcoind.testnet = (info.chain != 'main')
this.status.bitcoind.testnet = (info.chain !== 'main')
this.status.bitcoind.up = true
}
......
......@@ -10,7 +10,7 @@ const errors = require('../lib/errors')
const db = require('../lib/db/mysql-db-wrapper')
const network = require('../lib/bitcoin/network')
const keys = require('../keys')[network.key]
const RpcClient = require('../lib/bitcoind-rpc/rpc-client')
const { createRpcClient } = require('../lib/bitcoind-rpc/rpc-client')
const pushTxProcessor = require('./pushtx-processor')
......@@ -23,7 +23,7 @@ class TransactionsScheduler {
* Constructor
*/
constructor() {
this.rpcClient = new RpcClient()
this.rpcClient = createRpcClient()
}
/**
......@@ -41,7 +41,7 @@ class TransactionsScheduler {
script.sort((a,b) => a.hop - b.hop || a.nlocktime - b.nlocktime)
// Get the height of last block seen
const info = await this.rpcClient.getBlockchainInfo()
const info = await this.rpcClient.getblockchaininfo()
const lastHeight = info.blocks
// Get the nLockTime associated to the first transaction
......
......@@ -9,7 +9,7 @@ const Logger = require('../lib/logger')
const util = require('../lib/util')
const db = require('../lib/db/mysql-db-wrapper')
const network = require('../lib/bitcoin/network')
const RpcClient = require('../lib/bitcoind-rpc/rpc-client')
const { createRpcClient } = require('../lib/bitcoind-rpc/rpc-client')
const keys = require('../keys')[network.key]
......@@ -19,7 +19,7 @@ const keys = require('../keys')[network.key]
*/
// RPC Client requests data from bitcoind
let client = new RpcClient()
let client = createRpcClient()
// Database id of the previous block
let prevID = null;
......@@ -28,10 +28,10 @@ let prevID = null;
async function processBlock(height) {
Logger.info('Start processing block ' + height)
const blockHash = await client.getblockhash(height)
const blockHash = await client.getblockhash({ height })
if (blockHash) {
const header = await client.getblockheader(blockHash, true)
const header = await client.getblockheader({ blockhash: blockHash, verbose: true })
if (header) {
const dbBlock = {
......
......@@ -8,7 +8,7 @@ const { isMainThread, parentPort } = require('worker_threads')
const network = require('../lib/bitcoin/network')
const keys = require('../keys')[network.key]
const db = require('../lib/db/mysql-db-wrapper')
const RpcClient = require('../lib/bitcoind-rpc/rpc-client')
const { createRpcClient } = require('../lib/bitcoind-rpc/rpc-client')
const Block = require('./block')
......@@ -104,7 +104,7 @@ async function processMessage(msg) {
*/
async function initBlock(header) {
status = INITIALIZED
const hex = await rpcClient.getblock(header.hash, false)
const hex = await rpcClient.getblock({ blockhash: header.hash, verbosity: 0 })
block = new Block(hex, header)
return true
}
......@@ -153,7 +153,7 @@ function reset() {
/**
* MAIN
*/
const rpcClient = new RpcClient()
const rpcClient = createRpcClient()
let block = null
let txsForBroadcast = []
let status = IDLE
......
......@@ -11,7 +11,7 @@ const util = require('../lib/util')