You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
173 lines
3.6 KiB
173 lines
3.6 KiB
/*!
|
|
* tracker/block-worker.js
|
|
* Copyright © 2019 – Katana Cryptographic Ltd. All Rights Reserved.
|
|
*/
|
|
'use strict'
|
|
|
|
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 Block = require('./block')
|
|
|
|
|
|
/**
|
|
* STATUS
|
|
*/
|
|
const IDLE = 0
|
|
module.exports.IDLE = IDLE
|
|
|
|
const INITIALIZED = 1
|
|
module.exports.INITIALIZED = INITIALIZED
|
|
|
|
const OUTPUTS_PROCESSED = 2
|
|
module.exports.OUTPUTS_PROCESSED = OUTPUTS_PROCESSED
|
|
|
|
const INPUTS_PROCESSED = 3
|
|
module.exports.INPUTS_PROCESSED = INPUTS_PROCESSED
|
|
|
|
const TXS_CONFIRMED = 4
|
|
module.exports.TXS_CONFIRMED = TXS_CONFIRMED
|
|
|
|
/**
|
|
* OPS
|
|
*/
|
|
const OP_INIT = 0
|
|
module.exports.OP_INIT = OP_INIT
|
|
|
|
const OP_PROCESS_OUTPUTS = 1
|
|
module.exports.OP_PROCESS_OUTPUTS = OP_PROCESS_OUTPUTS
|
|
|
|
const OP_PROCESS_INPUTS = 2
|
|
module.exports.OP_PROCESS_INPUTS = OP_PROCESS_INPUTS
|
|
|
|
const OP_CONFIRM = 3
|
|
module.exports.OP_CONFIRM = OP_CONFIRM
|
|
|
|
const OP_RESET = 4
|
|
module.exports.OP_RESET = OP_RESET
|
|
|
|
|
|
|
|
/**
|
|
* Process message received by the worker
|
|
* @param {object} msg - message received by the worker
|
|
*/
|
|
async function processMessage(msg) {
|
|
let res = null
|
|
let success = true
|
|
|
|
try {
|
|
switch(msg.op) {
|
|
case OP_INIT:
|
|
if (status != IDLE)
|
|
throw 'Operation not allowed'
|
|
res = await initBlock(msg.header)
|
|
break
|
|
case OP_PROCESS_OUTPUTS:
|
|
if (status != INITIALIZED)
|
|
throw 'Operation not allowed'
|
|
res = await processOutputs()
|
|
break
|
|
case OP_PROCESS_INPUTS:
|
|
if (status != OUTPUTS_PROCESSED)
|
|
throw 'Operation not allowed'
|
|
res = await processInputs()
|
|
break
|
|
case OP_CONFIRM:
|
|
if (status != INPUTS_PROCESSED)
|
|
throw 'Operation not allowed'
|
|
res = await confirmTransactions(msg.blockId)
|
|
break
|
|
case OP_RESET:
|
|
res = await reset()
|
|
break
|
|
default:
|
|
throw 'Invalid Operation'
|
|
}
|
|
} catch (e) {
|
|
success = false
|
|
res = e
|
|
} finally {
|
|
parentPort.postMessage({
|
|
'op': msg.op,
|
|
'status': success,
|
|
'res': res
|
|
})
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Initialize the block
|
|
* @param {object} header - block header
|
|
*/
|
|
async function initBlock(header) {
|
|
status = INITIALIZED
|
|
const hex = await rpcClient.getblock(header.hash, false)
|
|
block = new Block(hex, header)
|
|
return true
|
|
}
|
|
|
|
/**
|
|
* Process the transactions outputs
|
|
*/
|
|
async function processOutputs() {
|
|
status = OUTPUTS_PROCESSED
|
|
txsForBroadcast = await block.processOutputs()
|
|
return true
|
|
}
|
|
|
|
/**
|
|
* Process the transactions inputs
|
|
*/
|
|
async function processInputs() {
|
|
status = INPUTS_PROCESSED
|
|
const txs = await block.processInputs()
|
|
txsForBroadcast = txsForBroadcast.concat(txs)
|
|
return true
|
|
}
|
|
|
|
/**
|
|
* Confirm the transactions
|
|
* @param {integer} blockId - id of the block in db
|
|
*/
|
|
async function confirmTransactions(blockId) {
|
|
status = TXS_CONFIRMED
|
|
const aTxsForBroadcast = [...new Set(txsForBroadcast)]
|
|
await block.confirmTransactions(aTxsForBroadcast, blockId)
|
|
return aTxsForBroadcast
|
|
}
|
|
|
|
/**
|
|
* Reset
|
|
*/
|
|
function reset() {
|
|
status = IDLE
|
|
block = null
|
|
txsForBroadcast = []
|
|
return true
|
|
}
|
|
|
|
|
|
/**
|
|
* MAIN
|
|
*/
|
|
const rpcClient = new RpcClient()
|
|
let block = null
|
|
let txsForBroadcast = []
|
|
let status = IDLE
|
|
|
|
if (!isMainThread) {
|
|
db.connect({
|
|
connectionLimit: keys.db.connectionLimitTracker,
|
|
acquireTimeout: keys.db.acquireTimeout,
|
|
host: keys.db.host,
|
|
user: keys.db.user,
|
|
password: keys.db.pass,
|
|
database: keys.db.database
|
|
})
|
|
|
|
reset()
|
|
parentPort.on('message', processMessage)
|
|
}
|
|
|