Browse Source

add support of strict_mode_vouts to pushtx endpoint

use-env-var-docker
kenshin-samourai 5 years ago
parent
commit
76271c8fcb
  1. 3
      lib/errors.js
  2. 47
      pushtx/pushtx-processor.js
  3. 30
      pushtx/pushtx-rest-api.js

3
lib/errors.js

@ -75,6 +75,7 @@ module.exports = {
pushtx: {
NLOCK_MISMATCH: 'nLockTime in script does not match nLockTime in transaction',
SCHEDULED_TOO_FAR: 'nLockTime is set to far in the future',
SCHEDULED_BAD_ORDER: 'Order of hop and nLockTime values must be consistent'
SCHEDULED_BAD_ORDER: 'Order of hop and nLockTime values must be consistent',
VIOLATION_STRICT_MODE_VOUTS: 'VIOLATION_STRICT_MODE_VOUTS'
}
}

47
pushtx/pushtx-processor.js

@ -8,11 +8,20 @@ const bitcoin = require('bitcoinjs-lib')
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 network = require('../lib/bitcoin/network')
const activeNet = network.network
const keys = require('../keys')[network.key]
const status = require('./status')
let Sources
if (network.key == 'bitcoin') {
Sources = require('../lib/remote-importer/sources-mainnet')
} else {
Sources = require('../lib/remote-importer/sources-testnet')
}
/**
* A singleton providing a wrapper
@ -25,6 +34,7 @@ class PushTxProcessor {
*/
constructor() {
this.notifSock = null
this.sources = new Sources()
// Initialize the rpc client
this.rpcClient = new RpcClient()
}
@ -38,6 +48,43 @@ class PushTxProcessor {
this.notifSock.bindSync(config.uriSocket)
}
/**
* Enforce a strict verification mode on a list of outputs
* @param {string} rawtx - raw bitcoin transaction in hex format
* @param {array} vouts - output indices (integer)
* @returns {array} returns the indices of the faulty outputs
*/
async enforceStrictModeVouts(rawtx, vouts) {
const faultyOutputs = []
const addrMap = {}
let tx
try {
tx = bitcoin.Transaction.fromHex(rawtx)
} catch(e) {
throw errors.tx.PARSE
}
// Check in db if addresses are known and have been used
for (let vout of vouts) {
if (vout >= tx.outs.length)
throw errors.txout.VOUT
const output = tx.outs[vout]
const address = bitcoin.address.fromOutputScript(output.script, activeNet)
const nbTxs = await db.getAddressNbTransactions(address)
if (nbTxs == null || nbTxs > 0)
faultyOutputs.push(vout)
else
addrMap[address] = vout
}
// Checks with indexer if addresses are known and have been used
if (keys.indexer.active != 'local_bitcoind') {
const results = await this.sources.getAddresses(Object.keys(addrMap))
for (let r of results)
if (r.ntx > 0)
faultyOutputs.push(addrMap[r.address])
}
return faultyOutputs
}
/**
* Push transactions to the Bitcoin network
* @param {string} rawtx - raw bitcoin transaction in hex format

30
pushtx/pushtx-rest-api.js

@ -152,6 +152,31 @@ class PushTxRestApi {
if (!validator.isHexadecimal(query.tx))
return this._traceError(res, errors.body.INVDATA)
if (query.strict_mode_vouts) {
const outs = query.strict_mode_vouts.split('|')
if (outs.length > 0) {
let faults
for (let item of outs) {
if (!validator.isInt(item))
return this._traceError(res, errors.body.INVDATA)
}
try {
const indices = outs.map(v => parseInt(v, 10))
faults = await pushTxProcessor.enforceStrictModeVouts(query.tx, indices)
} catch(e) {
this._traceError(res, e)
}
if (faults.length > 0) {
return this._traceError(res, {
'message': JSON.stringify({
'message': faults,
'code': errors.pushtx.VIOLATION_STRICT_MODE_VOUTS
})
})
}
}
}
try {
const txid = await pushTxProcessor.pushTx(query.tx)
HttpServer.sendOkData(res, txid)
@ -198,10 +223,7 @@ class PushTxRestApi {
if (msg.code && msg.message) {
Logger.error(null, 'PushTx : Error ' + msg.code + ': ' + msg.message)
ret = {
message: msg.message,
code: msg.code
}
ret = msg
} else {
Logger.error(err.message, 'PushTx : ')
ret = err.message

Loading…
Cancel
Save