Unverified Commit a1fa5309 authored by kenshin samourai's avatar kenshin samourai Committed by GitHub
Browse files

Merge pull request #165 from Samourai-Wallet/develop

merge develop into master for v1.6.0
parents 8c812e00 f6a5f7d3
......@@ -3,6 +3,7 @@
## Releases ##
- [v1.6.0](#1_6_0)
- [v1.5.0](#1_5_0)
- [v1.4.1](#1_4_1)
- [v1.4.0](#1_4_0)
......@@ -11,6 +12,110 @@
- [v1.1.0](#1_1_0)
<a name="1_6_0"/>
## Samourai Dojo v1.6.0 ##
### Notable changes ###
#### Whirlpool CLI ####
This version of Dojo introduces the support of an optional Whirlpool client ([whirlpool-client-cli](https://code.samourai.io/whirlpool/whirlpool-client-cli)) running inside MyDojo.
This option provides several benefits:
- all communications between the Whirlpool client and Dojo's API are internal to Docker,
- Whirlpool client exposes its API as a Tor hidden service. All communications between Whirlpool GUI and the Whirlpool client are moade over Tor.
See this [documentation](https://github.com/Samourai-Wallet/samourai-dojo/blob/master/doc/DOCKER_advanced_setups.md#local_whirlpool) for the detailed procedure allowing to configure and install the Whirlpool client.
#### Unified logs system ####
Starting with this version, logs of all containers are managed with the log system provided by Docker.
Logs of all NodeJS submodules (API, Tracker, PushTx, PushTx Orchestrator) are merged into a single stream.
The -d option of `dojo.sh logs` command is deprecated.
See this [documentation](https://github.com/Samourai-Wallet/samourai-dojo/blob/master/doc/DOCKER_setup.md#shell_script) for a list of logs available through the `dojo.sh` command.
#### Upgrade of bitcoind to v0.20.0 ####
Upgrade to Bitcoin Core v0.20.0
#### Upgrade of Tor to v0.4.2.7 ####
Upgrade to [Tor](https://www.torproject.org/) v0.4.2.7
#### Upgrade of BTC RPC Explorer to v2.0.0 ####
Upgrade to [btc-rpc-explorer](https://github.com/janoside/btc-rpc-explorer) v2.0.0
#### Upgrade of addrindexrs to v0.3.0 ####
Upgrade to [addrindexrs](https://github.com/Samourai-Wallet/addrindexrs) v0.3.0
### Change log ###
#### MyDojo ####
- [#128](https://github.com/Samourai-Wallet/samourai-dojo/pull/128) drop unneeded reversebuffer util method
- [#142](https://github.com/Samourai-Wallet/samourai-dojo/pull/142) modify results returned by dojo.sh onion
- [#143](https://github.com/Samourai-Wallet/samourai-dojo/pull/143) improve display of dojo version
- [#144](https://github.com/Samourai-Wallet/samourai-dojo/pull/144) add dynamic switch of startup mode
- [#147](https://github.com/Samourai-Wallet/samourai-dojo/pull/147) increase control over ports exposed by dojo
- [#148](https://github.com/Samourai-Wallet/samourai-dojo/pull/148) upgrade explorer to btc-rpc-explorer 2.0.0
- [#149](https://github.com/Samourai-Wallet/samourai-dojo/pull/149) upgrade tor to v0.4.2.7
- [#152](https://github.com/Samourai-Wallet/samourai-dojo/pull/152) add new optional whirlpool container
- [#154](https://github.com/Samourai-Wallet/samourai-dojo/pull/154) manage all logs with docker log system
- [#156](https://github.com/Samourai-Wallet/samourai-dojo/pull/156) upgrade indexer to addrindexrs v0.2.0
- [#157](https://github.com/Samourai-Wallet/samourai-dojo/pull/157) clean-up of log files
- [#158](https://github.com/Samourai-Wallet/samourai-dojo/pull/158) misc improvements in bitcoind rpc transactions class
- [#159](https://github.com/Samourai-Wallet/samourai-dojo/pull/159) upgrade indexer to rust 1.42.0 slim buster
- [#160](https://github.com/Samourai-Wallet/samourai-dojo/pull/160) upgrade bitcoind to bitcoin core 0.20.0
- [#mr141](https://code.samourai.io/dojo/samourai-dojo/-/merge_requests/141) added more header to allow proper cors
- [#163](https://github.com/Samourai-Wallet/samourai-dojo/pull/163) upgrade indexer to addrindexrs 0.3.0
- [#164](https://github.com/Samourai-Wallet/samourai-dojo/pull/164) upgrade whirlpool to whirlpool-cli 0.10.6
#### Bug fixes ####
- [4ee1f66](https://github.com/Samourai-Wallet/samourai-dojo/commit/4ee1f666b04f5096eae021f2ffb8b94d7323b7da) fix dojo version in index-example.js
- [37c4ac6](https://github.com/Samourai-Wallet/samourai-dojo/commit/37c4ac65d50ea849625c20a53fe260af386cc2f5) add missing quote breaking pushtx-rest-api.js script
- [#150](https://github.com/Samourai-Wallet/samourai-dojo/pull/150) define a floor for tracker normal mode
- [#153](https://github.com/Samourai-Wallet/samourai-dojo/pull/153) fix typo in install scripts causing a copy error when installing or upgrading
- [#155](https://github.com/Samourai-Wallet/samourai-dojo/pull/155) fix typo: laucnhed -> launched
- [#161](https://github.com/Samourai-Wallet/samourai-dojo/pull/161) trap docker & bash messages displayed on dojo.sh stop
- [#162](https://github.com/Samourai-Wallet/samourai-dojo/pull/162) fix path of sha256sums.asc
#### Documentation ####
- [#139](https://github.com/Samourai-Wallet/samourai-dojo/pull/139) update synology documentation
- [#146](https://github.com/Samourai-Wallet/samourai-dojo/pull/146) fix misleading docs for post_pushtx
#### Credits ###
- anwfr
- BTCxZelko
- dergigi
- kenshin-samourai
- LaurentMT
- lukechilds
- mikispag
- pajasevi
- zeroleak
<a name="1_5_0"/>
## Samourai Dojo v1.5.0 ##
......
......@@ -137,7 +137,7 @@ class ApiHelper {
HttpServer.sendError(res, errors.body.INVDATA)
Logger.error(
params,
`ApiHelper.validateEntitiesParams() : Invalid arguments`
`API : ApiHelper.validateEntitiesParams() : Invalid arguments`
)
}
}
......
......@@ -46,7 +46,7 @@ class FeesRestApi {
} catch (e) {
HttpServer.sendError(res, e)
} finally {
debugApi && Logger.info(`Completed GET /fees`)
debugApi && Logger.info(`API : Completed GET /fees`)
}
}
......
......@@ -49,7 +49,7 @@ class HeadersRestApi {
} catch(e) {
HttpServer.sendError(res, e)
} finally {
debugApi && Logger.info(`Completed GET /header/${req.params.hash}`)
debugApi && Logger.info(`API : Completed GET /header/${req.params.hash}`)
}
}
......@@ -66,7 +66,7 @@ class HeadersRestApi {
HttpServer.sendError(res, errors.body.INVDATA)
Logger.error(
req.params.hash,
'HeadersRestApi.validateArgsGetHeader() : Invalid hash'
'API : HeadersRestApi.validateArgsGetHeader() : Invalid hash'
)
} else {
next()
......
......@@ -20,15 +20,15 @@ if (cluster.isMaster) {
})
cluster.on('listening', function(worker) {
Logger.info(`Cluster ${worker.process.pid} connected`)
Logger.info(`API : Cluster ${worker.process.pid} connected`)
})
cluster.on('disconnect', function(worker) {
Logger.info(`Cluster ${worker.process.pid} disconnected`)
Logger.info(`API : Cluster ${worker.process.pid} disconnected`)
})
cluster.on('exit', function(worker) {
Logger.info(`Cluster ${worker.process.pid} is dead`)
Logger.info(`API : Cluster ${worker.process.pid} is dead`)
// Ensuring a new cluster will start if an old one dies
cluster.fork()
})
......
......@@ -28,8 +28,8 @@
/**
* Samourai REST API
*/
Logger.info('Process ID: ' + process.pid)
Logger.info('Preparing the REST API')
Logger.info('API : Process ID: ' + process.pid)
Logger.info('API : Preparing the REST API')
// Wait for Bitcoind RPC API
// being ready to process requests
......@@ -52,8 +52,9 @@
hdaHelper.activateExternalDerivation()
// Initialize the http server
const host = keys.apiBind
const port = keys.ports.account
const httpServer = new HttpServer(port)
const httpServer = new HttpServer(port, host)
// Initialize the rest api endpoints
const authRestApi = new AuthRestApi(httpServer)
......
......@@ -85,7 +85,7 @@ class MultiaddrRestApi {
${req.query.bip49 ? req.query.bip49 : ''} \
${req.query.bip84 ? req.query.bip84 : ''}`
Logger.info(`Completed GET /multiaddr ${strParams}`)
Logger.info(`API : Completed GET /multiaddr ${strParams}`)
}
}
}
......@@ -126,7 +126,7 @@ class MultiaddrRestApi {
${req.body.bip49 ? req.body.bip49 : ''} \
${req.body.bip84 ? req.body.bip84 : ''}`
Logger.info(`Completed POST /multiaddr ${strParams}`)
Logger.info(`API : Completed POST /multiaddr ${strParams}`)
}
}
}
......
......@@ -61,7 +61,7 @@ class NotificationsServer {
const header = JSON.parse(message.toString())
this.notifService.notifyBlock(header)
} catch(e) {
Logger.error(e, 'NotificationServer._initTrackerSocket() : Error in block message')
Logger.error(e, 'API : NotificationServer._initTrackerSocket() : Error in block message')
}
break
case 'transaction':
......@@ -69,11 +69,11 @@ class NotificationsServer {
const tx = JSON.parse(message.toString())
this.notifService.notifyTransaction(tx)
} catch(e) {
Logger.error(e, 'NotificationServer._initTrackerSocket() : Error in transaction message')
Logger.error(e, 'API : NotificationServer._initTrackerSocket() : Error in transaction message')
}
break
default:
Logger.info(`Unknown ZMQ message topic: "${topic}"`)
Logger.info(`API : Unknown ZMQ message topic: "${topic}"`)
}
})
}
......
......@@ -59,7 +59,7 @@ class NotificationsService {
_initWSServer(server) {
this.ws = new WebSocket.server({httpServer: server})
Logger.info('Created WebSocket server')
Logger.info('API : Created WebSocket server')
this.ws.on('request', req => {
try {
......@@ -67,14 +67,14 @@ class NotificationsService {
conn.id = status.sessions++
conn.subs = []
debug && Logger.info(`Client ${conn.id} connected`)
debug && Logger.info(`API : Client ${conn.id} connected`)
conn.on('close', () => {
this._closeWSConnection(conn, false)
})
conn.on('error', err => {
Logger.error(err, `NotificationsService : Error on connection ${conn.id}`)
Logger.error(err, `API : NotificationsService : Error on connection ${conn.id}`)
if (conn.connected)
this._closeWSConnection(conn, true)
})
......@@ -91,7 +91,7 @@ class NotificationsService {
status.maxConn = Math.max(status.maxConn, Object.keys(this.conn).length)
} catch(e) {
Logger.error(e, `NotificationsService._initWSServer() : Error during request accept`)
Logger.error(e, `API : NotificationsService._initWSServer() : Error during request accept`)
}
})
}
......@@ -120,10 +120,10 @@ class NotificationsService {
if (forcedClose && conn.connected)
conn.drop(1008, 'Get out of here!')
debug && Logger.info(`Client ${conn.id} disconnected`)
debug && Logger.info(`API : Client ${conn.id} disconnected`)
} catch(e) {
Logger.error(e, 'NotificationsService._closeWSConnection()')
Logger.error(e, 'API : NotificationsService._closeWSConnection()')
}
}
......@@ -134,7 +134,7 @@ class NotificationsService {
*/
_filterWSMessage(msg) {
if (this.cacheSubs.has(msg)) {
debug && Logger.info('Duplicate subscriptions detected')
debug && Logger.info('API : Duplicate subscriptions detected')
return false
} else {
this.cacheSubs.set(msg, true)
......@@ -150,7 +150,7 @@ class NotificationsService {
*/
_handleWSMessage(msg, conn) {
try {
debug && Logger.info(`Received from client ${conn.id}: ${msg}`)
debug && Logger.info(`API : Received from client ${conn.id}: ${msg}`)
const data = JSON.parse(msg)
......@@ -183,7 +183,7 @@ class NotificationsService {
break
}
} catch(e) {
Logger.error(e, 'NotificationsService._handleWSMessage() : WebSocket message error')
Logger.error(e, 'API : NotificationsService._handleWSMessage() : WebSocket message error')
}
}
......@@ -223,7 +223,7 @@ class NotificationsService {
this.subs[topic].push(conn.id)
debug && Logger.info(`Client ${conn.id} subscribed to ${topic}`)
debug && Logger.info(`API : Client ${conn.id} subscribed to ${topic}`)
}
/**
......@@ -267,7 +267,7 @@ class NotificationsService {
try {
this.conn[cid].sendUTF(msg)
} catch(e) {
Logger.error(e, `NotificationsService.dispatch() : Error sending dispatch for ${topic} to client ${cid}`)
Logger.error(e, `API : NotificationsService.dispatch() : Error sending dispatch for ${topic} to client ${cid}`)
}
}
}
......@@ -284,7 +284,7 @@ class NotificationsService {
}
this.dispatch('block', JSON.stringify(data))
} catch(e) {
Logger.error(e, `NotificationsService.notifyBlock()`)
Logger.error(e, `API : NotificationsService.notifyBlock()`)
}
}
......@@ -440,14 +440,14 @@ class NotificationsService {
try {
this.conn[cid].sendUTF(JSON.stringify(data))
debug && Logger.error(`Sent ctx ${ctx.hash} to client ${cid}`)
debug && Logger.error(`API : Sent ctx ${ctx.hash} to client ${cid}`)
} catch(e) {
Logger.error(e, `NotificationsService.notifyTransaction() : Trouble sending ctx to client ${cid}`)
Logger.error(e, `API : NotificationsService.notifyTransaction() : Trouble sending ctx to client ${cid}`)
}
}
} catch(e) {
Logger.error(e, `NotificationsService.notifyTransaction()`)
Logger.error(e, `API : NotificationsService.notifyTransaction()`)
}
}
......@@ -464,9 +464,9 @@ class NotificationsService {
try {
this.conn[cid].sendUTF(JSON.stringify(data))
debug && Logger.error(`Sent authentication error to client ${cid}`)
debug && Logger.error(`API : Sent authentication error to client ${cid}`)
} catch(e) {
Logger.error(e, `NotificationsService.notifyAuthError() : Trouble sending authentication error to client ${cid}`)
Logger.error(e, `API : NotificationsService.notifyAuthError() : Trouble sending authentication error to client ${cid}`)
}
}
......
......@@ -47,7 +47,7 @@ class StatusRestApi {
} catch(e) {
HttpServer.sendError(res, e)
} finally {
debugApi && Logger.info(`Completed GET /status`)
debugApi && Logger.info(`API : Completed GET /status`)
}
}
......
......@@ -108,7 +108,7 @@ class SupportRestApi {
HttpServer.sendError(res, errors.generic.GEN)
} finally {
debugApi && Logger.info(`Completed GET /support/address/${req.params.addr}/info`)
debugApi && Logger.info(`API : Completed GET /support/address/${req.params.addr}/info`)
}
}
......@@ -175,7 +175,7 @@ class SupportRestApi {
HttpServer.sendError(res, errors.generic.GEN)
} finally {
debugApi && Logger.info(`Completed GET /support/address/${req.params.addr}/rescan`)
debugApi && Logger.info(`API : Completed GET /support/address/${req.params.addr}/rescan`)
}
}
......@@ -212,7 +212,7 @@ class SupportRestApi {
HttpServer.sendError(res, errors.generic.GEN)
} finally {
debugApi && Logger.info(`Completed GET /support/xpub/${req.params.xpub}/info`)
debugApi && Logger.info(`API : Completed GET /support/xpub/${req.params.xpub}/info`)
}
}
......@@ -270,7 +270,7 @@ class SupportRestApi {
HttpServer.sendRawData(res, JSON.stringify(ret, null, 2))
} else {
ret.status = 'Rescan Error'
Logger.error(e, 'SupportRestApi.getXpubRescan() : Support rescan error')
Logger.error(e, 'API : SupportRestApi.getXpubRescan() : Support rescan error')
HttpServer.sendError(res, JSON.stringify(ret, null, 2))
}
}
......@@ -279,7 +279,7 @@ class SupportRestApi {
HttpServer.sendError(res, errors.generic.GEN)
} finally {
debugApi && Logger.info(`Completed GET /support/xpub/${req.params.xpub}/rescan`)
debugApi && Logger.info(`API : Completed GET /support/xpub/${req.params.xpub}/rescan`)
}
}
......@@ -300,10 +300,10 @@ class SupportRestApi {
const ret = {
status: 'error'
}
Logger.error(e, 'SupportRestApi.getPairing() : Support pairing error')
Logger.error(e, 'API : SupportRestApi.getPairing() : Support pairing error')
HttpServer.sendError(res, JSON.stringify(ret, null, 2))
} finally {
debugApi && Logger.info(`Completed GET /pairing`)
debugApi && Logger.info(`API : Completed GET /pairing`)
}
}
......@@ -318,7 +318,7 @@ class SupportRestApi {
url = fs.readFileSync('/var/lib/tor/hsv3explorer/hostname', 'utf8')
url = url.replace('\n', '')
} catch(e) {
Logger.error(e, 'SupportRestApi.getPairing() : Cannot read explorer onion address')
Logger.error(e, 'API : SupportRestApi.getPairing() : Cannot read explorer onion address')
}
}
const ret = {
......@@ -333,10 +333,10 @@ class SupportRestApi {
const ret = {
status: 'error'
}
Logger.error(e, 'SupportRestApi.getPairingExplorer() : Support pairing error')
Logger.error(e, 'API : SupportRestApi.getPairingExplorer() : Support pairing error')
HttpServer.sendError(res, JSON.stringify(ret, null, 2))
} finally {
debugApi && Logger.info(`Completed GET /pairing/explorer`)
debugApi && Logger.info(`API : Completed GET /pairing/explorer`)
}
}
......@@ -351,7 +351,7 @@ class SupportRestApi {
if (!isValidXpub) {
HttpServer.sendError(res, errors.body.INVDATA)
Logger.error(null, `SupportRestApi.validateArgsGetXpubInfo() : Invalid xpub ${req.params.xpub}`)
Logger.error(null, `API : SupportRestApi.validateArgsGetXpubInfo() : Invalid xpub ${req.params.xpub}`)
} else {
next()
}
......@@ -369,7 +369,7 @@ class SupportRestApi {
if (!(isValidXpub && isValidGap)) {
HttpServer.sendError(res, errors.body.INVDATA)
Logger.error(null, 'SupportRestApi.validateArgsGetXpubRescan() : Invalid arguments')
Logger.error(null, 'API : SupportRestApi.validateArgsGetXpubRescan() : Invalid arguments')
} else {
next()
}
......@@ -386,7 +386,7 @@ class SupportRestApi {
if (!isValidAddress) {
HttpServer.sendError(res, errors.body.INVDATA)
Logger.error(null, `SupportRestApi.validateAddress() : Invalid address ${req.params.addr}`)
Logger.error(null, `API : SupportRestApi.validateAddress() : Invalid address ${req.params.addr}`)
} else {
next()
}
......
......@@ -63,7 +63,7 @@ class TransactionsRestApi {
HttpServer.sendError(res, e)
} finally {
const strParams = `${req.query.fees ? req.query.fees : ''}`
debugApi && Logger.info(`Completed GET /tx/${req.params.txid} ${strParams}`)
debugApi && Logger.info(`API : Completed GET /tx/${req.params.txid} ${strParams}`)
}
}
......@@ -97,7 +97,7 @@ class TransactionsRestApi {
${req.query.page ? req.query.page : ''} \
${req.query.count ? req.query.count : ''}`
debugApi && Logger.info(`Completed GET /txs ${strParams}`)
debugApi && Logger.info(`API : Completed GET /txs ${strParams}`)
}
}
......@@ -118,7 +118,7 @@ class TransactionsRestApi {
HttpServer.sendError(res, errors.body.INVDATA)
Logger.error(
req.params,
'HeadersRestApi.validateArgsGetTransaction() : Invalid arguments'
'API : HeadersRestApi.validateArgsGetTransaction() : Invalid arguments'
)
Logger.error(req.query, '')
} else {
......@@ -145,7 +145,7 @@ class TransactionsRestApi {
HttpServer.sendError(res, errors.body.INVDATA)
Logger.error(
req.query,
'HeadersRestApi.validateArgsGetTransactions() : Invalid arguments'
'API : HeadersRestApi.validateArgsGetTransactions() : Invalid arguments'
)
} else {
next()
......
......@@ -85,7 +85,7 @@ class UnspentRestApi {
${req.query.bip49 ? req.query.bip49 : ''} \
${req.query.bip84 ? req.query.bip84 : ''}`
Logger.info(`Completed GET /unspent ${strParams}`)
Logger.info(`API : Completed GET /unspent ${strParams}`)
}
}
}
......@@ -126,7 +126,7 @@ class UnspentRestApi {
${req.body.bip49 ? req.body.bip49 : ''} \
${req.body.bip84 ? req.body.bip84 : ''}`
Logger.info(`Completed POST /unspent ${strParams}`)
Logger.info(`API : Completed POST /unspent ${strParams}`)
}
}
}
......
......@@ -151,7 +151,7 @@ class XPubRestApi {
return HttpServer.sendError(res, errors.generic.GEN)
} finally {
debugApi && Logger.info(`Completed POST /xpub ${req.body.xpub}`)
debugApi && Logger.info(`API : Completed POST /xpub ${req.body.xpub}`)
}
}
......@@ -194,11 +194,11 @@ class XPubRestApi {
HttpServer.sendOkData(res, ret)
} catch(e) {
Logger.error(e, 'XpubRestApi.getXpub()')
Logger.error(e, 'API : XpubRestApi.getXpub()')
HttpServer.sendError(res, e)
} finally {
debugApi && Logger.info(`Completed GET /xpub/${req.params.xpub}`)
debugApi && Logger.info(`API : Completed GET /xpub/${req.params.xpub}`)
}
}
......@@ -253,7 +253,7 @@ class XPubRestApi {
}
} finally {
debugApi && Logger.info(`Completed POST /xpub/${req.params.xpub}/lock`)
debugApi && Logger.info(`API : Completed POST /xpub/${req.params.xpub}/lock`)
}
}
......@@ -303,7 +303,7 @@ class XPubRestApi {
HttpServer.sendError(res, errors.generic.GEN)
} finally {
debugApi && Logger.info(`Completed DELETE /xpub/${req.params.xpub}`)
debugApi && Logger.info(`API : Completed DELETE /xpub/${req.params.xpub}`)
}
}
......@@ -327,8 +327,8 @@ class XPubRestApi {
xpub = hdaHelper.xlatXPUB(origXpub)
scheme = isYpub ? hdaHelper.BIP49 : hdaHelper.BIP84
if (trace) {
Logger.info('Converted: ' + origXpub)
Logger.info('Resulting xpub: ' + xpub)
Logger.info('API : Converted: ' + origXpub)
Logger.info('API : Resulting xpub: ' + xpub)
}
}
......@@ -371,7 +371,7 @@ class XPubRestApi {
HttpServer.sendError(res, errors.body.INVDATA)
Logger.error(
req.body,
'XpubRestApi.validateArgsPostXpub() : Invalid arguments'
'API : XpubRestApi.validateArgsPostXpub() : Invalid arguments'
)
} else {
next()
......@@ -391,7 +391,7 @@ class XPubRestApi {
HttpServer.sendError(res, errors.body.INVDATA)
Logger.error(
req.params.xpub,
'XpubRestApi.validateArgsGetXpub() : Invalid arguments'
'API : XpubRestApi.validateArgsGetXpub() : Invalid arguments'
)
} else {
next()
......@@ -414,7 +414,7 @@ class XPubRestApi {
HttpServer.sendError(res, errors.body.INVDATA)
Logger.error(
req.params,
'XpubRestApi.validateArgsPostLockXpub() : Invalid arguments'
'API : XpubRestApi.validateArgsPostLockXpub() : Invalid arguments'
)
Logger.error(req.body, '')
} else {
......@@ -437,7 +437,7 @@ class XPubRestApi {