fix(GET /encryption/publickey): Search blockchain for a public key associated with an address

This commit is contained in:
Chris Troutner
2020-05-03 15:37:46 -07:00
parent 72ef95abe6
commit f44229afe3
7 changed files with 255 additions and 4 deletions
+3
View File
@@ -38,6 +38,7 @@ const xpubV3 = require('./routes/v3/xpub')
const BlockbookV3 = require('./routes/v3/blockbook')
const Ninsight = require('./routes/v3/ninsight')
const ElectrumXV3 = require('./routes/v3/electrumx')
const EncryptionV3 = require('./routes/v3/encryption')
require('dotenv').config()
@@ -50,6 +51,7 @@ const slpV3 = new SlpV3()
const blockbookV3 = new BlockbookV3()
const electrumxv3 = new ElectrumXV3()
electrumxv3.connect()
const encryptionv3 = new EncryptionV3()
const app = express()
@@ -118,6 +120,7 @@ app.use(`/${v3prefix}/` + 'slp', slpV3.router)
app.use(`/${v3prefix}/` + 'xpub', xpubV3.router)
app.use(`/${v3prefix}/` + 'blockbook', blockbookV3.router)
app.use(`/${v3prefix}/` + 'electrumx', electrumxv3.router)
app.use(`/${v3prefix}/` + 'encryption', encryptionv3.router)
const ninsight = new Ninsight()
app.use(`/${v3prefix}/` + 'ninsight', ninsight.router)
+118 -1
View File
@@ -18,6 +18,14 @@ const routeUtils = new RouteUtils()
const BCHJS = require('@chris.troutner/bch-js')
const bchjs = new BCHJS()
// Use Blockbook for getting indexer data.
const Blockbook = require('./blockbook')
const blockbook = new Blockbook()
// Use RawTransactions library for getting raw blockchain data.
const RawTransactions = require('./full-node/rawtransactions')
const rawTransactions = new RawTransactions()
let _this
class Encryption {
@@ -28,10 +36,12 @@ class Encryption {
_this.axios = axios
_this.routeUtils = routeUtils
_this.bchjs = bchjs
_this.blockbook = blockbook
_this.rawTransactions = rawTransactions
_this.router = router
_this.router.get('/', _this.root)
// _this.router.get('/publickey', _this.getPublicKey)
_this.router.get('/publickey/:address', _this.getPublicKey)
}
// DRY error handler.
@@ -60,6 +70,113 @@ class Encryption {
root (req, res, next) {
return res.json({ status: 'encryption' })
}
/**
* @api {get} /encryption/publickey/{addr} Get public key for a BCH address.
* @apiName Get encryption key for bch address
* @apiGroup Encryption
* @apiDescription Searches the blockchain for a public key associated with a BCH address.
*
*
* @apiExample Example usage:
* curl -X GET "https://api.fullstack.cash/v3/encryption/publickey/bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf" -H "accept: application/json"
*
*/
async getPublicKey (req, res, next) {
try {
const address = req.params.address
// Reject if address is an array.
if (Array.isArray(address)) {
res.status(400)
return res.json({
success: false,
error: 'address can not be an array.'
})
}
const cashAddr = _this.bchjs.Address.toCashAddress(address)
// Prevent a common user error. Ensure they are using the correct network address.
const networkIsValid = _this.routeUtils.validateNetwork(cashAddr)
if (!networkIsValid) {
res.status(400)
return res.json({
success: false,
error:
'Invalid network. Trying to use a testnet address on mainnet, or vice versa.'
})
}
wlogger.debug(
'Executing encryption/getPublicKey with this address: ',
cashAddr
)
// Retrieve the transaction history for this address.
const balance = await _this.blockbook.balanceFromBlockbook(cashAddr)
// console.log(`balance: ${JSON.stringify(balance, null, 2)}`)
const txHistory = balance.txids
// console.log(`txHistory: ${JSON.stringify(txHistory, null, 2)}`)
if (txHistory.length === 0) {
throw new Error('No transaction history.')
}
// Loop through the transaction history and search for the public key.
for (let i = 0; i < txHistory.length; i++) {
const thisTx = txHistory[i]
const txDetails = await _this.rawTransactions.getRawTransactionsFromNode(
thisTx,
true
)
// console.log(`txDetails: ${JSON.stringify(txDetails, null, 2)}`)
const vin = txDetails.vin
// Loop through each input.
for (let j = 0; j < vin.length; j++) {
const thisVin = vin[j]
// console.log(`thisVin: ${JSON.stringify(thisVin, null, 2)}`)
// Extract the script signature.
const scriptSig = thisVin.scriptSig.asm.split(' ')
// console.log(`scriptSig: ${JSON.stringify(scriptSig, null, 2)}`)
// Extract the public key from the script signature.
const pubKey = scriptSig[scriptSig.length - 1]
// console.log(`pubKey: ${pubKey}`)
// Generate cash address from public key.
const keyBuf = Buffer.from(pubKey, 'hex')
const ec = _this.bchjs.ECPair.fromPublicKey(keyBuf)
const cashAddr2 = _this.bchjs.ECPair.toCashAddress(ec)
// console.log(`cashAddr2: ${cashAddr2}`)
// If public keys match, this is the correct public key.
if (cashAddr === cashAddr2) {
res.status(200)
return res.json({
success: true,
publicKey: pubKey
})
}
}
}
res.status(200)
return res.json({
success: false,
publicKey: 'not found'
})
} catch (err) {
wlogger.error('Error in encryption.js/getPublicKey().', err)
return _this.errorHandler(err, res)
}
}
}
module.exports = Encryption
+1 -1
View File
@@ -48,7 +48,7 @@ var wlogger = winston.createLogger({
wlogger.add(
new winston.transports.Console({
format: winston.format.simple(),
level: "info"
level: 'info'
})
)
*/